diff --git a/.github/actions/set-up-gh/action.yml b/.github/actions/set-up-gh/action.yml index fc16ce0b2633..4dc3af4a19f2 100644 --- a/.github/actions/set-up-gh/action.yml +++ b/.github/actions/set-up-gh/action.yml @@ -1,5 +1,5 @@ -name: 'install gh' -description: 'Install the gh cli in a debian based distro and switches to the PR branch.' +name: "install gh" +description: "Install the gh cli in a debian based distro and switches to the PR branch." inputs: pr-number: description: "Number of the PR" @@ -9,28 +9,20 @@ inputs: required: true outputs: branch: - description: 'Branch name for the PR' + description: "Branch name for the PR" value: ${{ steps.branch.outputs.branch }} runs: using: "composite" steps: - - name: Instal gh cli - shell: bash - # Here it would get the script from previous step - run: | - (type -p wget >/dev/null || (apt update && apt-get install wget -y)) - mkdir -p -m 755 /etc/apt/keyrings - wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null - chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null - apt update - apt install gh -y - git config --global --add safe.directory '*' - - run: gh pr checkout ${{ inputs.pr-number }} - shell: bash - env: - GITHUB_TOKEN: ${{ inputs.GH_TOKEN }} - - name: Export branch name - shell: bash - run: echo "branch=$(git rev-parse --abbrev-ref HEAD)" >> "$GITHUB_OUTPUT" - id: branch + - name: Set up git + shell: bash + # Here it would get the script from previous step + run: git config --global --add safe.directory '*' + - run: gh pr checkout ${{ inputs.pr-number }} + shell: bash + env: + GITHUB_TOKEN: ${{ inputs.GH_TOKEN }} + - name: Export branch name + shell: bash + run: echo "branch=$(git rev-parse --abbrev-ref HEAD)" >> "$GITHUB_OUTPUT" + id: branch diff --git a/.github/scripts/cmd/cmd.py b/.github/scripts/cmd/cmd.py index b5835f1f3085..01f36ea375c5 100755 --- a/.github/scripts/cmd/cmd.py +++ b/.github/scripts/cmd/cmd.py @@ -77,7 +77,7 @@ spec.loader.exec_module(generate_prdoc) parser_prdoc = subparsers.add_parser('prdoc', help='Generates PR documentation') -generate_prdoc.setup_parser(parser_prdoc) +generate_prdoc.setup_parser(parser_prdoc, pr_required=False) def main(): global args, unknown, runtimesMatrix @@ -104,7 +104,7 @@ def main(): print(f'-- listing pallets for benchmark for {runtime["name"]}') wasm_file = f"target/{profile}/wbuild/{runtime['package']}/{runtime['package'].replace('-', '_')}.wasm" output = os.popen( - f"frame-omni-bencher v1 benchmark pallet --no-csv-header --no-storage-info --no-min-squares --no-median-slopes --all --list --runtime={wasm_file}").read() + f"frame-omni-bencher v1 benchmark pallet --no-csv-header --no-storage-info --no-min-squares --no-median-slopes --all --list --runtime={wasm_file} {runtime['bench_flags']}").read() raw_pallets = output.strip().split('\n') all_pallets = set() @@ -182,7 +182,8 @@ def main(): f"--repeat=20 " \ f"--heap-pages=4096 " \ f"{f'--template={template} ' if template else ''}" \ - f"--no-storage-info --no-min-squares --no-median-slopes" + f"--no-storage-info --no-min-squares --no-median-slopes " \ + f"{config['bench_flags']}" print(f'-- Running: {cmd} \n') status = os.system(cmd) if status != 0 and not args.continue_on_fail: diff --git a/.github/scripts/cmd/test_cmd.py b/.github/scripts/cmd/test_cmd.py index f4e70903347f..0316c7ff1bb4 100644 --- a/.github/scripts/cmd/test_cmd.py +++ b/.github/scripts/cmd/test_cmd.py @@ -7,13 +7,45 @@ # Mock data for runtimes-matrix.json mock_runtimes_matrix = [ - {"name": "dev", "package": "kitchensink-runtime", "path": "substrate/frame", "header": "substrate/HEADER-APACHE2", "template": "substrate/.maintain/frame-weight-template.hbs", "bench_features": "runtime-benchmarks,riscv"}, - {"name": "westend", "package": "westend-runtime", "path": "polkadot/runtime/westend", "header": "polkadot/file_header.txt", "template": "polkadot/xcm/pallet-xcm-benchmarks/template.hbs", "bench_features": "runtime-benchmarks"}, - {"name": "rococo", "package": "rococo-runtime", "path": "polkadot/runtime/rococo", "header": "polkadot/file_header.txt", "template": "polkadot/xcm/pallet-xcm-benchmarks/template.hbs", "bench_features": "runtime-benchmarks"}, - {"name": "asset-hub-westend", "package": "asset-hub-westend-runtime", "path": "cumulus/parachains/runtimes/assets/asset-hub-westend", "header": "cumulus/file_header.txt", "template": "cumulus/templates/xcm-bench-template.hbs", "bench_features": "runtime-benchmarks"}, + { + "name": "dev", + "package": "kitchensink-runtime", + "path": "substrate/frame", + "header": "substrate/HEADER-APACHE2", + "template": "substrate/.maintain/frame-weight-template.hbs", + "bench_features": "runtime-benchmarks,riscv", + "bench_flags": "--flag1 --flag2" + }, + { + "name": "westend", + "package": "westend-runtime", + "path": "polkadot/runtime/westend", + "header": "polkadot/file_header.txt", + "template": "polkadot/xcm/pallet-xcm-benchmarks/template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "--flag3 --flag4" + }, + { + "name": "rococo", + "package": "rococo-runtime", + "path": "polkadot/runtime/rococo", + "header": "polkadot/file_header.txt", + "template": "polkadot/xcm/pallet-xcm-benchmarks/template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "" + }, + { + "name": "asset-hub-westend", + "package": "asset-hub-westend-runtime", + "path": "cumulus/parachains/runtimes/assets/asset-hub-westend", + "header": "cumulus/file_header.txt", + "template": "cumulus/templates/xcm-bench-template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "--flag7 --flag8" + } ] -def get_mock_bench_output(runtime, pallets, output_path, header, template = None): +def get_mock_bench_output(runtime, pallets, output_path, header, bench_flags, template = None): return f"frame-omni-bencher v1 benchmark pallet --extrinsic=* " \ f"--runtime=target/release/wbuild/{runtime}-runtime/{runtime.replace('-', '_')}_runtime.wasm " \ f"--pallet={pallets} --header={header} " \ @@ -21,7 +53,8 @@ def get_mock_bench_output(runtime, pallets, output_path, header, template = None f"--wasm-execution=compiled " \ f"--steps=50 --repeat=20 --heap-pages=4096 " \ f"{f'--template={template} ' if template else ''}" \ - f"--no-storage-info --no-min-squares --no-median-slopes" + f"--no-storage-info --no-min-squares --no-median-slopes " \ + f"{bench_flags}" class TestCmd(unittest.TestCase): @@ -89,10 +122,29 @@ def test_bench_command_normal_execution_all_runtimes(self): call("forklift cargo build -p rococo-runtime --profile release --features=runtime-benchmarks"), call("forklift cargo build -p asset-hub-westend-runtime --profile release --features=runtime-benchmarks"), - call(get_mock_bench_output('kitchensink', 'pallet_balances', './substrate/frame/balances/src/weights.rs', os.path.abspath('substrate/HEADER-APACHE2'), "substrate/.maintain/frame-weight-template.hbs")), - call(get_mock_bench_output('westend', 'pallet_balances', './polkadot/runtime/westend/src/weights', os.path.abspath('polkadot/file_header.txt'))), + call(get_mock_bench_output( + runtime='kitchensink', + pallets='pallet_balances', + output_path='./substrate/frame/balances/src/weights.rs', + header=os.path.abspath('substrate/HEADER-APACHE2'), + bench_flags='--flag1 --flag2', + template="substrate/.maintain/frame-weight-template.hbs" + )), + call(get_mock_bench_output( + runtime='westend', + pallets='pallet_balances', + output_path='./polkadot/runtime/westend/src/weights', + header=os.path.abspath('polkadot/file_header.txt'), + bench_flags='--flag3 --flag4' + )), # skips rococo benchmark - call(get_mock_bench_output('asset-hub-westend', 'pallet_balances', './cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights', os.path.abspath('cumulus/file_header.txt'))), + call(get_mock_bench_output( + runtime='asset-hub-westend', + pallets='pallet_balances', + output_path='./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights', + header=os.path.abspath('cumulus/file_header.txt'), + bench_flags='--flag7 --flag8' + )), ] self.mock_system.assert_has_calls(expected_calls, any_order=True) @@ -121,8 +173,20 @@ def test_bench_command_normal_execution(self): call("forklift cargo build -p westend-runtime --profile release --features=runtime-benchmarks"), # Westend runtime calls - call(get_mock_bench_output('westend', 'pallet_balances', './polkadot/runtime/westend/src/weights', header_path)), - call(get_mock_bench_output('westend', 'pallet_staking', './polkadot/runtime/westend/src/weights', header_path)), + call(get_mock_bench_output( + runtime='westend', + pallets='pallet_balances', + output_path='./polkadot/runtime/westend/src/weights', + header=header_path, + bench_flags='--flag3 --flag4' + )), + call(get_mock_bench_output( + runtime='westend', + pallets='pallet_staking', + output_path='./polkadot/runtime/westend/src/weights', + header=header_path, + bench_flags='--flag3 --flag4' + )), ] self.mock_system.assert_has_calls(expected_calls, any_order=True) @@ -153,11 +217,12 @@ def test_bench_command_normal_execution_xcm(self): # Westend runtime calls call(get_mock_bench_output( - 'westend', - 'pallet_xcm_benchmarks::generic', - './polkadot/runtime/westend/src/weights/xcm', - header_path, - "polkadot/xcm/pallet-xcm-benchmarks/template.hbs" + runtime='westend', + pallets='pallet_xcm_benchmarks::generic', + output_path='./polkadot/runtime/westend/src/weights/xcm', + header=header_path, + bench_flags='--flag3 --flag4', + template="polkadot/xcm/pallet-xcm-benchmarks/template.hbs" )), ] self.mock_system.assert_has_calls(expected_calls, any_order=True) @@ -188,11 +253,35 @@ def test_bench_command_two_runtimes_two_pallets(self): call("forklift cargo build -p westend-runtime --profile release --features=runtime-benchmarks"), call("forklift cargo build -p rococo-runtime --profile release --features=runtime-benchmarks"), # Westend runtime calls - call(get_mock_bench_output('westend', 'pallet_staking', './polkadot/runtime/westend/src/weights', header_path)), - call(get_mock_bench_output('westend', 'pallet_balances', './polkadot/runtime/westend/src/weights', header_path)), + call(get_mock_bench_output( + runtime='westend', + pallets='pallet_staking', + output_path='./polkadot/runtime/westend/src/weights', + header=header_path, + bench_flags='--flag3 --flag4' + )), + call(get_mock_bench_output( + runtime='westend', + pallets='pallet_balances', + output_path='./polkadot/runtime/westend/src/weights', + header=header_path, + bench_flags='--flag3 --flag4' + )), # Rococo runtime calls - call(get_mock_bench_output('rococo', 'pallet_staking', './polkadot/runtime/rococo/src/weights', header_path)), - call(get_mock_bench_output('rococo', 'pallet_balances', './polkadot/runtime/rococo/src/weights', header_path)), + call(get_mock_bench_output( + runtime='rococo', + pallets='pallet_staking', + output_path='./polkadot/runtime/rococo/src/weights', + header=header_path, + bench_flags='' + )), + call(get_mock_bench_output( + runtime='rococo', + pallets='pallet_balances', + output_path='./polkadot/runtime/rococo/src/weights', + header=header_path, + bench_flags='' + )), ] self.mock_system.assert_has_calls(expected_calls, any_order=True) @@ -223,11 +312,12 @@ def test_bench_command_one_dev_runtime(self): call("forklift cargo build -p kitchensink-runtime --profile release --features=runtime-benchmarks,riscv"), # Westend runtime calls call(get_mock_bench_output( - 'kitchensink', - 'pallet_balances', - manifest_dir + "/src/weights.rs", - header_path, - "substrate/.maintain/frame-weight-template.hbs" + runtime='kitchensink', + pallets='pallet_balances', + output_path=manifest_dir + "/src/weights.rs", + header=header_path, + bench_flags='--flag1 --flag2', + template="substrate/.maintain/frame-weight-template.hbs" )), ] self.mock_system.assert_has_calls(expected_calls, any_order=True) @@ -257,10 +347,11 @@ def test_bench_command_one_cumulus_runtime(self): call("forklift cargo build -p asset-hub-westend-runtime --profile release --features=runtime-benchmarks"), # Asset-hub-westend runtime calls call(get_mock_bench_output( - 'asset-hub-westend', - 'pallet_assets', - './cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights', - header_path + runtime='asset-hub-westend', + pallets='pallet_assets', + output_path='./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights', + header=header_path, + bench_flags='--flag7 --flag8' )), ] @@ -291,17 +382,19 @@ def test_bench_command_one_cumulus_runtime_xcm(self): call("forklift cargo build -p asset-hub-westend-runtime --profile release --features=runtime-benchmarks"), # Asset-hub-westend runtime calls call(get_mock_bench_output( - 'asset-hub-westend', - 'pallet_xcm_benchmarks::generic', - './cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm', - header_path, - "cumulus/templates/xcm-bench-template.hbs" + runtime='asset-hub-westend', + pallets='pallet_xcm_benchmarks::generic', + output_path='./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm', + header=header_path, + bench_flags='--flag7 --flag8', + template="cumulus/templates/xcm-bench-template.hbs" )), call(get_mock_bench_output( - 'asset-hub-westend', - 'pallet_assets', - './cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights', - header_path + runtime='asset-hub-westend', + pallets='pallet_assets', + output_path='./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights', + header=header_path, + bench_flags='--flag7 --flag8' )), ] diff --git a/.github/scripts/generate-prdoc.py b/.github/scripts/generate-prdoc.py index f05d517a5802..edcdb82cd22e 100644 --- a/.github/scripts/generate-prdoc.py +++ b/.github/scripts/generate-prdoc.py @@ -7,7 +7,7 @@ This will delete any prdoc that already exists for the PR if `--force` is passed. Usage: - python generate-prdoc.py --pr 1234 --audience "TODO" --bump "TODO" + python generate-prdoc.py --pr 1234 --audience node_dev --bump patch """ import argparse @@ -110,27 +110,33 @@ def yaml_multiline_string_presenter(dumper, data): yaml.add_representer(str, yaml_multiline_string_presenter) # parse_args is also used by cmd/cmd.py -def setup_parser(parser=None): +# if pr_required is False, then --pr is optional, as it can be derived from the PR comment body +def setup_parser(parser=None, pr_required=True): + allowed_audiences = ["runtime_dev", "runtime_user", "node_dev", "node_operator"] if parser is None: parser = argparse.ArgumentParser() - parser.add_argument("--pr", type=int, required=True, help="The PR number to generate the PrDoc for." ) - parser.add_argument("--audience", type=str, default="TODO", help="The audience of whom the changes may concern.") - parser.add_argument("--bump", type=str, default="TODO", help="A default bump level for all crates.") - parser.add_argument("--force", type=str, help="Whether to overwrite any existing PrDoc.") - + parser.add_argument("--pr", type=int, required=pr_required, help="The PR number to generate the PrDoc for.") + parser.add_argument("--audience", type=str, nargs='*', choices=allowed_audiences, default=["todo"], help="The audience of whom the changes may concern. Example: --audience runtime_dev node_dev") + parser.add_argument("--bump", type=str, default="major", choices=["patch", "minor", "major", "silent", "ignore", "no_change"], help="A default bump level for all crates. Example: --bump patch") + parser.add_argument("--force", action="store_true", help="Whether to overwrite any existing PrDoc.") return parser +def snake_to_title(s): + return ' '.join(word.capitalize() for word in s.split('_')) + def main(args): - force = True if (args.force or "false").lower() == "true" else False - print(f"Args: {args}, force: {force}") + print(f"Args: {args}, force: {args.force}") setup_yaml() try: - from_pr_number(args.pr, args.audience, args.bump, force) + # Convert snake_case audience arguments to title case + mapped_audiences = [snake_to_title(a) for a in args.audience] + from_pr_number(args.pr, mapped_audiences, args.bump, args.force) return 0 except Exception as e: print(f"Error generating prdoc: {e}") return 1 if __name__ == "__main__": - args = setup_parser().parse_args() + parser = setup_parser() + args = parser.parse_args() main(args) diff --git a/.github/scripts/release/build-deb.sh b/.github/scripts/release/build-deb.sh new file mode 100755 index 000000000000..6cb833f98a4e --- /dev/null +++ b/.github/scripts/release/build-deb.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -e + +PRODUCT=$1 +VERSION=$2 +PROFILE=${PROFILE:-production} + +cargo install --version 2.7.0 cargo-deb --locked -q +echo "Using cargo-deb v$(cargo-deb --version)" +echo "Building a Debian package for '$PRODUCT' in '$PROFILE' profile" + +# we need to start the custom version with a didgit as requires it cargo-deb +cargo deb --profile $PROFILE --no-strip --no-build -p $PRODUCT --deb-version 1-$VERSION + +deb=target/debian/$PRODUCT_*_amd64.deb + +cp $deb target/production/ diff --git a/.github/scripts/release/build-linux-release.sh b/.github/scripts/release/build-linux-release.sh new file mode 100755 index 000000000000..a6bd658d292a --- /dev/null +++ b/.github/scripts/release/build-linux-release.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +# This is used to build our binaries: +# - polkadot +# - polkadot-parachain +# set -e + +BIN=$1 +PACKAGE=${2:-$BIN} + +PROFILE=${PROFILE:-production} +ARTIFACTS=/artifacts/$BIN +VERSION=$(git tag -l --contains HEAD | grep -E "^v.*") + +echo "Artifacts will be copied into $ARTIFACTS" +mkdir -p "$ARTIFACTS" + +git log --pretty=oneline -n 1 +time cargo build --profile $PROFILE --locked --verbose --bin $BIN --package $PACKAGE + +echo "Artifact target: $ARTIFACTS" + +cp ./target/$PROFILE/$BIN "$ARTIFACTS" +pushd "$ARTIFACTS" > /dev/nul +sha256sum "$BIN" | tee "$BIN.sha256" + +EXTRATAG="$($ARTIFACTS/$BIN --version | + sed -n -r 's/^'$BIN' ([0-9.]+.*-[0-9a-f]{7,13})-.*$/\1/p')" + +EXTRATAG="${VERSION}-${EXTRATAG}-$(cut -c 1-8 $ARTIFACTS/$BIN.sha256)" + +echo "$BIN version = ${VERSION} (EXTRATAG = ${EXTRATAG})" +echo -n ${VERSION} > "$ARTIFACTS/VERSION" +echo -n ${EXTRATAG} > "$ARTIFACTS/EXTRATAG" diff --git a/.github/scripts/release/release_lib.sh b/.github/scripts/release/release_lib.sh index 81a3c14edec8..f5032073b617 100644 --- a/.github/scripts/release/release_lib.sh +++ b/.github/scripts/release/release_lib.sh @@ -116,3 +116,24 @@ set_polkadot_parachain_binary_version() { commit_with_message "$MESSAGE" git_show_log "$MESSAGE" } + + +upload_s3_release() { + alias aws='podman run --rm -it docker.io/paritytech/awscli -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_BUCKET aws' + + product=$1 + version=$2 + + echo "Working on product: $product " + echo "Working on version: $version " + + echo "Current content, should be empty on new uploads:" + aws s3 ls "s3://releases.parity.io/polkadot/${version}/" --recursive --human-readable --summarize || true + echo "Content to be uploaded:" + artifacts="artifacts/$product/" + ls "$artifacts" + aws s3 sync --acl public-read "$artifacts" "s3://releases.parity.io/polkadot/${version}/" + echo "Uploaded files:" + aws s3 ls "s3://releases.parity.io/polkadot/${version}/" --recursive --human-readable --summarize + echo "✅ The release should be at https://releases.parity.io/polkadot/${version}" +} diff --git a/.github/workflows/check-cargo-check-runtimes.yml b/.github/workflows/check-cargo-check-runtimes.yml index 7e9f0dc77b7c..b49a2cbbfd3e 100644 --- a/.github/workflows/check-cargo-check-runtimes.yml +++ b/.github/workflows/check-cargo-check-runtimes.yml @@ -7,11 +7,12 @@ concurrency: on: pull_request: types: [opened, synchronize, reopened, ready_for_review] + paths: + - "cumulus/parachains/runtimes/*" # Jobs in this workflow depend on each other, only for limiting peak amount of spawned workers jobs: - preflight: uses: ./.github/workflows/reusable-preflight.yml diff --git a/.github/workflows/check-frame-omni-bencher.yml b/.github/workflows/check-frame-omni-bencher.yml index 9b01311aa69c..924a8b7f712f 100644 --- a/.github/workflows/check-frame-omni-bencher.yml +++ b/.github/workflows/check-frame-omni-bencher.yml @@ -16,14 +16,11 @@ env: ARTIFACTS_NAME: frame-omni-bencher-artifacts jobs: - preflight: - # TODO: remove once migration is complete or this workflow is fully stable - if: contains(github.event.label.name, 'GHA-migration') uses: ./.github/workflows/reusable-preflight.yml quick-benchmarks-omni: - runs-on: ${{ needs.preflight.outputs.RUNNER }} + runs-on: ${{ needs.preflight.outputs.RUNNER_BENCHMARK }} needs: [preflight] if: ${{ needs.preflight.outputs.changes_rust }} env: @@ -31,6 +28,7 @@ jobs: RUST_BACKTRACE: "full" WASM_BUILD_NO_COLOR: 1 WASM_BUILD_RUSTFLAGS: "-C debug-assertions" + RUST_LOG: "frame_omni_bencher=info,polkadot_sdk_frame=info" timeout-minutes: 30 container: image: ${{ needs.preflight.outputs.IMAGE }} @@ -42,33 +40,41 @@ jobs: forklift cargo build --locked --quiet --release -p asset-hub-westend-runtime --features runtime-benchmarks forklift cargo run --locked --release -p frame-omni-bencher --quiet -- v1 benchmark pallet --runtime target/release/wbuild/asset-hub-westend-runtime/asset_hub_westend_runtime.compact.compressed.wasm --all --steps 2 --repeat 1 --quiet + runtime-matrix: + runs-on: ubuntu-latest + needs: [preflight] + if: ${{ needs.preflight.outputs.changes_rust }} + timeout-minutes: 30 + outputs: + runtime: ${{ steps.runtime.outputs.runtime }} + container: + image: ${{ needs.preflight.outputs.IMAGE }} + name: Extract runtimes from matrix + steps: + - uses: actions/checkout@v4 + - id: runtime + run: | + RUNTIMES=$(jq '[.[] | select(.package != null)]' .github/workflows/runtimes-matrix.json) + + RUNTIMES=$(echo $RUNTIMES | jq -c .) + echo "runtime=$RUNTIMES" + echo "runtime=$RUNTIMES" >> $GITHUB_OUTPUT + run-frame-omni-bencher: - runs-on: ${{ needs.preflight.outputs.RUNNER }} - needs: [preflight] # , build-frame-omni-bencher ] + runs-on: ${{ needs.preflight.outputs.RUNNER_BENCHMARK }} + needs: [preflight, runtime-matrix] if: ${{ needs.preflight.outputs.changes_rust }} timeout-minutes: 30 strategy: fail-fast: false # keep running other workflows even if one fails, to see the logs of all possible failures matrix: - runtime: - [ - westend-runtime, - rococo-runtime, - asset-hub-rococo-runtime, - asset-hub-westend-runtime, - bridge-hub-rococo-runtime, - bridge-hub-westend-runtime, - collectives-westend-runtime, - coretime-rococo-runtime, - coretime-westend-runtime, - people-rococo-runtime, - people-westend-runtime, - glutton-westend-runtime, - ] + runtime: ${{ fromJSON(needs.runtime-matrix.outputs.runtime) }} container: image: ${{ needs.preflight.outputs.IMAGE }} env: - PACKAGE_NAME: ${{ matrix.runtime }} + PACKAGE_NAME: ${{ matrix.runtime.package }} + FLAGS: ${{ matrix.runtime.bench_flags }} + RUST_LOG: "frame_omni_bencher=info,polkadot_sdk_frame=info" steps: - name: Checkout uses: actions/checkout@v4 @@ -77,14 +83,17 @@ jobs: run: | RUNTIME_BLOB_NAME=$(echo $PACKAGE_NAME | sed 's/-/_/g').compact.compressed.wasm RUNTIME_BLOB_PATH=./target/release/wbuild/$PACKAGE_NAME/$RUNTIME_BLOB_NAME - forklift cargo build --release --locked -p $PACKAGE_NAME -p frame-omni-bencher --features runtime-benchmarks + forklift cargo build --release --locked -p $PACKAGE_NAME -p frame-omni-bencher --features=${{ matrix.runtime.bench_features }} --quiet echo "Running short benchmarking for PACKAGE_NAME=$PACKAGE_NAME and RUNTIME_BLOB_PATH=$RUNTIME_BLOB_PATH" ls -lrt $RUNTIME_BLOB_PATH - ./target/release/frame-omni-bencher v1 benchmark pallet --runtime $RUNTIME_BLOB_PATH --all --steps 2 --repeat 1 + + cmd="./target/release/frame-omni-bencher v1 benchmark pallet --runtime $RUNTIME_BLOB_PATH --all --steps 2 --repeat 1 $FLAGS" + echo "Running command: $cmd" + eval "$cmd" confirm-frame-omni-benchers-passed: runs-on: ubuntu-latest name: All benchmarks passed - needs: run-frame-omni-bencher + needs: [quick-benchmarks-omni, run-frame-omni-bencher] if: always() && !cancelled() steps: - run: | diff --git a/.github/workflows/check-semver.yml b/.github/workflows/check-semver.yml index b5866e0ce414..811ec4d5558f 100644 --- a/.github/workflows/check-semver.yml +++ b/.github/workflows/check-semver.yml @@ -13,10 +13,13 @@ env: TOOLCHAIN: nightly-2024-06-01 jobs: + preflight: + uses: ./.github/workflows/reusable-preflight.yml check-semver: runs-on: ubuntu-latest + needs: [preflight] container: - image: docker.io/paritytech/ci-unified:bullseye-1.77.0-2024-04-10-v20240408 + image: ${{ needs.preflight.outputs.IMAGE }} steps: - uses: actions/checkout@6d193bf28034eafb982f37bd894289fe649468fc # v4.1.7 with: @@ -36,10 +39,6 @@ jobs: run: | echo "This is a backport into stable." - wget -q https://github.com/cli/cli/releases/download/v2.51.0/gh_2.51.0_linux_amd64.tar.gz -O gh.tar.gz && \ - tar -xzf gh.tar.gz && mv gh_2.51.0_linux_amd64/bin/gh /usr/local/bin/gh && rm gh.tar.gz - chmod +x /usr/local/bin/gh - cat > msg.txt <> $GITHUB_OUTPUT python3 -m pip install -r .github/scripts/generate-prdoc.requirements.txt + echo 'help<> $GITHUB_OUTPUT python3 .github/scripts/cmd/cmd.py $CMD >> $GITHUB_OUTPUT echo 'EOF' >> $GITHUB_OUTPUT @@ -283,6 +283,7 @@ jobs: env: JOB_NAME: "cmd" runs-on: ${{ needs.set-image.outputs.RUNNER }} + timeout-minutes: 1800 # 30 hours as it could take a long time to run all the runtimes/pallets container: image: ${{ needs.set-image.outputs.IMAGE }} steps: @@ -291,7 +292,18 @@ jobs: id: get-pr-comment with: text: ${{ github.event.comment.body }} - regex: '^(\/cmd )([-\/\s\w.=:]+)$' # see explanation in docs/contributor/commands-readme.md#examples + regex: "^(\\/cmd )([-\\/\\s\\w.=:]+)$" # see explanation in docs/contributor/commands-readme.md#examples + + # In order to run prdoc without specifying the PR number, we need to add the PR number as an argument automatically + - name: Prepare PR Number argument + id: pr-arg + run: | + CMD="${{ steps.get-pr-comment.outputs.group2 }}" + if echo "$CMD" | grep -q "prdoc" && ! echo "$CMD" | grep -qE "\-\-pr[[:space:]=][0-9]+"; then + echo "arg=--pr ${{ github.event.issue.number }}" >> $GITHUB_OUTPUT + else + echo "arg=" >> $GITHUB_OUTPUT + fi - name: Build workflow link if: ${{ !contains(github.event.comment.body, '--quiet') }} @@ -314,7 +326,8 @@ jobs: echo "run_url=$runLink" >> $GITHUB_OUTPUT - name: Comment PR (Start) - if: ${{ !contains(github.event.comment.body, '--quiet') }} + # No need to comment on prdoc start or if --quiet + if: ${{ !contains(github.event.comment.body, '--quiet') && !contains(github.event.comment.body, 'prdoc') }} uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} @@ -344,14 +357,15 @@ jobs: id: cmd env: CMD: ${{ steps.get-pr-comment.outputs.group2 }} # to avoid "" around the command + PR_ARG: ${{ steps.pr-arg.outputs.arg }} run: | - echo "Running command: '$CMD' on '${{ needs.set-image.outputs.RUNNER }}' runner, container: '${{ needs.set-image.outputs.IMAGE }}'" + echo "Running command: '$CMD $PR_ARG' on '${{ needs.set-image.outputs.RUNNER }}' runner, container: '${{ needs.set-image.outputs.IMAGE }}'" echo "RUST_NIGHTLY_VERSION: $RUST_NIGHTLY_VERSION" # Fixes "detected dubious ownership" error in the ci git config --global --add safe.directory '*' git remote -v python3 -m pip install -r .github/scripts/generate-prdoc.requirements.txt - python3 .github/scripts/cmd/cmd.py $CMD + python3 .github/scripts/cmd/cmd.py $CMD $PR_ARG git status git diff @@ -395,7 +409,8 @@ jobs: } >> $GITHUB_OUTPUT - name: Comment PR (End) - if: ${{ !failure() && !contains(github.event.comment.body, '--quiet') }} + # No need to comment on prdoc success or --quiet + if: ${{ !failure() && !contains(github.event.comment.body, '--quiet') && !contains(github.event.comment.body, 'prdoc') }} uses: actions/github-script@v7 env: SUBWEIGHT: "${{ steps.subweight.outputs.result }}" diff --git a/.github/workflows/command-prdoc.yml b/.github/workflows/command-prdoc.yml index 2154c8a987f2..7022e8e0e006 100644 --- a/.github/workflows/command-prdoc.yml +++ b/.github/workflows/command-prdoc.yml @@ -14,7 +14,7 @@ on: required: true options: - "TODO" - - "no change" + - "no_change" - "patch" - "minor" - "major" @@ -25,18 +25,15 @@ on: required: true options: - "TODO" - - "Runtime Dev" - - "Runtime User" - - "Node Dev" - - "Node Operator" + - "runtime_dev" + - "runtime_user" + - "node_dev" + - "node_operator" overwrite: - type: choice + type: boolean description: Overwrite existing PrDoc - default: "true" + default: true required: true - options: - - "true" - - "false" concurrency: group: command-prdoc @@ -81,4 +78,4 @@ jobs: with: commit_message: Add PrDoc (auto generated) branch: ${{ steps.gh.outputs.branch }} - file_pattern: 'prdoc/*.prdoc' + file_pattern: "prdoc/*.prdoc" diff --git a/.github/workflows/release-build-rc.yml b/.github/workflows/release-build-rc.yml new file mode 100644 index 000000000000..5c25e3c749b8 --- /dev/null +++ b/.github/workflows/release-build-rc.yml @@ -0,0 +1,74 @@ +name: Release - Build node release candidate + +on: + workflow_dispatch: + inputs: + binary: + description: Binary to be build for the release + default: all + type: choice + options: + - polkadot + - polkadot-parachain + - all + + release_tag: + description: Tag matching the actual release candidate with the format stableYYMM-rcX or stableYYMM + type: string + +jobs: + check-synchronization: + uses: paritytech-release/sync-workflows/.github/workflows/check-syncronization.yml@main + + validate-inputs: + needs: [check-synchronization] + if: ${{ needs.check-synchronization.outputs.checks_passed }} == 'true' + runs-on: ubuntu-latest + outputs: + release_tag: ${{ steps.validate_inputs.outputs.release_tag }} + + steps: + - name: Checkout sources + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + + - name: Validate inputs + id: validate_inputs + run: | + . ./.github/scripts/common/lib.sh + + RELEASE_TAG=$(validate_stable_tag ${{ inputs.release_tag }}) + echo "release_tag=${RELEASE_TAG}" >> $GITHUB_OUTPUT + + build-polkadot-binary: + needs: [validate-inputs] + if: ${{ inputs.binary == 'polkadot' || inputs.binary == 'all' }} + uses: "./.github/workflows/release-reusable-rc-buid.yml" + with: + binary: '["polkadot", "polkadot-prepare-worker", "polkadot-execute-worker"]' + package: polkadot + release_tag: ${{ needs.validate-inputs.outputs.release_tag }} + secrets: + PGP_KMS_KEY: ${{ secrets.PGP_KMS_KEY }} + PGP_KMS_HASH: ${{ secrets.PGP_KMS_HASH }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }} + AWS_RELEASE_ACCESS_KEY_ID: ${{ secrets.AWS_RELEASE_ACCESS_KEY_ID }} + AWS_RELEASE_SECRET_ACCESS_KEY: ${{ secrets.AWS_RELEASE_SECRET_ACCESS_KEY }} + + build-polkadot-parachain-binary: + needs: [validate-inputs] + if: ${{ inputs.binary == 'polkadot-parachain' || inputs.binary == 'all' }} + uses: "./.github/workflows/release-reusable-rc-buid.yml" + with: + binary: '["polkadot-parachain"]' + package: "polkadot-parachain-bin" + release_tag: ${{ needs.validate-inputs.outputs.release_tag }} + secrets: + PGP_KMS_KEY: ${{ secrets.PGP_KMS_KEY }} + PGP_KMS_HASH: ${{ secrets.PGP_KMS_HASH }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }} + AWS_RELEASE_ACCESS_KEY_ID: ${{ secrets.AWS_RELEASE_ACCESS_KEY_ID }} + AWS_RELEASE_SECRET_ACCESS_KEY: ${{ secrets.AWS_RELEASE_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/release-reusable-rc-buid.yml b/.github/workflows/release-reusable-rc-buid.yml new file mode 100644 index 000000000000..2aee9dc995b1 --- /dev/null +++ b/.github/workflows/release-reusable-rc-buid.yml @@ -0,0 +1,191 @@ +name: RC Build + +on: + workflow_call: + inputs: + binary: + description: Binary to be build for the release + required: true + default: polkadot + type: string + + package: + description: Package to be built, for now is either polkadot or polkadot-parachain-bin + required: true + type: string + + release_tag: + description: Tag matching the actual release candidate with the format stableYYMM-rcX or stableYYMM + required: true + type: string + + secrets: + PGP_KMS_KEY: + required: true + PGP_KMS_HASH: + required: true + AWS_ACCESS_KEY_ID: + required: true + AWS_SECRET_ACCESS_KEY: + required: true + AWS_DEFAULT_REGION: + required: true + AWS_RELEASE_ACCESS_KEY_ID: + required: true + AWS_RELEASE_SECRET_ACCESS_KEY: + required: true + +permissions: + id-token: write + contents: read + attestations: write + +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@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + + - id: set_image + run: cat .github/env >> $GITHUB_OUTPUT + + build-rc: + needs: [set-image] + runs-on: ubuntu-latest + environment: release + container: + image: ${{ needs.set-image.outputs.IMAGE }} + strategy: + matrix: + binaries: ${{ fromJSON(inputs.binary) }} + env: + PGP_KMS_KEY: ${{ secrets.PGP_KMS_KEY }} + PGP_KMS_HASH: ${{ secrets.PGP_KMS_HASH }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }} + + steps: + - name: Install pgpkkms + run: | + # Install pgpkms that is used to sign built artifacts + python3 -m pip install "pgpkms @ git+https://github.com/paritytech-release/pgpkms.git@5a8f82fbb607ea102d8c178e761659de54c7af69" + which pgpkms + + - name: Checkout sources + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + with: + ref: ${{ inputs.release_tag }} + fetch-depth: 0 + + - name: Import gpg keys + shell: bash + run: | + . ./.github/scripts/common/lib.sh + + import_gpg_keys + + - name: Build binary + run: | + git config --global --add safe.directory "${GITHUB_WORKSPACE}" #avoid "detected dubious ownership" error + ./.github/scripts/release/build-linux-release.sh ${{ matrix.binaries }} ${{ inputs.package }} + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@1c608d11d69870c2092266b3f9a6f3abbf17002c # v1.4.3 + with: + subject-path: /artifacts/${{ matrix.binaries }}/${{ matrix.binaries }} + + - name: Sign artifacts + working-directory: /artifacts/${{ matrix.binaries }} + run: | + python3 -m pgpkms sign --input ${{matrix.binaries }} -o ${{ matrix.binaries }}.asc + + - name: Check sha256 ${{ matrix.binaries }} + working-directory: /artifacts/${{ matrix.binaries }} + shell: bash + run: | + . "${GITHUB_WORKSPACE}"/.github/scripts/common/lib.sh + + echo "Checking binary ${{ matrix.binaries }}" + check_sha256 ${{ matrix.binaries }} + + - name: Check GPG ${{ matrix.binaries }} + working-directory: /artifacts/${{ matrix.binaries }} + shell: bash + run: | + . "${GITHUB_WORKSPACE}"/.github/scripts/common/lib.sh + + check_gpg ${{ matrix.binaries }} + + - name: Upload ${{ matrix.binaries }} artifacts + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + with: + name: ${{ matrix.binaries }} + path: /artifacts/${{ matrix.binaries }} + + build-polkadot-deb-package: + if: ${{ inputs.package == 'polkadot' }} + needs: [build-rc] + runs-on: ubuntu-latest + + steps: + - name: Checkout sources + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + with: + ref: ${{ inputs.release_tag }} + fetch-depth: 0 + + - name: Download artifacts + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + with: + path: target/production + merge-multiple: true + + - name: Build polkadot deb package + shell: bash + run: | + . "${GITHUB_WORKSPACE}"/.github/scripts/release/build-deb.sh ${{ inputs.package }} ${{ inputs.release_tag }} + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@1c608d11d69870c2092266b3f9a6f3abbf17002c # v1.4.3 + with: + subject-path: target/production/*.deb + + - name: Upload ${{inputs.package }} artifacts + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + with: + name: ${{ inputs.package }} + path: target/production + overwrite: true + + upload-polkadot-artifacts-to-s3: + if: ${{ inputs.package == 'polkadot' }} + needs: [build-polkadot-deb-package] + uses: ./.github/workflows/release-reusable-s3-upload.yml + with: + package: ${{ inputs.package }} + release_tag: ${{ inputs.release_tag }} + secrets: + AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }} + AWS_RELEASE_ACCESS_KEY_ID: ${{ secrets.AWS_RELEASE_ACCESS_KEY_ID }} + AWS_RELEASE_SECRET_ACCESS_KEY: ${{ secrets.AWS_RELEASE_SECRET_ACCESS_KEY }} + + + upload-polkadot-parachain-artifacts-to-s3: + if: ${{ inputs.package == 'polkadot-parachain-bin' }} + needs: [build-rc] + uses: ./.github/workflows/release-reusable-s3-upload.yml + with: + package: ${{ inputs.binary }} + release_tag: ${{ inputs.release_tag }} + secrets: + AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }} + AWS_RELEASE_ACCESS_KEY_ID: ${{ secrets.AWS_RELEASE_ACCESS_KEY_ID }} + AWS_RELEASE_SECRET_ACCESS_KEY: ${{ secrets.AWS_RELEASE_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/release-reusable-s3-upload.yml b/.github/workflows/release-reusable-s3-upload.yml new file mode 100644 index 000000000000..6776b78da8e6 --- /dev/null +++ b/.github/workflows/release-reusable-s3-upload.yml @@ -0,0 +1,53 @@ +name: Upload to s3 + +on: + workflow_call: + inputs: + package: + description: Package to be built, for now is either polkadot or polkadot-parachain-bin + required: true + type: string + + release_tag: + description: Tag matching the actual release candidate with the format stableYYMM-rcX or stableYYMM-rcX + required: true + type: string + + secrets: + AWS_DEFAULT_REGION: + required: true + AWS_RELEASE_ACCESS_KEY_ID: + required: true + AWS_RELEASE_SECRET_ACCESS_KEY: + required: true + +jobs: + upload-artifacts-to-s3: + runs-on: ubuntu-latest + environment: release + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_RELEASE_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_RELEASE_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_DEFAULT_REGION }} + + steps: + - name: Checkout + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + + - name: Download artifacts + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + with: + name: ${{ inputs.package }} + path: artifacts/${{ inputs.package }} + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + with: + aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + - name: Upload ${{ inputs.package }} artifacts to s3 + run: | + . ./.github/scripts/release/release_lib.sh + upload_s3_release ${{ inputs.package }} ${{ inputs.release_tag }} diff --git a/.github/workflows/runtimes-matrix.json b/.github/workflows/runtimes-matrix.json index 50fa44b1b073..e4e3a2dbe6d1 100644 --- a/.github/workflows/runtimes-matrix.json +++ b/.github/workflows/runtimes-matrix.json @@ -6,6 +6,7 @@ "header": "substrate/HEADER-APACHE2", "template": "substrate/.maintain/frame-weight-template.hbs", "bench_features": "runtime-benchmarks,riscv", + "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic,pallet_nomination_pools,pallet_remark,pallet_transaction_storage", "uri": null, "is_relay": false }, @@ -15,8 +16,9 @@ "path": "polkadot/runtime/westend", "header": "polkadot/file_header.txt", "template": "polkadot/xcm/pallet-xcm-benchmarks/template.hbs", - "uri": "wss://try-runtime-westend.polkadot.io:443", + "bench_flags": "", "bench_features": "runtime-benchmarks", + "uri": "wss://try-runtime-westend.polkadot.io:443", "is_relay": true }, { @@ -27,6 +29,7 @@ "template": "polkadot/xcm/pallet-xcm-benchmarks/template.hbs", "uri": "wss://try-runtime-rococo.polkadot.io:443", "bench_features": "runtime-benchmarks", + "bench_flags": "", "is_relay": true }, { @@ -36,6 +39,7 @@ "header": "cumulus/file_header.txt", "template": "cumulus/templates/xcm-bench-template.hbs", "bench_features": "runtime-benchmarks", + "bench_flags": "", "uri": "wss://westend-asset-hub-rpc.polkadot.io:443", "is_relay": false }, @@ -44,8 +48,9 @@ "package": "asset-hub-rococo-runtime", "path": "cumulus/parachains/runtimes/assets/asset-hub-rococo", "header": "cumulus/file_header.txt", - "bench_features": "runtime-benchmarks", "template": "cumulus/templates/xcm-bench-template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "", "uri": "wss://rococo-asset-hub-rpc.polkadot.io:443", "is_relay": false }, @@ -54,8 +59,9 @@ "package": "bridge-hub-rococo-runtime", "path": "cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo", "header": "cumulus/file_header.txt", - "bench_features": "runtime-benchmarks", "template": "cumulus/templates/xcm-bench-template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "", "uri": "wss://rococo-bridge-hub-rpc.polkadot.io:443", "is_relay": false }, @@ -64,8 +70,9 @@ "package": "bridge-hub-rococo-runtime", "path": "cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend", "header": "cumulus/file_header.txt", - "bench_features": "runtime-benchmarks", "template": "cumulus/templates/xcm-bench-template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "", "uri": "wss://westend-bridge-hub-rpc.polkadot.io:443", "is_relay": false }, @@ -74,8 +81,9 @@ "package": "collectives-westend-runtime", "path": "cumulus/parachains/runtimes/collectives/collectives-westend", "header": "cumulus/file_header.txt", - "bench_features": "runtime-benchmarks", "template": "cumulus/templates/xcm-bench-template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "", "uri": "wss://westend-collectives-rpc.polkadot.io:443" }, { @@ -83,8 +91,9 @@ "package": "contracts-rococo-runtime", "path": "cumulus/parachains/runtimes/contracts/contracts-rococo", "header": "cumulus/file_header.txt", - "bench_features": "runtime-benchmarks", "template": "cumulus/templates/xcm-bench-template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm", "uri": "wss://rococo-contracts-rpc.polkadot.io:443", "is_relay": false }, @@ -93,8 +102,9 @@ "package": "coretime-rococo-runtime", "path": "cumulus/parachains/runtimes/coretime/coretime-rococo", "header": "cumulus/file_header.txt", - "bench_features": "runtime-benchmarks", "template": "cumulus/templates/xcm-bench-template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic", "uri": "wss://rococo-coretime-rpc.polkadot.io:443", "is_relay": false }, @@ -103,8 +113,9 @@ "package": "coretime-westend-runtime", "path": "cumulus/parachains/runtimes/coretime/coretime-westend", "header": "cumulus/file_header.txt", - "bench_features": "runtime-benchmarks", "template": "cumulus/templates/xcm-bench-template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic", "uri": "wss://westend-coretime-rpc.polkadot.io:443", "is_relay": false }, @@ -113,8 +124,9 @@ "package": "glutton-westend-runtime", "path": "cumulus/parachains/runtimes/gluttons/glutton-westend", "header": "cumulus/file_header.txt", - "bench_features": "runtime-benchmarks", "template": "cumulus/templates/xcm-bench-template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "--genesis-builder-policy=none", "uri": null, "is_relay": false }, @@ -123,8 +135,9 @@ "package": "people-rococo-runtime", "path": "cumulus/parachains/runtimes/people/people-rococo", "header": "cumulus/file_header.txt", - "bench_features": "runtime-benchmarks", "template": "cumulus/templates/xcm-bench-template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic", "uri": "wss://rococo-people-rpc.polkadot.io:443", "is_relay": false }, @@ -133,8 +146,9 @@ "package": "people-westend-runtime", "path": "cumulus/parachains/runtimes/people/people-westend", "header": "cumulus/file_header.txt", - "bench_features": "runtime-benchmarks", "template": "cumulus/templates/xcm-bench-template.hbs", + "bench_features": "runtime-benchmarks", + "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic", "uri": "wss://westend-people-rpc.polkadot.io:443", "is_relay": false } diff --git a/.github/workflows/tests-linux-stable.yml b/.github/workflows/tests-linux-stable.yml index 599edd8e69a1..dd292d55e201 100644 --- a/.github/workflows/tests-linux-stable.yml +++ b/.github/workflows/tests-linux-stable.yml @@ -98,6 +98,41 @@ jobs: if: ${{ matrix.partition == '1/3' }} run: forklift cargo nextest run -p sp-api-test --features enable-staging-api --cargo-quiet + # some tests do not run with `try-runtime` feature enabled + # https://github.com/paritytech/polkadot-sdk/pull/4251#discussion_r1624282143 + # + # all_security_features_work and nonexistent_cache_dir are currently skipped + # becuase runners don't have the necessary permissions to run them + test-linux-stable-no-try-runtime: + needs: [preflight] + if: ${{ needs.preflight.outputs.changes_rust }} + runs-on: ${{ needs.preflight.outputs.RUNNER }} + timeout-minutes: 60 + container: + image: ${{ needs.preflight.outputs.IMAGE }} + strategy: + fail-fast: false + matrix: + partition: [1/2, 2/2] + 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: | + forklift cargo nextest run --workspace \ + --locked \ + --release \ + --no-fail-fast \ + --cargo-quiet \ + --features experimental,riscv,ci-only-tests \ + --filter-expr " !test(/all_security_features_work/) - test(/nonexistent_cache_dir/)" \ + --partition count:${{ matrix.partition }} \ + confirm-required-jobs-passed: runs-on: ubuntu-latest name: All tests passed @@ -107,6 +142,7 @@ jobs: test-linux-stable-int, test-linux-stable-runtime-benchmarks, test-linux-stable, + test-linux-stable-no-try-runtime, ] if: always() && !cancelled() steps: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dbc5dafeb0ae..f508404f1efa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -225,8 +225,6 @@ include: - .gitlab/pipeline/test.yml # build jobs - .gitlab/pipeline/build.yml - # short-benchmarks jobs - - .gitlab/pipeline/short-benchmarks.yml # publish jobs - .gitlab/pipeline/publish.yml # zombienet jobs @@ -284,8 +282,3 @@ cancel-pipeline-build-linux-substrate: extends: .cancel-pipeline-template needs: - job: build-linux-substrate - -cancel-pipeline-build-short-benchmark: - extends: .cancel-pipeline-template - needs: - - job: build-short-benchmark diff --git a/.gitlab/pipeline/build.yml b/.gitlab/pipeline/build.yml index 0d509879b449..179eebf8b509 100644 --- a/.gitlab/pipeline/build.yml +++ b/.gitlab/pipeline/build.yml @@ -160,19 +160,6 @@ build-implementers-guide: - mkdir -p artifacts - mv polkadot/roadmap/implementers-guide/book artifacts/ -build-short-benchmark: - stage: build - extends: - - .docker-env - - .common-refs - - .run-immediately - - .collect-artifacts - script: - - cargo build --profile release --locked --features=runtime-benchmarks,on-chain-release-build --bin polkadot --workspace - - mkdir -p artifacts - - target/release/polkadot --version - - cp ./target/release/polkadot ./artifacts/ - build-polkadot-zombienet-tests: stage: build extends: @@ -191,7 +178,6 @@ build-polkadot-zombienet-tests: - mkdir -p artifacts - cp polkadot-zombienet-tests.tar.zst ./artifacts - # build jobs from cumulus build-linux-stable-cumulus: @@ -234,92 +220,6 @@ build-test-parachain: - mkdir -p ./artifacts/zombienet - mv ./target/release/wbuild/cumulus-test-runtime/wasm_binary_spec_version_incremented.rs.compact.compressed.wasm ./artifacts/zombienet/. -# build runtime only if files in $RUNTIME_PATH/$RUNTIME_NAME were changed -.build-runtime-template: &build-runtime-template - stage: build - extends: - - .docker-env - - .test-refs-no-trigger-prs-only - - .run-immediately - variables: - RUNTIME_PATH: "parachains/runtimes/assets" - script: - - cd ${RUNTIME_PATH} - - for directory in $(echo */); do - echo "_____Running cargo check for ${directory} ______"; - cd ${directory}; - pwd; - SKIP_WASM_BUILD=1 cargo check --locked; - cd ..; - done - -# DAG: build-runtime-assets -> build-runtime-collectives -> build-runtime-bridge-hubs -# DAG: build-runtime-assets -> build-runtime-collectives -> build-runtime-contracts -# DAG: build-runtime-assets -> build-runtime-coretime -# DAG: build-runtime-assets -> build-runtime-testing -build-runtime-assets: - <<: *build-runtime-template - variables: - RUNTIME_PATH: "cumulus/parachains/runtimes/assets" - -build-runtime-collectives: - <<: *build-runtime-template - variables: - RUNTIME_PATH: "cumulus/parachains/runtimes/collectives" - # this is an artificial job dependency, for pipeline optimization using GitLab's DAGs - needs: - - job: build-runtime-assets - artifacts: false - -build-runtime-coretime: - <<: *build-runtime-template - variables: - RUNTIME_PATH: "cumulus/parachains/runtimes/coretime" - # this is an artificial job dependency, for pipeline optimization using GitLab's DAGs - needs: - - job: build-runtime-assets - artifacts: false - -build-runtime-bridge-hubs: - <<: *build-runtime-template - variables: - RUNTIME_PATH: "cumulus/parachains/runtimes/bridge-hubs" - # this is an artificial job dependency, for pipeline optimization using GitLab's DAGs - needs: - - job: build-runtime-collectives - artifacts: false - -build-runtime-contracts: - <<: *build-runtime-template - variables: - RUNTIME_PATH: "cumulus/parachains/runtimes/contracts" - # this is an artificial job dependency, for pipeline optimization using GitLab's DAGs - needs: - - job: build-runtime-collectives - artifacts: false - -build-runtime-testing: - <<: *build-runtime-template - variables: - RUNTIME_PATH: "cumulus/parachains/runtimes/testing" - # this is an artificial job dependency, for pipeline optimization using GitLab's DAGs - needs: - - job: build-runtime-assets - artifacts: false - -build-short-benchmark-cumulus: - stage: build - extends: - - .docker-env - - .common-refs - - .run-immediately - - .collect-artifacts - script: - - cargo build --profile release --locked --features=runtime-benchmarks,on-chain-release-build -p polkadot-parachain-bin --bin polkadot-parachain --workspace - - mkdir -p artifacts - - target/release/polkadot-parachain --version - - cp ./target/release/polkadot-parachain ./artifacts/ - # substrate build-linux-substrate: @@ -340,7 +240,7 @@ build-linux-substrate: # tldr: we need to checkout the branch HEAD explicitly because of our dynamic versioning approach while building the substrate binary # see https://github.com/paritytech/ci_cd/issues/682#issuecomment-1340953589 - git checkout -B "$CI_COMMIT_REF_NAME" "$CI_COMMIT_SHA" - - !reference [ .forklift-cache, before_script ] + - !reference [.forklift-cache, before_script] script: - time WASM_BUILD_NO_COLOR=1 cargo build --locked --release -p staging-node-cli - mv $CARGO_TARGET_DIR/release/substrate-node ./artifacts/substrate/substrate diff --git a/.gitlab/pipeline/short-benchmarks.yml b/.gitlab/pipeline/short-benchmarks.yml index ad09f3f7cb0a..ed97d539c095 100644 --- a/.gitlab/pipeline/short-benchmarks.yml +++ b/.gitlab/pipeline/short-benchmarks.yml @@ -1,121 +1 @@ -# This file is part of .gitlab-ci.yml -# Here are all jobs that are executed during "short-benchmarks" stage - -# Run all pallet benchmarks only once to check if there are any errors - -# run short-benchmarks for relay chain runtimes from polkadot - -short-benchmark-westend: &short-bench - stage: short-benchmarks - extends: - - .docker-env - - .common-refs - needs: - - job: build-short-benchmark - artifacts: true - variables: - RUNTIME: westend - # Enable debug assertions since we are running optimized builds for testing - # but still want to have debug assertions. - RUSTFLAGS: "-C debug-assertions -D warnings" - RUST_BACKTRACE: "full" - WASM_BUILD_NO_COLOR: 1 - WASM_BUILD_RUSTFLAGS: "-C debug-assertions -D warnings" - tags: - - benchmark - script: - - ./artifacts/polkadot benchmark pallet --chain $RUNTIME-dev --pallet "*" --extrinsic "*" --steps 2 --repeat 1 - -short-benchmark-rococo: &short-bench - stage: short-benchmarks - extends: - - .docker-env - - .common-refs - needs: - - job: build-short-benchmark - artifacts: true - variables: - RUNTIME: rococo - # Enable debug assertions since we are running optimized builds for testing - # but still want to have debug assertions. - RUSTFLAGS: "-C debug-assertions -D warnings" - RUST_BACKTRACE: "full" - WASM_BUILD_NO_COLOR: 1 - WASM_BUILD_RUSTFLAGS: "-C debug-assertions -D warnings" - tags: - - benchmark - script: - - ./artifacts/polkadot benchmark pallet --chain $RUNTIME-dev --pallet "*" --extrinsic "*" --steps 2 --repeat 1 - -# run short-benchmarks for system parachain runtimes from cumulus - -.short-benchmark-cumulus: &short-bench-cumulus - stage: short-benchmarks - extends: - - .common-refs - - .docker-env - needs: - - job: build-short-benchmark-cumulus - artifacts: true - variables: - RUNTIME_CHAIN: benchmarked-runtime-chain - # Enable debug assertions since we are running optimized builds for testing - # but still want to have debug assertions. - RUSTFLAGS: "-C debug-assertions -D warnings" - RUST_BACKTRACE: "full" - WASM_BUILD_NO_COLOR: 1 - WASM_BUILD_RUSTFLAGS: "-C debug-assertions -D warnings" - tags: - - benchmark - script: - - ./artifacts/polkadot-parachain benchmark pallet --chain $RUNTIME_CHAIN --pallet "*" --extrinsic "*" --steps 2 --repeat 1 - -short-benchmark-asset-hub-rococo: - <<: *short-bench-cumulus - variables: - RUNTIME_CHAIN: asset-hub-rococo-dev - -short-benchmark-asset-hub-westend: - <<: *short-bench-cumulus - variables: - RUNTIME_CHAIN: asset-hub-westend-dev - -short-benchmark-bridge-hub-rococo: - <<: *short-bench-cumulus - variables: - RUNTIME_CHAIN: bridge-hub-rococo-dev - -short-benchmark-bridge-hub-westend: - <<: *short-bench-cumulus - variables: - RUNTIME_CHAIN: bridge-hub-westend-dev - -short-benchmark-collectives-westend: - <<: *short-bench-cumulus - variables: - RUNTIME_CHAIN: collectives-westend-dev - -short-benchmark-coretime-rococo: - <<: *short-bench-cumulus - variables: - RUNTIME_CHAIN: coretime-rococo-dev - -short-benchmark-coretime-westend: - <<: *short-bench-cumulus - variables: - RUNTIME_CHAIN: coretime-westend-dev - -short-benchmark-people-rococo: - <<: *short-bench-cumulus - variables: - RUNTIME_CHAIN: people-rococo-dev - -short-benchmark-people-westend: - <<: *short-bench-cumulus - variables: - RUNTIME_CHAIN: people-westend-dev - -short-benchmark-glutton-westend: - <<: *short-bench-cumulus - variables: - RUNTIME_CHAIN: glutton-westend-dev-1300 +--- diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml index 0252620cd0f3..81e9ad12751a 100644 --- a/.gitlab/pipeline/test.yml +++ b/.gitlab/pipeline/test.yml @@ -110,31 +110,6 @@ test-linux-stable-codecov: 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 -# some tests do not run with `try-runtime` feature enabled -# https://github.com/paritytech/polkadot-sdk/pull/4251#discussion_r1624282143 -# Move to github after https://github.com/paritytech/ci_cd/issues/1056 is fixed -test-linux-stable-no-try-runtime: - stage: test - extends: - - .docker-env - - .common-refs - - .run-immediately - - .pipeline-stopper-artifacts - variables: - RUST_TOOLCHAIN: stable - # Enable debug assertions since we are running optimized builds for testing - # but still want to have debug assertions. - RUSTFLAGS: "-Cdebug-assertions=y -Dwarnings" - script: - - > - time cargo nextest run \ - --workspace \ - --locked \ - --release \ - --no-fail-fast \ - --cargo-quiet \ - --features experimental,riscv,ci-only-tests - test-doc: stage: test extends: @@ -161,20 +136,3 @@ test-rustdoc: SKIP_WASM_BUILD: 1 script: - time cargo doc --workspace --all-features --no-deps - -quick-benchmarks-omni: - stage: test - extends: - - .docker-env - - .common-refs - - .run-immediately - variables: - # Enable debug assertions since we are running optimized builds for testing - # but still want to have debug assertions. - RUSTFLAGS: "-C debug-assertions" - RUST_BACKTRACE: "full" - WASM_BUILD_NO_COLOR: 1 - WASM_BUILD_RUSTFLAGS: "-C debug-assertions" - script: - - time cargo build --locked --quiet --release -p asset-hub-westend-runtime --features runtime-benchmarks - - time cargo run --locked --release -p frame-omni-bencher --quiet -- v1 benchmark pallet --runtime target/release/wbuild/asset-hub-westend-runtime/asset_hub_westend_runtime.compact.compressed.wasm --all --steps 2 --repeat 1 --quiet diff --git a/.gitlab/pipeline/zombienet.yml b/.gitlab/pipeline/zombienet.yml index b02d857f3f24..2a7e2e7559a0 100644 --- a/.gitlab/pipeline/zombienet.yml +++ b/.gitlab/pipeline/zombienet.yml @@ -1,12 +1,14 @@ .zombienet-refs: extends: .build-refs variables: - ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.113" + ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.114" PUSHGATEWAY_URL: "http://zombienet-prometheus-pushgateway.managed-monitoring:9091/metrics/job/zombie-metrics" DEBUG: "zombie,zombie::network-node,zombie::kube::client::logs" ZOMBIE_PROVIDER: "k8s" RUST_LOG: "info,zombienet_orchestrator=debug" RUN_IN_CI: "1" + KUBERNETES_CPU_REQUEST: "512m" + KUBERNETES_MEMORY_REQUEST: "512M" timeout: 60m include: diff --git a/.gitlab/pipeline/zombienet/polkadot.yml b/.gitlab/pipeline/zombienet/polkadot.yml index 0da95f224cfc..d17380839942 100644 --- a/.gitlab/pipeline/zombienet/polkadot.yml +++ b/.gitlab/pipeline/zombienet/polkadot.yml @@ -172,7 +172,7 @@ zombienet-polkadot-elastic-scaling-0001-basic-3cores-6s-blocks: variables: FORCED_INFRA_INSTANCE: "spot-iops" before_script: - - !reference [.zombienet-polkadot-common, before_script] + - !reference [ .zombienet-polkadot-common, before_script ] - cp --remove-destination ${LOCAL_DIR}/assign-core.js ${LOCAL_DIR}/elastic_scaling script: - /home/nonroot/zombie-net/scripts/ci/run-test-local-env-manager.sh @@ -183,14 +183,14 @@ zombienet-polkadot-elastic-scaling-0002-elastic-scaling-doesnt-break-parachains: extends: - .zombienet-polkadot-common before_script: - - !reference [.zombienet-polkadot-common, before_script] + - !reference [ .zombienet-polkadot-common, before_script ] - cp --remove-destination ${LOCAL_DIR}/assign-core.js ${LOCAL_DIR}/elastic_scaling script: - /home/nonroot/zombie-net/scripts/ci/run-test-local-env-manager.sh --local-dir="${LOCAL_DIR}/elastic_scaling" --test="0002-elastic-scaling-doesnt-break-parachains.zndsl" -zombienet-polkadot-functional-0012-spam-statement-distribution-requests: +.zombienet-polkadot-functional-0012-spam-statement-distribution-requests: extends: - .zombienet-polkadot-common script: @@ -218,7 +218,7 @@ zombienet-polkadot-functional-0015-coretime-shared-core: extends: - .zombienet-polkadot-common before_script: - - !reference [.zombienet-polkadot-common, before_script] + - !reference [ .zombienet-polkadot-common, before_script ] - cp --remove-destination ${LOCAL_DIR}/assign-core.js ${LOCAL_DIR}/functional script: - /home/nonroot/zombie-net/scripts/ci/run-test-local-env-manager.sh @@ -277,7 +277,7 @@ zombienet-polkadot-smoke-0002-parachains-parachains-upgrade-smoke: --local-dir="${LOCAL_DIR}/smoke" --test="0002-parachains-upgrade-smoke-test.zndsl" -zombienet-polkadot-smoke-0003-deregister-register-validator: +.zombienet-polkadot-smoke-0003-deregister-register-validator: extends: - .zombienet-polkadot-common script: @@ -360,10 +360,10 @@ zombienet-polkadot-malus-0001-dispute-valid: - job: build-polkadot-zombienet-tests artifacts: true before_script: - - !reference [".zombienet-polkadot-common", "before_script"] + - !reference [ ".zombienet-polkadot-common", "before_script" ] - export POLKADOT_IMAGE="${ZOMBIENET_INTEGRATION_TEST_IMAGE}" script: - # we want to use `--no-capture` in zombienet tests. + # we want to use `--no-capture` in zombienet tests. - unset NEXTEST_FAILURE_OUTPUT - unset NEXTEST_SUCCESS_OUTPUT - cargo nextest run --archive-file ./artifacts/polkadot-zombienet-tests.tar.zst --no-capture -- smoke::coretime_revenue::coretime_revenue_test diff --git a/.gitlab/pipeline/zombienet/substrate.yml b/.gitlab/pipeline/zombienet/substrate.yml index d4ffa34f3395..030a0a3f50a9 100644 --- a/.gitlab/pipeline/zombienet/substrate.yml +++ b/.gitlab/pipeline/zombienet/substrate.yml @@ -70,7 +70,7 @@ zombienet-substrate-0001-basic-warp-sync: --local-dir="${LOCAL_DIR}/0001-basic-warp-sync" --test="test-warp-sync.zndsl" -zombienet-substrate-0002-validators-warp-sync: +.zombienet-substrate-0002-validators-warp-sync: extends: - .zombienet-substrate-warp-sync-common before_script: diff --git a/Cargo.lock b/Cargo.lock index 2c7d695c417c..0b3e1e71bfd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -900,7 +900,7 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "polkadot-runtime-common", - "primitive-types", + "primitive-types 0.13.1", "rococo-runtime-constants", "scale-info", "serde_json", @@ -1033,7 +1033,7 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "polkadot-runtime-common", - "primitive-types", + "primitive-types 0.13.1", "scale-info", "serde_json", "snowbridge-router-primitives", @@ -1765,9 +1765,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" dependencies = [ "arrayref", "arrayvec 0.7.4", @@ -2048,7 +2048,6 @@ dependencies = [ "frame-system", "hex", "parity-scale-codec", - "parity-util-mem", "scale-info", "serde", "sp-core 28.0.0", @@ -2229,6 +2228,7 @@ dependencies = [ "staging-xcm", "staging-xcm-executor", "testnet-parachains-constants", + "xcm-runtime-apis", ] [[package]] @@ -2422,6 +2422,7 @@ dependencies = [ "staging-xcm", "staging-xcm-executor", "testnet-parachains-constants", + "xcm-runtime-apis", ] [[package]] @@ -2708,12 +2709,13 @@ checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" [[package]] name = "cc" -version = "1.0.94" +version = "1.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" +checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -5755,9 +5757,9 @@ dependencies = [ [[package]] name = "ethabi-decode" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d398648d65820a727d6a81e58b962f874473396a047e4c30bafe3240953417" +checksum = "f9af52ec57c5147716872863c2567c886e7d62f539465b94352dbc0108fe5293" dependencies = [ "ethereum-types", "tiny-keccak", @@ -5765,33 +5767,33 @@ dependencies = [ [[package]] name = "ethbloom" -version = "0.13.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +checksum = "8c321610643004cf908ec0f5f2aa0d8f1f8e14b540562a2887a1111ff1ecbf7b" dependencies = [ "crunchy", "fixed-hash", - "impl-codec", + "impl-codec 0.7.0", "impl-rlp", - "impl-serde", + "impl-serde 0.5.0", "scale-info", "tiny-keccak", ] [[package]] name = "ethereum-types" -version = "0.14.1" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +checksum = "1ab15ed80916029f878e0267c3a9f92b67df55e79af370bf66199059ae2b4ee3" dependencies = [ "ethbloom", "fixed-hash", - "impl-codec", + "impl-codec 0.7.0", "impl-rlp", - "impl-serde", - "primitive-types", + "impl-serde 0.5.0", + "primitive-types 0.13.1", "scale-info", - "uint", + "uint 0.10.0", ] [[package]] @@ -7611,6 +7613,15 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "impl-codec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67aa010c1e3da95bf151bd8b4c059b2ed7e75387cdb969b4f8f2723a43f9941" +dependencies = [ + "parity-scale-codec", +] + [[package]] name = "impl-num-traits" version = "0.1.2" @@ -7619,16 +7630,27 @@ checksum = "951641f13f873bff03d4bf19ae8bec531935ac0ac2cc775f84d7edfdcfed3f17" dependencies = [ "integer-sqrt", "num-traits", - "uint", + "uint 0.9.5", +] + +[[package]] +name = "impl-num-traits" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d15461ab0dcc56706adf266158acbc44ccf719bf7d0af30705f58b90a4b8c" +dependencies = [ + "integer-sqrt", + "num-traits", + "uint 0.10.0", ] [[package]] name = "impl-rlp" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +checksum = "54ed8ad1f3877f7e775b8cbf30ed1bd3209a95401817f19a0eb4402d13f8cf90" dependencies = [ - "rlp", + "rlp 0.6.1", ] [[package]] @@ -7640,6 +7662,15 @@ dependencies = [ "serde", ] +[[package]] +name = "impl-serde" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a143eada6a1ec4aefa5049037a26a6d597bfd64f8c026d07b77133e02b7dd0b" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.2" @@ -7920,9 +7951,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] @@ -8367,7 +8398,7 @@ dependencies = [ "pallet-example-tasks", "parity-scale-codec", "polkadot-sdk", - "primitive-types", + "primitive-types 0.13.1", "scale-info", "serde_json", "static_assertions", @@ -8780,7 +8811,7 @@ dependencies = [ "sha2 0.10.8", "smallvec", "thiserror", - "uint", + "uint 0.9.5", "unsigned-varint 0.7.2", "void", ] @@ -9243,7 +9274,7 @@ dependencies = [ "tokio-tungstenite", "tokio-util", "tracing", - "uint", + "uint 0.9.5", "unsigned-varint 0.8.0", "url", "x25519-dalek", @@ -9278,15 +9309,6 @@ dependencies = [ "value-bag", ] -[[package]] -name = "lru" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" -dependencies = [ - "hashbrown 0.12.3", -] - [[package]] name = "lru" version = "0.11.0" @@ -10629,7 +10651,7 @@ dependencies = [ "pallet-assets", "pallet-balances", "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", "scale-info", "sp-api 26.0.0", "sp-arithmetic 23.0.0", @@ -10650,7 +10672,7 @@ dependencies = [ "pallet-assets", "pallet-balances", "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", "scale-info", "sp-arithmetic 23.0.0", "sp-core 28.0.0", @@ -11448,7 +11470,7 @@ dependencies = [ "sp-npos-elections", "sp-runtime 31.0.1", "sp-tracing 16.0.0", - "strum 0.26.2", + "strum 0.26.3", ] [[package]] @@ -12311,9 +12333,10 @@ dependencies = [ "pallet-utility", "parity-scale-codec", "paste", - "polkavm 0.11.0", + "polkavm 0.12.0", + "polkavm-common 0.12.0", "pretty_assertions", - "rlp", + "rlp 0.6.1", "scale-info", "serde", "sp-api 26.0.0", @@ -12336,7 +12359,7 @@ dependencies = [ "frame-system", "log", "parity-wasm", - "polkavm-linker 0.11.0", + "polkavm-linker 0.12.0", "sp-core 28.0.0", "sp-io 30.0.0", "sp-runtime 31.0.1", @@ -12396,7 +12419,7 @@ dependencies = [ "bitflags 1.3.2", "parity-scale-codec", "paste", - "polkavm-derive 0.11.0", + "polkavm-derive 0.12.0", "scale-info", ] @@ -12830,6 +12853,7 @@ dependencies = [ "frame-support", "frame-system", "impl-trait-for-tuples", + "log", "pallet-balances", "pallet-utility", "parity-scale-codec", @@ -13280,35 +13304,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "parity-util-mem" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d32c34f4f5ca7f9196001c0aba5a1f9a5a12382c8944b8b0f90233282d1e8f8" -dependencies = [ - "cfg-if", - "ethereum-types", - "hashbrown 0.12.3", - "impl-trait-for-tuples", - "lru 0.8.1", - "parity-util-mem-derive", - "parking_lot 0.12.3", - "primitive-types", - "smallvec", - "winapi", -] - -[[package]] -name = "parity-util-mem-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" -dependencies = [ - "proc-macro2 1.0.86", - "syn 1.0.109", - "synstructure 0.12.6", -] - [[package]] name = "parity-wasm" version = "0.45.0" @@ -13480,7 +13475,7 @@ dependencies = [ "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", - "primitive-types", + "primitive-types 0.12.2", "scale-info", "smallvec", "sp-api 26.0.0", @@ -14321,6 +14316,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-test-helpers", "polkadot-node-subsystem-util", + "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-primitives-test-helpers", "polkadot-statement-table", @@ -14541,6 +14537,7 @@ dependencies = [ "slotmap", "sp-core 28.0.0", "sp-maybe-compressed-blob 11.0.0", + "strum 0.26.3", "tempfile", "test-parachain-adder", "test-parachain-halt", @@ -14709,7 +14706,7 @@ dependencies = [ "sc-network", "sc-network-types", "sp-runtime 31.0.1", - "strum 0.26.2", + "strum 0.26.3", "thiserror", "tracing-gum", ] @@ -14793,6 +14790,7 @@ dependencies = [ "sp-blockchain", "sp-consensus-babe", "sp-runtime 31.0.1", + "strum 0.26.3", "substrate-prometheus-endpoint", "thiserror", ] @@ -14839,69 +14837,16 @@ dependencies = [ ] [[package]] -name = "polkadot-overseer" -version = "7.0.0" -dependencies = [ - "assert_matches", - "async-trait", - "femme", - "futures", - "futures-timer", - "orchestra", - "parking_lot 0.12.3", - "polkadot-node-metrics", - "polkadot-node-network-protocol", - "polkadot-node-primitives", - "polkadot-node-subsystem-test-helpers", - "polkadot-node-subsystem-types", - "polkadot-primitives", - "polkadot-primitives-test-helpers", - "prioritized-metered-channel", - "sc-client-api", - "sp-api 26.0.0", - "sp-core 28.0.0", - "tikv-jemalloc-ctl", - "tracing-gum", -] - -[[package]] -name = "polkadot-parachain-bin" -version = "4.0.0" +name = "polkadot-omni-node" +version = "0.1.0" dependencies = [ - "asset-hub-rococo-runtime", - "asset-hub-westend-runtime", - "bp-messages", - "bridge-hub-rococo-runtime", - "bridge-hub-westend-runtime", - "collectives-westend-runtime", "color-eyre", - "contracts-rococo-runtime", - "coretime-rococo-runtime", - "coretime-westend-runtime", - "cumulus-primitives-core", - "glutton-westend-runtime", - "hex-literal", - "log", - "parachains-common", - "penpal-runtime", - "people-rococo-runtime", - "people-westend-runtime", - "polkadot-parachain-lib", - "rococo-parachain-runtime", - "sc-chain-spec", - "sc-cli", - "sc-service", - "serde", - "serde_json", - "sp-core 28.0.0", - "sp-genesis-builder", - "staging-xcm", + "polkadot-omni-node-lib", "substrate-build-script-utils", - "testnet-parachains-constants", ] [[package]] -name = "polkadot-parachain-lib" +name = "polkadot-omni-node-lib" version = "0.1.0" dependencies = [ "assert_cmd", @@ -14974,6 +14919,66 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "polkadot-overseer" +version = "7.0.0" +dependencies = [ + "assert_matches", + "async-trait", + "femme", + "futures", + "futures-timer", + "orchestra", + "parking_lot 0.12.3", + "polkadot-node-metrics", + "polkadot-node-network-protocol", + "polkadot-node-primitives", + "polkadot-node-subsystem-test-helpers", + "polkadot-node-subsystem-types", + "polkadot-primitives", + "polkadot-primitives-test-helpers", + "prioritized-metered-channel", + "sc-client-api", + "sp-api 26.0.0", + "sp-core 28.0.0", + "tikv-jemalloc-ctl", + "tracing-gum", +] + +[[package]] +name = "polkadot-parachain-bin" +version = "4.0.0" +dependencies = [ + "asset-hub-rococo-runtime", + "asset-hub-westend-runtime", + "bridge-hub-rococo-runtime", + "bridge-hub-westend-runtime", + "collectives-westend-runtime", + "color-eyre", + "contracts-rococo-runtime", + "coretime-rococo-runtime", + "coretime-westend-runtime", + "cumulus-primitives-core", + "glutton-westend-runtime", + "hex-literal", + "log", + "parachains-common", + "penpal-runtime", + "people-rococo-runtime", + "people-westend-runtime", + "polkadot-omni-node-lib", + "rococo-parachain-runtime", + "sc-chain-spec", + "sc-cli", + "sc-service", + "serde", + "serde_json", + "sp-core 28.0.0", + "sp-genesis-builder", + "staging-xcm", + "substrate-build-script-utils", +] + [[package]] name = "polkadot-parachain-primitives" version = "6.0.0" @@ -15407,8 +15412,8 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-types", "polkadot-node-subsystem-util", + "polkadot-omni-node-lib", "polkadot-overseer", - "polkadot-parachain-lib", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-rpc", @@ -15920,7 +15925,7 @@ dependencies = [ "sp-runtime 31.0.1", "sp-timestamp", "sp-tracing 16.0.0", - "strum 0.26.2", + "strum 0.26.3", "substrate-prometheus-endpoint", "tikv-jemallocator", "tokio", @@ -16143,15 +16148,15 @@ dependencies = [ [[package]] name = "polkavm" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1195fbc12f11645143a4f3974bf909d25c7f7efddcc6f4e57688d9a518c90bae" +checksum = "f27910c5061e4cea6be6c66684b49d0f42b6a05900c9b0da9e7f3dd2d587a8d4" dependencies = [ "libc", "log", - "polkavm-assembler 0.11.0", - "polkavm-common 0.11.0", - "polkavm-linux-raw 0.11.0", + "polkavm-assembler 0.12.0", + "polkavm-common 0.12.0", + "polkavm-linux-raw 0.12.0", ] [[package]] @@ -16165,9 +16170,9 @@ dependencies = [ [[package]] name = "polkavm-assembler" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b0399659fe7a5370c3e3464188888d29069cfa46d99631d19834a379c15826" +checksum = "82f0e374fa043f31459b30d629d7e866247ac4b6c7662ac72e4e5bf50d052b92" dependencies = [ "log", ] @@ -16189,12 +16194,13 @@ dependencies = [ [[package]] name = "polkavm-common" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254b19b64ff9b57c06b32c0affed961cb9a32429b8d3e5cf2633cad7fbb3e270" +checksum = "f4e42e082c3d89da2346555baf4d951fe07dcb9208e42a02c272e6d5d0326f9a" dependencies = [ + "blake3", "log", - "polkavm-assembler 0.11.0", + "polkavm-assembler 0.12.0", ] [[package]] @@ -16217,11 +16223,11 @@ dependencies = [ [[package]] name = "polkavm-derive" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f565f0106fbb3598d64b8528d5cb966b6a87a8dd93fbcfe09fb6388ff2865711" +checksum = "540b798393e68a890202d5dc9f86a985b7ea83611e3406d90dc1043e7997b4d1" dependencies = [ - "polkavm-derive-impl-macro 0.11.0", + "polkavm-derive-impl-macro 0.12.0", ] [[package]] @@ -16250,11 +16256,11 @@ dependencies = [ [[package]] name = "polkavm-derive-impl" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "314445fb5688b4769354087d92be2ac94c487e63ffe74a6fb7bb312e57f20827" +checksum = "d179eddaaef62ce5960faaa2ec9e8f131c81661c8b9365c4d55b275011688534" dependencies = [ - "polkavm-common 0.11.0", + "polkavm-common 0.12.0", "proc-macro2 1.0.86", "quote 1.0.37", "syn 2.0.79", @@ -16282,11 +16288,11 @@ dependencies = [ [[package]] name = "polkavm-derive-impl-macro" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf952e05bc5ce7d81293bae18cb44c271c78615b201d75e983cdcc40d5c6ef1" +checksum = "bd35472599d35d90e24afe9eb39ae6ee6cb1b924f0c03b277ef8b5f174a63853" dependencies = [ - "polkavm-derive-impl 0.11.0", + "polkavm-derive-impl 0.12.0", "syn 2.0.79", ] @@ -16307,15 +16313,15 @@ dependencies = [ [[package]] name = "polkavm-linker" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535a2095a186ccde2cd2fa721d6370c495586d47714817565b2f6621d31164b3" +checksum = "6f917b16db9ab13819a738a321b48a2d0d20d9e32dedcff75054148676afbec4" dependencies = [ "gimli 0.28.0", "hashbrown 0.14.5", "log", "object 0.36.1", - "polkavm-common 0.11.0", + "polkavm-common 0.12.0", "regalloc2 0.9.3", "rustc-demangle", ] @@ -16328,9 +16334,9 @@ checksum = "26e85d3456948e650dff0cfc85603915847faf893ed1e66b020bb82ef4557120" [[package]] name = "polkavm-linux-raw" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3011697430dfcfe800d1d7c540ef69e3bdd66e9037cc38f01fee1c2e0908011e" +checksum = "d280301d5b5a321c732173c969058f4b5726f3a0046f6802f396df2599f3753d" [[package]] name = "polling" @@ -16514,12 +16520,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", - "impl-codec", - "impl-num-traits", + "impl-codec 0.6.0", + "impl-num-traits 0.1.2", + "impl-serde 0.4.0", + "scale-info", + "uint 0.9.5", +] + +[[package]] +name = "primitive-types" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15600a7d856470b7d278b3fe0e311fe28c2526348549f8ef2ff7db3299c87f5" +dependencies = [ + "fixed-hash", + "impl-codec 0.7.0", + "impl-num-traits 0.2.0", "impl-rlp", - "impl-serde", + "impl-serde 0.5.0", "scale-info", - "uint", + "uint 0.10.0", ] [[package]] @@ -17631,6 +17651,16 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "rlp" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa24e92bb2a83198bb76d661a71df9f7076b8c420b8696e4d3d97d50d94479e3" +dependencies = [ + "bytes", + "rustc-hex", +] + [[package]] name = "rocksdb" version = "0.21.0" @@ -17941,10 +17971,10 @@ dependencies = [ "num-bigint", "num-traits", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "proptest", "rand", - "rlp", + "rlp 0.5.2", "ruint-macro", "serde", "valuable", @@ -19874,7 +19904,7 @@ checksum = "e98f3262c250d90e700bb802eb704e1f841e03331c2eb815e46516c4edbf5b27" dependencies = [ "derive_more", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "scale-bits", "scale-decode-derive", "scale-type-resolver", @@ -19901,7 +19931,7 @@ checksum = "4ba0b9c48dc0eb20c60b083c29447c0c4617cb7c4a4c9fef72aa5c5bc539e15e" dependencies = [ "derive_more", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "scale-bits", "scale-encode-derive", "scale-type-resolver", @@ -20863,7 +20893,7 @@ dependencies = [ "hex", "hex-literal", "parity-scale-codec", - "rlp", + "rlp 0.6.1", "scale-info", "serde", "snowbridge-ethereum", @@ -20911,7 +20941,7 @@ dependencies = [ "parity-bytes", "parity-scale-codec", "rand", - "rlp", + "rlp 0.6.1", "scale-info", "serde", "serde-big-array", @@ -21469,7 +21499,7 @@ dependencies = [ "integer-sqrt", "num-traits", "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", "rand", "scale-info", "serde", @@ -21639,7 +21669,7 @@ dependencies = [ "sp-mmr-primitives", "sp-runtime 31.0.1", "sp-weights 27.0.0", - "strum 0.26.2", + "strum 0.26.3", "w3f-bls", ] @@ -21709,7 +21739,7 @@ dependencies = [ "futures", "hash-db", "hash256-std-hasher", - "impl-serde", + "impl-serde 0.4.0", "itertools 0.11.0", "k256", "libsecp256k1", @@ -21719,7 +21749,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "paste", - "primitive-types", + "primitive-types 0.13.1", "rand", "regex", "scale-info", @@ -21758,7 +21788,7 @@ dependencies = [ "futures", "hash-db", "hash256-std-hasher", - "impl-serde", + "impl-serde 0.4.0", "itertools 0.10.5", "k256", "libsecp256k1", @@ -21768,7 +21798,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "paste", - "primitive-types", + "primitive-types 0.12.2", "rand", "scale-info", "schnorrkel 0.11.4", @@ -21805,7 +21835,7 @@ dependencies = [ "futures", "hash-db", "hash256-std-hasher", - "impl-serde", + "impl-serde 0.4.0", "itertools 0.10.5", "k256", "libsecp256k1", @@ -21815,7 +21845,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "paste", - "primitive-types", + "primitive-types 0.12.2", "rand", "scale-info", "schnorrkel 0.11.4", @@ -21852,7 +21882,7 @@ dependencies = [ "futures", "hash-db", "hash256-std-hasher", - "impl-serde", + "impl-serde 0.4.0", "itertools 0.11.0", "k256", "libsecp256k1", @@ -21862,7 +21892,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "paste", - "primitive-types", + "primitive-types 0.12.2", "rand", "scale-info", "schnorrkel 0.11.4", @@ -22211,7 +22241,7 @@ version = "31.0.0" dependencies = [ "sp-core 28.0.0", "sp-runtime 31.0.1", - "strum 0.26.2", + "strum 0.26.3", ] [[package]] @@ -22507,7 +22537,7 @@ dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "sp-externalities 0.19.0", "sp-runtime-interface-proc-macro 11.0.0", "sp-std 8.0.0", @@ -22525,7 +22555,7 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "polkavm-derive 0.9.1", - "primitive-types", + "primitive-types 0.13.1", "rustversion", "sp-core 28.0.0", "sp-externalities 0.25.0", @@ -22551,7 +22581,7 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "polkavm-derive 0.8.0", - "primitive-types", + "primitive-types 0.12.2", "sp-externalities 0.27.0", "sp-runtime-interface-proc-macro 18.0.0", "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -22571,7 +22601,7 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "polkavm-derive 0.9.1", - "primitive-types", + "primitive-types 0.12.2", "sp-externalities 0.28.0", "sp-runtime-interface-proc-macro 18.0.0", "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -22812,7 +22842,7 @@ name = "sp-storage" version = "13.0.0" source = "git+https://github.com/paritytech/polkadot-sdk#82912acb33a9030c0ef3bf590a34fca09b72dc5f" dependencies = [ - "impl-serde", + "impl-serde 0.4.0", "parity-scale-codec", "ref-cast", "serde", @@ -22824,7 +22854,7 @@ dependencies = [ name = "sp-storage" version = "19.0.0" dependencies = [ - "impl-serde", + "impl-serde 0.4.0", "parity-scale-codec", "ref-cast", "serde", @@ -22837,7 +22867,7 @@ version = "20.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dba5791cb3978e95daf99dad919ecb3ec35565604e88cd38d805d9d4981e8bd" dependencies = [ - "impl-serde", + "impl-serde 0.4.0", "parity-scale-codec", "ref-cast", "serde", @@ -22851,7 +22881,7 @@ version = "21.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99c82989b3a4979a7e1ad848aad9f5d0b4388f1f454cc131766526601ab9e8f8" dependencies = [ - "impl-serde", + "impl-serde 0.4.0", "parity-scale-codec", "ref-cast", "serde", @@ -23052,7 +23082,7 @@ dependencies = [ name = "sp-version" version = "29.0.0" dependencies = [ - "impl-serde", + "impl-serde 0.4.0", "parity-scale-codec", "parity-wasm", "scale-info", @@ -23070,7 +23100,7 @@ version = "35.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ff74bf12b4f7d29387eb1caeec5553209a505f90a2511d2831143b970f89659" dependencies = [ - "impl-serde", + "impl-serde 0.4.0", "parity-scale-codec", "parity-wasm", "scale-info", @@ -23404,7 +23434,7 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-parachains", "polkadot-test-runtime", - "primitive-types", + "primitive-types 0.13.1", "scale-info", "sp-arithmetic 23.0.0", "sp-core 28.0.0", @@ -23538,11 +23568,11 @@ checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ - "strum_macros 0.26.2", + "strum_macros 0.26.4", ] [[package]] @@ -23573,11 +23603,11 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2 1.0.86", "quote 1.0.37", "rustversion", @@ -23773,7 +23803,7 @@ dependencies = [ "sp-runtime 31.0.1", "sp-trie 29.0.0", "structopt", - "strum 0.26.2", + "strum 0.26.3", "thiserror", ] @@ -23966,7 +23996,7 @@ dependencies = [ "sp-maybe-compressed-blob 11.0.0", "sp-tracing 16.0.0", "sp-version 29.0.0", - "strum 0.26.2", + "strum 0.26.3", "tempfile", "toml 0.8.12", "walkdir", @@ -24029,11 +24059,11 @@ dependencies = [ "frame-metadata 16.0.0", "futures", "hex", - "impl-serde", + "impl-serde 0.4.0", "instant", "jsonrpsee 0.22.5", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "reconnecting-jsonrpsee-ws-client", "scale-bits", "scale-decode", @@ -24086,9 +24116,9 @@ dependencies = [ "frame-metadata 16.0.0", "hashbrown 0.14.5", "hex", - "impl-serde", + "impl-serde 0.4.0", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "scale-bits", "scale-decode", "scale-encode", @@ -25439,6 +25469,18 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unarray" version = "0.1.4" diff --git a/Cargo.toml b/Cargo.toml index df662ac26988..fde05e90ca6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -133,8 +133,9 @@ members = [ "cumulus/parachains/runtimes/test-utils", "cumulus/parachains/runtimes/testing/penpal", "cumulus/parachains/runtimes/testing/rococo-parachain", + "cumulus/polkadot-omni-node", + "cumulus/polkadot-omni-node/lib", "cumulus/polkadot-parachain", - "cumulus/polkadot-parachain/polkadot-parachain-lib", "cumulus/primitives/aura", "cumulus/primitives/core", "cumulus/primitives/parachain-inherent", @@ -541,6 +542,7 @@ members = [ ] default-members = [ + "cumulus/polkadot-omni-node", "cumulus/polkadot-parachain", "polkadot", "substrate/bin/node/cli", @@ -739,8 +741,8 @@ env_logger = { version = "0.11.2" } environmental = { version = "1.1.4", default-features = false } equivocation-detector = { path = "bridges/relays/equivocation" } ethabi = { version = "1.0.0", default-features = false, package = "ethabi-decode" } -ethbloom = { version = "0.13.0", default-features = false } -ethereum-types = { version = "0.14.1", default-features = false } +ethbloom = { version = "0.14.1", default-features = false } +ethereum-types = { version = "0.15.1", default-features = false } exit-future = { version = "0.2.0" } expander = { version = "2.0.0" } fatality = { version = "0.1.1" } @@ -1001,7 +1003,6 @@ parachains-relay = { path = "bridges/relays/parachains" } parachains-runtimes-test-utils = { path = "cumulus/parachains/runtimes/test-utils", default-features = false } parity-bytes = { version = "0.1.2", default-features = false } parity-db = { version = "0.4.12" } -parity-util-mem = { version = "0.12.0" } parity-wasm = { version = "0.45.0" } parking_lot = { version = "0.12.1", default-features = false } partial_sort = { version = "0.2.0" } @@ -1052,8 +1053,9 @@ polkadot-node-subsystem = { path = "polkadot/node/subsystem", default-features = polkadot-node-subsystem-test-helpers = { path = "polkadot/node/subsystem-test-helpers" } polkadot-node-subsystem-types = { path = "polkadot/node/subsystem-types", default-features = false } polkadot-node-subsystem-util = { path = "polkadot/node/subsystem-util", default-features = false } +polkadot-omni-node = { path = "cumulus/polkadot-omni-node", default-features = false } +polkadot-omni-node-lib = { path = "cumulus/polkadot-omni-node/lib", default-features = false } polkadot-overseer = { path = "polkadot/node/overseer", default-features = false } -polkadot-parachain-lib = { path = "cumulus/polkadot-parachain/polkadot-parachain-lib", default-features = false } polkadot-parachain-primitives = { path = "polkadot/parachain", default-features = false } polkadot-primitives = { path = "polkadot/primitives", default-features = false } polkadot-primitives-test-helpers = { path = "polkadot/primitives/test-helpers" } @@ -1075,7 +1077,7 @@ polkavm-derive = "0.9.1" polkavm-linker = "0.9.2" portpicker = { version = "0.1.1" } pretty_assertions = { version = "1.3.0" } -primitive-types = { version = "0.12.1", default-features = false } +primitive-types = { version = "0.13.1", default-features = false, features = ["num-traits"] } proc-macro-crate = { version = "3.0.0" } proc-macro-warning = { version = "1.0.0", default-features = false } proc-macro2 = { version = "1.0.86" } @@ -1103,7 +1105,7 @@ relay-substrate-client = { path = "bridges/relays/client-substrate" } relay-utils = { path = "bridges/relays/utils" } remote-externalities = { path = "substrate/utils/frame/remote-externalities", default-features = false, package = "frame-remote-externalities" } reqwest = { version = "0.11", default-features = false } -rlp = { version = "0.5.2", default-features = false } +rlp = { version = "0.6.1", default-features = false } rococo-emulated-chain = { path = "cumulus/parachains/integration-tests/emulated/chains/relays/rococo" } rococo-parachain-runtime = { path = "cumulus/parachains/runtimes/testing/rococo-parachain" } rococo-runtime = { path = "polkadot/runtime/rococo" } @@ -1280,7 +1282,7 @@ ssz_rs_derive = { version = "0.9.0", default-features = false } static_assertions = { version = "1.1.0", default-features = false } static_init = { version = "1.0.3" } structopt = { version = "0.3" } -strum = { version = "0.26.2", default-features = false } +strum = { version = "0.26.3", default-features = false } subkey = { path = "substrate/bin/utils/subkey", default-features = false } substrate-bip39 = { path = "substrate/utils/substrate-bip39", default-features = false } substrate-build-script-utils = { path = "substrate/utils/build-script-utils", default-features = false } diff --git a/bridges/modules/xcm-bridge-hub-router/src/lib.rs b/bridges/modules/xcm-bridge-hub-router/src/lib.rs index 7ba524e95b1d..fe8f5a2efdfb 100644 --- a/bridges/modules/xcm-bridge-hub-router/src/lib.rs +++ b/bridges/modules/xcm-bridge-hub-router/src/lib.rs @@ -99,7 +99,7 @@ pub mod pallet { type DestinationVersion: GetVersion; /// Actual message sender (`HRMP` or `DMP`) to the sibling bridge hub location. - type ToBridgeHubSender: SendXcm + InspectMessageQueues; + type ToBridgeHubSender: SendXcm; /// Local XCM channel manager. type LocalXcmChannelManager: XcmChannelStatusProvider; @@ -408,12 +408,12 @@ impl, I: 'static> SendXcm for Pallet { } impl, I: 'static> InspectMessageQueues for Pallet { - fn clear_messages() { - ViaBridgeHubExporter::::clear_messages() - } + fn clear_messages() {} + /// This router needs to implement `InspectMessageQueues` but doesn't have to + /// return any messages, since it just reuses the `XcmpQueue` router. fn get_messages() -> Vec<(VersionedLocation, Vec>)> { - ViaBridgeHubExporter::::get_messages() + Vec::new() } } @@ -646,34 +646,13 @@ mod tests { } #[test] - fn get_messages_works() { + fn get_messages_does_not_return_anything() { 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() - )], - ),], - ); + assert_eq!(XcmBridgeHubRouter::get_messages(), vec![]); }); } } diff --git a/bridges/primitives/polkadot-core/Cargo.toml b/bridges/primitives/polkadot-core/Cargo.toml index 366ee7aa948e..295fb281e9bb 100644 --- a/bridges/primitives/polkadot-core/Cargo.toml +++ b/bridges/primitives/polkadot-core/Cargo.toml @@ -12,7 +12,6 @@ workspace = true [dependencies] codec = { features = ["derive"], workspace = true } -parity-util-mem = { optional = true, workspace = true } scale-info = { features = ["derive"], workspace = true } serde = { optional = true, features = [ "derive", @@ -42,7 +41,6 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", - "parity-util-mem", "scale-info/std", "serde", "sp-core/std", diff --git a/bridges/primitives/polkadot-core/src/parachains.rs b/bridges/primitives/polkadot-core/src/parachains.rs index d54ee108386e..a8b1cf6eebf4 100644 --- a/bridges/primitives/polkadot-core/src/parachains.rs +++ b/bridges/primitives/polkadot-core/src/parachains.rs @@ -32,9 +32,6 @@ use sp_std::vec::Vec; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; -#[cfg(feature = "std")] -use parity_util_mem::MallocSizeOf; - /// Parachain id. /// /// This is an equivalent of the `polkadot_parachain_primitives::Id`, which is a compact-encoded @@ -71,7 +68,7 @@ impl From for ParaId { #[derive( PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode, RuntimeDebug, TypeInfo, Default, )] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash))] pub struct ParaHead(pub Vec); impl ParaHead { diff --git a/bridges/relays/lib-substrate-relay/src/cli/mod.rs b/bridges/relays/lib-substrate-relay/src/cli/mod.rs index be64866fc14b..d7aa38f1f2ba 100644 --- a/bridges/relays/lib-substrate-relay/src/cli/mod.rs +++ b/bridges/relays/lib-substrate-relay/src/cli/mod.rs @@ -20,7 +20,6 @@ use rbtag::BuildInfo; use sp_runtime::traits::TryConvert; use std::str::FromStr; use structopt::StructOpt; -use strum::{EnumString, VariantNames}; pub mod bridge; pub mod chain_schema; @@ -139,17 +138,6 @@ where } } -#[doc = "Runtime version params."] -#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, VariantNames)] -pub enum RuntimeVersionType { - /// Auto query version from chain - Auto, - /// Custom `spec_version` and `transaction_version` - Custom, - /// Read version from bundle dependencies directly. - Bundle, -} - #[cfg(test)] mod tests { use super::*; diff --git a/bridges/relays/lib-substrate-relay/src/cli/relay_headers.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_headers.rs index ea92a0c9acce..308b041c46f7 100644 --- a/bridges/relays/lib-substrate-relay/src/cli/relay_headers.rs +++ b/bridges/relays/lib-substrate-relay/src/cli/relay_headers.rs @@ -96,6 +96,7 @@ pub trait HeadersRelayer: RelayToRelayHeadersCliBridge { signer: target_sign, mortality: target_transactions_mortality, }; + Self::Finality::start_relay_guards(&target_client, target_client.can_start_version_guard()) .await?; 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 3878b081d6c3..71d3adc078e2 100644 --- a/bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs +++ b/bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs @@ -121,6 +121,8 @@ where anyhow::format_err!("Invalid laneId: {:?}!", invalid_lane_id) })?; + Self::start_relay_guards(&target_client, target_client.can_start_version_guard()).await?; + crate::messages::run::(MessagesRelayParams { source_client, source_transaction_params: TransactionParams { @@ -216,4 +218,18 @@ where ) .await } + + /// Add relay guards if required. + async fn start_relay_guards( + target_client: &impl Client, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.spec_version, + ); + } + Ok(()) + } } 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 77cd395ff722..83285b69f701 100644 --- a/bridges/relays/lib-substrate-relay/src/cli/relay_parachains.rs +++ b/bridges/relays/lib-substrate-relay/src/cli/relay_parachains.rs @@ -32,6 +32,7 @@ use crate::{ chain_schema::*, DefaultClient, PrometheusParams, }, + finality::SubstrateFinalitySyncPipeline, parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter}, TransactionParams, }; @@ -104,6 +105,12 @@ where data.prometheus_params.into_metrics_params()?; GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; + Self::RelayFinality::start_relay_guards( + target_client.target_client(), + target_client.target_client().can_start_version_guard(), + ) + .await?; + parachains_relay::parachains_loop::run( source_client, target_client, diff --git a/bridges/relays/parachains/src/parachains_loop.rs b/bridges/relays/parachains/src/parachains_loop.rs index 59ca458e6667..dfe6b230ceda 100644 --- a/bridges/relays/parachains/src/parachains_loop.rs +++ b/bridges/relays/parachains/src/parachains_loop.rs @@ -177,6 +177,14 @@ pub async fn run( where P::SourceRelayChain: Chain, { + log::info!( + target: "bridge", + "Starting {} -> {} finality proof relay: relaying (only_free_headers: {:?}) headers", + P::SourceParachain::NAME, + P::TargetChain::NAME, + only_free_headers, + ); + let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .with_metrics(metrics_params) diff --git a/bridges/snowbridge/docs/v2.md b/bridges/snowbridge/docs/v2.md new file mode 100644 index 000000000000..8ec440c47cec --- /dev/null +++ b/bridges/snowbridge/docs/v2.md @@ -0,0 +1,356 @@ +# Snowbridge V2 + +This design lowers fees, improves UX, improves relayer decentralization and allows "transacting" over the bridge, making +it a general-purpose bridge rather than just a token bridge. + +We're grateful to Adrian Catangiu, Francisco Aguirre, and others from the Parity XCM/Bridges team for their help and +collaboration on this design. + +## Summary + +- Unordered messaging +- All messages routed through AH +- Off-chain fee estimation +- P→E Fee Asset: WETH +- E→P Fee Asset: ETH +- Relayer rewards for both directions paid out on AH in WETH + +## Polkadot→Ethereum + +Given source parachain $S$, with native token $S^{'}$ and the initial xcm $x_0$ to be executed on $S$. + +### Step 1: User agent constructs initial XCM + +The user agent constructs an initial XCM message $x_0$ that will be executed on S. + +The fee amounts in this message should be high enough to enable dry-running, after which they will be lowered. + +### Step 2: User agent estimates fees + +- Given source parachain $S$, with native token $S^{'}$ and the initial xcm $x_0$ to be executed on $S$. +- The native currency $P^{'}$ (DOT) of the Polkadot relay chain, and $E^{'}$ (ETH) of Ethereum. +- Suppose that the user agent chooses relayer reward $r$ in $E^{'}$. +- Suppose that the exchange rates are $K_{P^{'}/S^{'}}$ and $K_{E^{'}/S^{'}}$. The user agent chooses a multiplier to + $\beta$ to cover volatility in these rates. + +Apply the following sequence operations: + +1. Dry-run $x_0$ on $S$ to receive xcm $x_1$ and cost $a$ in $S^{'}$ +2. Dry-run $x_1$ on AH to receive xcm $x_2$ and cost $b$ in $P^{'}$ (DOT) +3. Dry-run $x_2$ on BH to receive command $m$ and cost $c$ in $P^{'}$ (DOT) +4. Dry-run $m$ on Ethereum to receive cost $d$ in $E^{'}$ (ETH) + +The final cost to the user in $S^{'}$ is given by + +$$ +\beta \left(a + \frac{b + c}{K_{P^{'}/S^{'}}} + \frac{d + r}{K_{E^{'}/S^{'}}}\right) +$$ + +The user agent should perform a final update to xcm $x_0$, substituting the calculated fee amounts. + +### Step 3: User agent initiates bridging operation + +The user agent calls `pallet_xcm::execute` with the initial xcm $x_0$ + +```text +WithdrawAsset (KLT, 100) +PayFees (KLT, 20) +InitiateAssetsTransfer asset=(KLT, 60) remoteFee=(KLT, 20) dest=AH + ExchangeAsset give=(KLT, 20) want=(WETH, 1) + InitiateAssetsTransfer asset=(KLT, 40) remoteFee=(WETH, 1) dest=Ethereum + DepositAsset (KLT, 40) beneficiary=Bob +``` + +### Step 4: AH executes message x1 + +The message $x_1$ is application-specific: + +```text +ReserveAssetDeposited (KLT, 80) +PayFees (KLT, 20) +SetAssetClaimer Kilt/Alice +AliasOrigin Kilt/Alice +ExchangeAsset give=(KLT, 20) want=(WETH, 1) +InitiateAssetsTransfer asset=(KLT, 60) remoteFee=(WETH, 1) dest=Ethereum + DepositAsset (KLT, 60) beneficiary=Bob +``` + +or + +```text +*ReserveAssetDeposited (KLT, 80) +*PayFees (KLT, 20) +*SetAssetClaimer Kilt/Alice +*AliasOrigin Kilt/Alice +ExchangeAsset give=(KLT, 20) want=(WETH, 1) +InitiateAssetsTransfer asset=(KLT, 60) remoteFee=(WETH, 1) dest=Ethereum + DepositAsset (KLT, 60) beneficiary=Bob + Transact Bob.hello() +``` + +Note that the `SetAssetClaimer` instruction is placed before `AliasOrigin` in case AH fails to interpret the latter +instruction. + +In all cases, $x_1$ should contain the necessary instructions to: + +1. Pay fees for local execution using `PaysFees` +2. Obtain WETH for remote delivery fees. + +The XCM bridge-router on AH will charge a small fee to prevent spamming BH with bridge messages. This is necessary since +the `ExportMessage` instruction in message $x_2$ will have no execution fee on BH. For a similar reason, we should also +impose a minimum relayer reward of at least the existential deposit 0.1 DOT, which acts as a deposit to stop spamming +messages with 0 rewards. + +### Step 5: BH executes message x2 + +Message $x_2$ is parsed by the `SnowbridgeMessageExporter` in block $n$ with the following effects: + +- A bridge command $m$ is committed to binary merkle tree $M_n$. + - The transferred asset is parsed from `ReserveAssetDeposited` , `WithdrawAsset` or `TeleportedAssetReceived` + instructions for the local, destination and teleport asset transfer types respectively. + - The original origin is preserved through the `AliasOrigin` instruction. This will allow us to resolve agents for the + case of `Transact`. + - The message exporter must be able to support multiple assets and reserve types in the same message and potentially + multiple `Transacts`. + - The Message Exporter must be able to support multiple Deposited Assets. + - The Message Exporter must be able to parse `SetAssetClaimer` and allow the provided location to claim the assets on + BH in case of errors. +- Given relayer reward $r$ in WETH, set storage $P(\mathrm{hash}(m)) = r$. This is parsed from the `WithdrawAsset` and + `PayFees` instruction within `ExportMessage`. + +Note that WETH on AH & BH is a wrapped derivative of the +[WETH](https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2) ERC20 contract on Ethereum, which is +itself a wrapper over ETH, the native currency of Ethereum. For the purposes of this document you can consider them all +to be of equivalent value. + +```text +!WithdrawAsset(DOT, 10) +!PayFees (DOT, 10) +!ExportMessage dest=Ethereum + *ReserveAssetDeposited (KLT, 60) + *WithdrawAsset (WETH, 1) + *PayFees (WETH, 1) + *SetAssetClaimer Kilt/Alice + *AliasOrigin Kilt/Alice + DepositAsset (KLT, 60) beneficiary=Bob +``` + +or + +```text +!WithdrawAsset(DOT, 10) +!PayFees (DOT, 10) +!ExportMessage dest=Ethereum + *ReserveAssetDeposited (KLT, 80) + *PayFees (KLT, 20) + *SetAssetClaimer Kilt/Alice + *AliasOrigin Kilt/Alice + DepositAsset (KLT, 60) beneficiary=Bob + Transact Bob.hello() +``` + +### Step 6: Relayer relays message to Gateway + +1. A relayer _Charlie_ inspects storage $P$ to look for new messages to relay. Suppose it finds $\mathrm{hash}(m)$ + giving reward $r$. +2. The relayer queries $m$ from $M$ and constructs the necessary proofs. +3. The relayer dry-runs m on Ethereum to decide whether the message is profitable to deliver. +4. The relayer finally delivers the message together with a relayer-controlled address $u$ on AH where the relayer can + claim their reward after proof of delivery. + +### Step 7: Relayer delivers proof of delivery to BH + +The proof of delivery is essentially a merkle proof for the `InboundMessageAccepted` event log. + +When BH processes the proof of delivery: + +1. The command $m$ is removed from storage items $M$ and $P$. +2. The relayer reward is tracked in storage $R$, where $R(u)$ is the accumulated rewards that can be claimed by account + $u$. + +## Ethereum→Polkadot + +### Step 1: Submit send on Gateway + +The interface that the Gateway will use to initiate transfers will be similar to the interface from +`transfer_assets_using_type_and_then` extrinsic that we currently use to initiate transfers from the Polkadot to +Ethereum direction. + +1. It must allow multiple assets to be transferred and specify the transfer type: Local, Destination or Teleport asset + transfer types. It is the job of the User Agent/UX layer to fill in this information correctly. +2. It must allow specifying a destination which is `Address32`, `Address20` or a custom scale-encoded XCM payload that + is executed on the destination. This is how we will support `Transact` , the User Agent/UX layer can build a + scale-encoded payload with an encoded transact call. +3. The same interface is used for both PNA (Polkadot Assets) and ERC20 tokens. Internally we will still look up whether + the token is registered as a PNA or ERC20 for the purpose of minting/locking burning/unlocking logic. The asset + transfer type chosen by the UX layer will inform the XCM that is built from the message on BH. + +```solidity +enum Kind { + Index, + Address32, + Address20, + XCMPayload, +} + +struct Beneficiary { + Kind kind; + bytes data; +} + +enum AssetTransferType { + ReserveDeposit, ReserveWithdraw, Teleport +} + +struct Token { + AssetTransferType type; + address token; + uint128 amount; +} + +function send( + ParaID destinationChain, + Beneficiary calldata beneficiary, + Token[] tokens, + uint128 reward +) external payable; +``` + +Message enqueued $m_0$: + +```solidity +send( + 3022, // KILT Para Id + Address32(0x0000....), + [(ReserveWithdraw, KLT, 100)], + 10, // WETH +) +``` + +```solidity +send { value: 3 }( // Send 3 Eth for fees and reward + 3022, // KILT Para Id + XCMPayload( + DepositAsset (KLT, 100) dest=Bob + Transact Bob.hello() + ), + [(ReserveWithdraw, KLT, 100)], + 1, // 1 ETH of 3 needs to be for the reward, the rest is for fees +) +``` + +The User Agent/UX layer will need to estimate the fee required to be passed into the `send` method. This may be an issue +as we cannot Dry-Run something on Polkadot that has not even been submitted on Ethereum yet. We may need to make RPC API +to DryRun and get back the xcm that would be submitted to asset hub. + +### Step 2: Relayer relays message to Bridge Hub + +On-chain exchange rate is eliminated. Users pay remote delivery costs in ETH, and this amount is sent with the message +as WETH. The delivery fee can be claimed by the relayer on BH. + +The user agent applies a similar dry-running process as with +[Step 2: User agent estimates fees](https://www.notion.so/Step-2-User-agent-estimates-fees-113296aaabef8159bcd0e6dd2e64c3d0?pvs=21). + +The message is converted from $m_0$ to $x_0$ during message submission on BH. Dry-running submission will return $x_0$ +to the relayer so that it can verify it is profitable. + +### Step 3: AH receives $x_0$ from BH + +Submitting the message $m_0$ will cause the following XCM, $x_0$, to be built on BH and dispatched to AH. + +```text +WithdrawAsset (KLT, 100) +ReserveAssetDeposited(WETH, 2) +PayFees (WETH, 1) +SetAssetClaimer Kilt/Bob // derived from beneficiary on final destination +AliasOrigin Ethereum/Alice // derived from msg.sender +InitiateAssetsTransfer asset=(KLT, 100) remoteFee=(WETH, 1) dest=KLT + DepositAsset (KLT, 100) beneficiary=Bob +``` + +```text +WithdrawAsset (KLT, 100) +ReserveAssetDeposited(WETH, 2) +PayFees (WETH, 1) +SetAssetClaimer Kilt/Bob // derived from beneficiary on final destination +AliasOrigin Ethereum/Alice // derived from msg.sender +InitiateAssetsTransfer asset=(KLT, 100) remoteFee=(WETH, 1) dest=KLT + DepositAsset (KLT, 100) beneficiary=Bob + Transact Bob.hello() +``` + +### Step 4: KILT Receives XCM from AH + +The following XCM $x_1$ is received from AH on KILT. + +```text +*WithdrawAsset (KLT, 100) +*ReserveAssetDeposited (WETH, 1) +*PayFees (WETH, 1) +*SetAssetClaimer Ethereum/Alice +*AliasOrigin Ethereum/Alice // origin preserved from AH +SetAssetClaimer Bob +DepositAsset (KLT, 100) beneficiary=Bob +``` + +```text +*WithdrawAsset (KLT, 100) +*ReserveAssetDeposited (WETH, 1) +*PayFees (WETH, 1) +*SetAssetClaimer Ethereum/Alice +*AliasOrigin Ethereum/Alice // origin preserved from AH +SetAssetClaimer Bob +DepositAsset (KLT, 100) beneficiary=Bob +Transact Bob.hello() // executes with the origin from AH +``` + +## Relayer Rewards + +The tracking and disbursement of relayer rewards for both directions has been unified. Rewards are accumulated on BH in +WETH and must be manually claimed. As part of the claims flow, an XCM instruction is sent to AH to mint the WETH into +the deposit account chosen by the relayer. + +To claim, call following extrinsic, where $o$ is rewards account (origin), and $w$ is account on AH where the WETH will +be minted. + +$$ +\mathrm{claim}(o,w) +$$ + +For tax accounting purposes it might be desirable that $o \neq w$. + +## Top-Up + +Top-up of the relayer reward is viable to implement for either direction as extrinsics on Bridge Hub and Ethereum +respectively. + +## Origin Preservation + +Origins for transact will be preserved by use of the `AliasOrigin` instruction. This instruction will have the following +rules that parachain runtimes will need to allow: + +1. `AliasOrigin` can behave like `DescendOrigin`. This is safe because it respects the hierarchy of multi-locations and + does not allow jumping up. Meaning no escalation of privileges. + 1. Example location `Ethereum` can alias into `Ethereum/Alice` because we are descending in origin and this + essentially is how the `DescendOrigin` instruction works. +2. `AliasOrigin` must allow AH to alias into bridged locations such as + `{ parents: 2, interior: GlobalConsensus(Ethereum) }` and all of its internal locations so that AH can act as a proxy + for the bridge on parachains. + +`AliasOrigin` will be inserted by every `InitiateAssetTransfer` instruction on the source parachain, populated with the +contents of the origin register, essentially forwarding the origin of the source to the destination. + +RFCS: + +[https://github.com/polkadot-fellows/RFCs/pull/122](https://github.com/polkadot-fellows/RFCs/pull/122) + +[https://github.com/polkadot-fellows/RFCs/blob/main/text/0100-xcm-multi-type-asset-transfer.md](https://github.com/polkadot-fellows/RFCs/blob/main/text/0100-xcm-multi-type-asset-transfer.md) + +## Parachain Requirements + +1. Pallet-xcm.execute enabled. +2. XCM payment and dry run apis implemented. +3. Must accept WETH needed for fees. Though in future user agents can inject `ExchangeAsset` instructions to obtain + WETH. +4. Trust AH as a reserve for bridged assets. +5. Origin Preservation rules configured which allow asset hub to impersonate bridged addresses. diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs index 6d0eb3145250..003dd3180192 100644 --- a/cumulus/pallets/parachain-system/src/lib.rs +++ b/cumulus/pallets/parachain-system/src/lib.rs @@ -1627,7 +1627,11 @@ impl InspectMessageQueues for Pallet { .map(|encoded_message| VersionedXcm::<()>::decode(&mut &encoded_message[..]).unwrap()) .collect(); - vec![(VersionedLocation::V4(Parent.into()), messages)] + if messages.is_empty() { + vec![] + } else { + vec![(VersionedLocation::from(Location::parent()), messages)] + } } } diff --git a/cumulus/parachains/chain-specs/coretime-polkadot.json b/cumulus/parachains/chain-specs/coretime-polkadot.json index 806231db7646..e4f947d2afc9 100644 --- a/cumulus/parachains/chain-specs/coretime-polkadot.json +++ b/cumulus/parachains/chain-specs/coretime-polkadot.json @@ -10,7 +10,9 @@ "/dns4/coretime-polkadot.boot.stake.plus/tcp/30332/wss/p2p/12D3KooWFJ2yBTKFKYwgKUjfY3F7XfaxHV8hY6fbJu5oMkpP7wZ9", "/dns4/coretime-polkadot.boot.stake.plus/tcp/31332/wss/p2p/12D3KooWCy5pToLafcQzPHn5kadxAftmF6Eh8ZJGPXhSeXSUDfjv", "/dns/coretime-polkadot-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWGpmytHjdthrkKgkXDZyKm9ABtJ2PtGk9NStJDG4pChy9", - "/dns/coretime-polkadot-boot-ng.dwellir.com/tcp/30361/p2p/12D3KooWGpmytHjdthrkKgkXDZyKm9ABtJ2PtGk9NStJDG4pChy9" + "/dns/coretime-polkadot-boot-ng.dwellir.com/tcp/30361/p2p/12D3KooWGpmytHjdthrkKgkXDZyKm9ABtJ2PtGk9NStJDG4pChy9", + "/dns/coretime-polkadot-bootnode.radiumblock.com/tcp/30333/p2p/12D3KooWFsQphSqvqjVyKcEdR1D7LPcXHqjmy6ASuJrTr5isk9JU", + "/dns/coretime-polkadot-bootnode.radiumblock.com/tcp/30336/wss/p2p/12D3KooWFsQphSqvqjVyKcEdR1D7LPcXHqjmy6ASuJrTr5isk9JU" ], "telemetryEndpoints": null, "protocolId": null, @@ -91,4 +93,4 @@ "childrenDefault": {} } } -} \ No newline at end of file +} diff --git a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs index 578bca84ce5a..68926b04bfe6 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs @@ -403,3 +403,51 @@ macro_rules! test_chain_can_claim_assets { } }; } + +#[macro_export] +macro_rules! test_dry_run_transfer_across_pk_bridge { + ( $sender_asset_hub:ty, $sender_bridge_hub:ty, $destination:expr ) => { + $crate::macros::paste::paste! { + use frame_support::{dispatch::RawOrigin, traits::fungible}; + use sp_runtime::AccountId32; + use xcm::prelude::*; + use xcm_runtime_apis::dry_run::runtime_decl_for_dry_run_api::DryRunApiV1; + + let who = AccountId32::new([1u8; 32]); + let transfer_amount = 10_000_000_000_000u128; + let initial_balance = transfer_amount * 10; + + // Bridge setup. + $sender_asset_hub::force_xcm_version($destination, XCM_VERSION); + open_bridge_between_asset_hub_rococo_and_asset_hub_westend(); + + <$sender_asset_hub as TestExt>::execute_with(|| { + type Runtime = <$sender_asset_hub as Chain>::Runtime; + type RuntimeCall = <$sender_asset_hub as Chain>::RuntimeCall; + type OriginCaller = <$sender_asset_hub as Chain>::OriginCaller; + type Balances = <$sender_asset_hub as [<$sender_asset_hub Pallet>]>::Balances; + + // Give some initial funds. + >::set_balance(&who, initial_balance); + + let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::transfer_assets { + dest: Box::new(VersionedLocation::from($destination)), + beneficiary: Box::new(VersionedLocation::from(Junction::AccountId32 { + id: who.clone().into(), + network: None, + })), + assets: Box::new(VersionedAssets::from(vec![ + (Parent, transfer_amount).into(), + ])), + fee_asset_item: 0, + weight_limit: Unlimited, + }); + let result = Runtime::dry_run_call(OriginCaller::system(RawOrigin::Signed(who)), call).unwrap(); + // We assert the dry run succeeds and sends only one message to the local bridge hub. + assert!(result.execution_result.is_ok()); + assert_eq!(result.forwarded_xcms.len(), 1); + assert_eq!(result.forwarded_xcms[0].0, VersionedLocation::from(Location::new(1, [Parachain($sender_bridge_hub::para_id().into())]))); + }); + } + }; +} 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 86ace7d564e8..9f6fe78a33ee 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 @@ -28,6 +28,7 @@ sp-runtime = { workspace = true } xcm = { workspace = true } pallet-xcm = { workspace = true } xcm-executor = { workspace = true } +xcm-runtime-apis = { workspace = true } # Bridges pallet-bridge-messages = { workspace = true } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs index e83b28076789..a542de16de5f 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs @@ -33,8 +33,8 @@ mod imports { pub use emulated_integration_tests_common::{ accounts::ALICE, impls::Inspect, - test_parachain_is_trusted_teleporter, test_parachain_is_trusted_teleporter_for_relay, - test_relay_is_trusted_teleporter, + test_dry_run_transfer_across_pk_bridge, test_parachain_is_trusted_teleporter, + test_parachain_is_trusted_teleporter_for_relay, test_relay_is_trusted_teleporter, xcm_emulator::{ assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, TestExt, }, diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs index 11930798da44..f1e2a6dcca61 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs @@ -534,3 +534,12 @@ fn send_back_wnds_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_weste assert!(receiver_wnds_after > receiver_wnds_before); assert!(receiver_wnds_after <= receiver_wnds_before + amount); } + +#[test] +fn dry_run_transfer_to_westend_sends_xcm_to_bridge_hub() { + test_dry_run_transfer_across_pk_bridge!( + AssetHubRococo, + BridgeHubRococo, + asset_hub_westend_location() + ); +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml index 44121cbfdafb..b87f25ac0f01 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml @@ -29,6 +29,7 @@ sp-runtime = { workspace = true } xcm = { workspace = true } pallet-xcm = { workspace = true } xcm-executor = { workspace = true } +xcm-runtime-apis = { workspace = true } # Bridges pallet-bridge-messages = { workspace = true } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs index d9b92cb11e92..9228700c0198 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs @@ -32,8 +32,8 @@ mod imports { pub use emulated_integration_tests_common::{ accounts::ALICE, impls::Inspect, - test_parachain_is_trusted_teleporter, test_parachain_is_trusted_teleporter_for_relay, - test_relay_is_trusted_teleporter, + test_dry_run_transfer_across_pk_bridge, test_parachain_is_trusted_teleporter, + test_parachain_is_trusted_teleporter_for_relay, test_relay_is_trusted_teleporter, xcm_emulator::{ assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, TestExt, }, diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs index 6492c520234f..7def637a66e4 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs @@ -554,3 +554,12 @@ fn send_back_rocs_from_penpal_westend_through_asset_hub_westend_to_asset_hub_roc assert!(receiver_rocs_after > receiver_rocs_before); assert!(receiver_rocs_after <= receiver_rocs_before + amount); } + +#[test] +fn dry_run_transfer_to_rococo_sends_xcm_to_bridge_hub() { + test_dry_run_transfer_across_pk_bridge!( + AssetHubWestend, + BridgeHubWestend, + asset_hub_rococo_location() + ); +} diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs index e8cc9d02fb0e..40801f66a47b 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs @@ -72,7 +72,10 @@ impl Config for Runtime { type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; type MaxDelegateDependencies = ConstU32<32>; type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; - type Migrations = (pallet_contracts::migration::v16::Migration,); + #[cfg(not(feature = "runtime-benchmarks"))] + type Migrations = (); + #[cfg(feature = "runtime-benchmarks")] + type Migrations = pallet_contracts::migration::codegen::BenchMigrations; type RuntimeHoldReason = RuntimeHoldReason; type Debug = (); type Environment = (); diff --git a/cumulus/polkadot-omni-node/Cargo.toml b/cumulus/polkadot-omni-node/Cargo.toml new file mode 100644 index 000000000000..a736e1ef80c5 --- /dev/null +++ b/cumulus/polkadot-omni-node/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "polkadot-omni-node" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +build = "build.rs" +description = "Generic binary that can run a parachain node with u32 block number and Aura consensus" +license = "Apache-2.0" + +[lints] +workspace = true + +[dependencies] +color-eyre = { workspace = true } + +# Local +polkadot-omni-node-lib = { workspace = true } + +[build-dependencies] +substrate-build-script-utils = { workspace = true, default-features = true } + +[features] +default = [] +runtime-benchmarks = [ + "polkadot-omni-node-lib/runtime-benchmarks", +] +try-runtime = [ + "polkadot-omni-node-lib/try-runtime", +] diff --git a/cumulus/polkadot-omni-node/build.rs b/cumulus/polkadot-omni-node/build.rs new file mode 100644 index 000000000000..8c498735eae9 --- /dev/null +++ b/cumulus/polkadot-omni-node/build.rs @@ -0,0 +1,22 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// 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 . + +use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; + +fn main() { + generate_cargo_keys(); + rerun_if_git_head_changed(); +} diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/Cargo.toml b/cumulus/polkadot-omni-node/lib/Cargo.toml similarity index 99% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/Cargo.toml rename to cumulus/polkadot-omni-node/lib/Cargo.toml index 5e4c9fcf1a3d..3dd482f4adaf 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/Cargo.toml +++ b/cumulus/polkadot-omni-node/lib/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "polkadot-parachain-lib" +name = "polkadot-omni-node-lib" version = "0.1.0" authors.workspace = true edition.workspace = true diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs b/cumulus/polkadot-omni-node/lib/src/cli.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs rename to cumulus/polkadot-omni-node/lib/src/cli.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs b/cumulus/polkadot-omni-node/lib/src/command.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs rename to cumulus/polkadot-omni-node/lib/src/command.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/aura.rs b/cumulus/polkadot-omni-node/lib/src/common/aura.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/aura.rs rename to cumulus/polkadot-omni-node/lib/src/common/aura.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/chain_spec.rs b/cumulus/polkadot-omni-node/lib/src/common/chain_spec.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/chain_spec.rs rename to cumulus/polkadot-omni-node/lib/src/common/chain_spec.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/command.rs b/cumulus/polkadot-omni-node/lib/src/common/command.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/command.rs rename to cumulus/polkadot-omni-node/lib/src/common/command.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs b/cumulus/polkadot-omni-node/lib/src/common/mod.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs rename to cumulus/polkadot-omni-node/lib/src/common/mod.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/rpc.rs b/cumulus/polkadot-omni-node/lib/src/common/rpc.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/rpc.rs rename to cumulus/polkadot-omni-node/lib/src/common/rpc.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/runtime.rs b/cumulus/polkadot-omni-node/lib/src/common/runtime.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/runtime.rs rename to cumulus/polkadot-omni-node/lib/src/common/runtime.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/spec.rs b/cumulus/polkadot-omni-node/lib/src/common/spec.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/spec.rs rename to cumulus/polkadot-omni-node/lib/src/common/spec.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/types.rs b/cumulus/polkadot-omni-node/lib/src/common/types.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/types.rs rename to cumulus/polkadot-omni-node/lib/src/common/types.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/fake_runtime_api/mod.rs b/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/mod.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/fake_runtime_api/mod.rs rename to cumulus/polkadot-omni-node/lib/src/fake_runtime_api/mod.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/fake_runtime_api/utils.rs b/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/fake_runtime_api/utils.rs rename to cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/lib.rs b/cumulus/polkadot-omni-node/lib/src/lib.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/lib.rs rename to cumulus/polkadot-omni-node/lib/src/lib.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs b/cumulus/polkadot-omni-node/lib/src/nodes/aura.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs rename to cumulus/polkadot-omni-node/lib/src/nodes/aura.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs b/cumulus/polkadot-omni-node/lib/src/nodes/manual_seal.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs rename to cumulus/polkadot-omni-node/lib/src/nodes/manual_seal.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs b/cumulus/polkadot-omni-node/lib/src/nodes/mod.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs rename to cumulus/polkadot-omni-node/lib/src/nodes/mod.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/benchmark_storage_works.rs b/cumulus/polkadot-omni-node/lib/src/tests/benchmark_storage_works.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/benchmark_storage_works.rs rename to cumulus/polkadot-omni-node/lib/src/tests/benchmark_storage_works.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/common.rs b/cumulus/polkadot-omni-node/lib/src/tests/common.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/common.rs rename to cumulus/polkadot-omni-node/lib/src/tests/common.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/polkadot_argument_parsing.rs b/cumulus/polkadot-omni-node/lib/src/tests/polkadot_argument_parsing.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/polkadot_argument_parsing.rs rename to cumulus/polkadot-omni-node/lib/src/tests/polkadot_argument_parsing.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/polkadot_mdns_issue.rs b/cumulus/polkadot-omni-node/lib/src/tests/polkadot_mdns_issue.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/polkadot_mdns_issue.rs rename to cumulus/polkadot-omni-node/lib/src/tests/polkadot_mdns_issue.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/purge_chain_works.rs b/cumulus/polkadot-omni-node/lib/src/tests/purge_chain_works.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/purge_chain_works.rs rename to cumulus/polkadot-omni-node/lib/src/tests/purge_chain_works.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/running_the_node_and_interrupt.rs b/cumulus/polkadot-omni-node/lib/src/tests/running_the_node_and_interrupt.rs similarity index 100% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/tests/running_the_node_and_interrupt.rs rename to cumulus/polkadot-omni-node/lib/src/tests/running_the_node_and_interrupt.rs diff --git a/cumulus/polkadot-omni-node/src/main.rs b/cumulus/polkadot-omni-node/src/main.rs new file mode 100644 index 000000000000..a86ec6f6fde6 --- /dev/null +++ b/cumulus/polkadot-omni-node/src/main.rs @@ -0,0 +1,60 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// 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 . + +//! Basic polkadot omni-node. +//! +//! It can be used to start a parachain node from a provided chain spec file. +//! It is only compatible with runtimes that use block number `u32` and `Aura` consensus. +//! +//! Example: `polkadot-omni-node --chain [chain_spec.json]` + +#![warn(missing_docs)] +#![warn(unused_extern_crates)] + +use polkadot_omni_node_lib::{ + chain_spec::DiskChainSpecLoader, run, runtime::DefaultRuntimeResolver, CliConfig as CliConfigT, + RunConfig, +}; + +struct CliConfig; + +impl CliConfigT for CliConfig { + fn impl_version() -> String { + env!("SUBSTRATE_CLI_IMPL_VERSION").into() + } + + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } + + fn support_url() -> String { + "https://github.com/paritytech/polkadot-sdk/issues/new".into() + } + + fn copyright_start_year() -> u16 { + 2017 + } +} + +fn main() -> color_eyre::eyre::Result<()> { + color_eyre::install()?; + + let config = RunConfig { + chain_spec_loader: Box::new(DiskChainSpecLoader), + runtime_resolver: Box::new(DefaultRuntimeResolver), + }; + Ok(run::(config)?) +} diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index fb95853c492a..426679ce0cd5 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -22,7 +22,7 @@ serde = { features = ["derive"], workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } # Local -polkadot-parachain-lib = { features = ["rococo-native", "westend-native"], workspace = true } +polkadot-omni-node-lib = { features = ["rococo-native", "westend-native"], workspace = true } rococo-parachain-runtime = { workspace = true } glutton-westend-runtime = { workspace = true } asset-hub-rococo-runtime = { workspace = true, default-features = true } @@ -37,10 +37,6 @@ penpal-runtime = { workspace = true } people-rococo-runtime = { workspace = true } people-westend-runtime = { workspace = true } parachains-common = { workspace = true, default-features = true } -testnet-parachains-constants = { features = [ - "rococo", - "westend", -], workspace = true } # Substrate sp-core = { workspace = true, default-features = true } @@ -55,9 +51,6 @@ xcm = { workspace = true, default-features = true } # Cumulus cumulus-primitives-core = { workspace = true, default-features = true } -# Bridges -bp-messages = { workspace = true, default-features = true } - [build-dependencies] substrate-build-script-utils = { workspace = true, default-features = true } @@ -66,7 +59,7 @@ default = [] runtime-benchmarks = [ "cumulus-primitives-core/runtime-benchmarks", "parachains-common/runtime-benchmarks", - "polkadot-parachain-lib/runtime-benchmarks", + "polkadot-omni-node-lib/runtime-benchmarks", "sc-service/runtime-benchmarks", "asset-hub-rococo-runtime/runtime-benchmarks", @@ -84,7 +77,7 @@ runtime-benchmarks = [ "rococo-parachain-runtime/runtime-benchmarks", ] try-runtime = [ - "polkadot-parachain-lib/try-runtime", + "polkadot-omni-node-lib/try-runtime", "asset-hub-rococo-runtime/try-runtime", "asset-hub-westend-runtime/try-runtime", diff --git a/cumulus/polkadot-parachain/src/chain_spec/asset_hubs.rs b/cumulus/polkadot-parachain/src/chain_spec/asset_hubs.rs index 699c0b5ce775..ec2afc743de8 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/asset_hubs.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/asset_hubs.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . -use polkadot_parachain_lib::chain_spec::{Extensions, GenericChainSpec}; +use polkadot_omni_node_lib::chain_spec::{Extensions, GenericChainSpec}; use sc_service::ChainType; pub fn asset_hub_westend_development_config() -> GenericChainSpec { diff --git a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs index af399be9eacf..839e93d0a67b 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs @@ -15,7 +15,7 @@ // along with Cumulus. If not, see . use cumulus_primitives_core::ParaId; -use polkadot_parachain_lib::chain_spec::GenericChainSpec; +use polkadot_omni_node_lib::chain_spec::GenericChainSpec; use sc_chain_spec::{ChainSpec, ChainType}; use std::str::FromStr; @@ -127,7 +127,7 @@ fn ensure_id(id: &str) -> Result<&str, String> { /// Sub-module for Rococo setup pub mod rococo { use super::{ChainType, ParaId}; - use polkadot_parachain_lib::chain_spec::{Extensions, GenericChainSpec}; + use polkadot_omni_node_lib::chain_spec::{Extensions, GenericChainSpec}; pub(crate) const BRIDGE_HUB_ROCOCO: &str = "bridge-hub-rococo"; pub(crate) const BRIDGE_HUB_ROCOCO_LOCAL: &str = "bridge-hub-rococo-local"; @@ -175,7 +175,7 @@ pub mod kusama { /// Sub-module for Westend setup. pub mod westend { use super::{ChainType, ParaId}; - use polkadot_parachain_lib::chain_spec::{Extensions, GenericChainSpec}; + use polkadot_omni_node_lib::chain_spec::{Extensions, GenericChainSpec}; pub(crate) const BRIDGE_HUB_WESTEND: &str = "bridge-hub-westend"; pub(crate) const BRIDGE_HUB_WESTEND_LOCAL: &str = "bridge-hub-westend-local"; diff --git a/cumulus/polkadot-parachain/src/chain_spec/collectives.rs b/cumulus/polkadot-parachain/src/chain_spec/collectives.rs index 227e15fdff8d..0d2f66b5acc0 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/collectives.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/collectives.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . -use polkadot_parachain_lib::chain_spec::{Extensions, GenericChainSpec}; +use polkadot_omni_node_lib::chain_spec::{Extensions, GenericChainSpec}; use sc_service::ChainType; /// Collectives Westend Development Config. diff --git a/cumulus/polkadot-parachain/src/chain_spec/coretime.rs b/cumulus/polkadot-parachain/src/chain_spec/coretime.rs index fec3f56e6d35..e42e95ad16f8 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/coretime.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/coretime.rs @@ -15,7 +15,7 @@ // along with Cumulus. If not, see . use cumulus_primitives_core::ParaId; -use polkadot_parachain_lib::chain_spec::GenericChainSpec; +use polkadot_omni_node_lib::chain_spec::GenericChainSpec; use sc_chain_spec::{ChainSpec, ChainType}; use std::{borrow::Cow, str::FromStr}; @@ -150,7 +150,7 @@ pub mod rococo { get_account_id_from_seed, get_collator_keys_from_seed, SAFE_XCM_VERSION, }; use parachains_common::{AccountId, AuraId, Balance}; - use polkadot_parachain_lib::chain_spec::{Extensions, GenericChainSpec}; + use polkadot_omni_node_lib::chain_spec::{Extensions, GenericChainSpec}; use sc_chain_spec::ChainType; use sp_core::sr25519; @@ -248,7 +248,7 @@ pub mod westend { get_account_id_from_seed, get_collator_keys_from_seed, SAFE_XCM_VERSION, }; use parachains_common::{AccountId, AuraId, Balance}; - use polkadot_parachain_lib::chain_spec::Extensions; + use polkadot_omni_node_lib::chain_spec::Extensions; use sp_core::sr25519; pub(crate) const CORETIME_WESTEND: &str = "coretime-westend"; diff --git a/cumulus/polkadot-parachain/src/chain_spec/glutton.rs b/cumulus/polkadot-parachain/src/chain_spec/glutton.rs index 136411b93e8b..e70f86f725a1 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/glutton.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/glutton.rs @@ -17,7 +17,7 @@ use crate::chain_spec::get_account_id_from_seed; use cumulus_primitives_core::ParaId; use parachains_common::AuraId; -use polkadot_parachain_lib::chain_spec::{Extensions, GenericChainSpec}; +use polkadot_omni_node_lib::chain_spec::{Extensions, GenericChainSpec}; use sc_service::ChainType; use sp_core::sr25519; diff --git a/cumulus/polkadot-parachain/src/chain_spec/mod.rs b/cumulus/polkadot-parachain/src/chain_spec/mod.rs index 16fdbdc38656..a820fdbd13e8 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/mod.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/mod.rs @@ -18,7 +18,7 @@ use cumulus_primitives_core::ParaId; pub(crate) use parachains_common::genesis_config_helpers::{ get_account_id_from_seed, get_collator_keys_from_seed, get_from_seed, }; -use polkadot_parachain_lib::{ +use polkadot_omni_node_lib::{ chain_spec::{GenericChainSpec, LoadSpec}, runtime::{ AuraConsensusId, BlockNumber, Consensus, Runtime, RuntimeResolver as RuntimeResolverT, diff --git a/cumulus/polkadot-parachain/src/chain_spec/penpal.rs b/cumulus/polkadot-parachain/src/chain_spec/penpal.rs index 5645bf06b67b..006c5c9b53c2 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/penpal.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/penpal.rs @@ -17,7 +17,7 @@ use crate::chain_spec::{get_account_id_from_seed, get_collator_keys_from_seed, SAFE_XCM_VERSION}; use cumulus_primitives_core::ParaId; use parachains_common::{AccountId, AuraId}; -use polkadot_parachain_lib::chain_spec::{Extensions, GenericChainSpec}; +use polkadot_omni_node_lib::chain_spec::{Extensions, GenericChainSpec}; use sc_service::ChainType; use sp_core::sr25519; diff --git a/cumulus/polkadot-parachain/src/chain_spec/people.rs b/cumulus/polkadot-parachain/src/chain_spec/people.rs index 3c1150d95422..b89f1c3a5fe6 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/people.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/people.rs @@ -16,7 +16,7 @@ use cumulus_primitives_core::ParaId; use parachains_common::Balance as PeopleBalance; -use polkadot_parachain_lib::chain_spec::GenericChainSpec; +use polkadot_omni_node_lib::chain_spec::GenericChainSpec; use sc_chain_spec::ChainSpec; use std::str::FromStr; @@ -124,7 +124,7 @@ pub mod rococo { get_account_id_from_seed, get_collator_keys_from_seed, SAFE_XCM_VERSION, }; use parachains_common::{AccountId, AuraId}; - use polkadot_parachain_lib::chain_spec::{Extensions, GenericChainSpec}; + use polkadot_omni_node_lib::chain_spec::{Extensions, GenericChainSpec}; use sc_chain_spec::ChainType; use sp_core::sr25519; @@ -234,7 +234,7 @@ pub mod westend { get_account_id_from_seed, get_collator_keys_from_seed, SAFE_XCM_VERSION, }; use parachains_common::{AccountId, AuraId}; - use polkadot_parachain_lib::chain_spec::{Extensions, GenericChainSpec}; + use polkadot_omni_node_lib::chain_spec::{Extensions, GenericChainSpec}; use sc_chain_spec::ChainType; use sp_core::sr25519; diff --git a/cumulus/polkadot-parachain/src/chain_spec/rococo_parachain.rs b/cumulus/polkadot-parachain/src/chain_spec/rococo_parachain.rs index 251926838d24..39762f590cfe 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/rococo_parachain.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/rococo_parachain.rs @@ -20,7 +20,7 @@ use crate::chain_spec::{get_from_seed, SAFE_XCM_VERSION}; use cumulus_primitives_core::ParaId; use hex_literal::hex; use parachains_common::{genesis_config_helpers::get_account_id_from_seed, AccountId}; -use polkadot_parachain_lib::chain_spec::{Extensions, GenericChainSpec}; +use polkadot_omni_node_lib::chain_spec::{Extensions, GenericChainSpec}; use rococo_parachain_runtime::AuraId; use sc_chain_spec::ChainType; use sp_core::{crypto::UncheckedInto, sr25519}; diff --git a/cumulus/polkadot-parachain/src/main.rs b/cumulus/polkadot-parachain/src/main.rs index f2dce552c51a..c8464be937cc 100644 --- a/cumulus/polkadot-parachain/src/main.rs +++ b/cumulus/polkadot-parachain/src/main.rs @@ -21,7 +21,7 @@ mod chain_spec; -use polkadot_parachain_lib::{run, CliConfig as CliConfigT, RunConfig}; +use polkadot_omni_node_lib::{run, CliConfig as CliConfigT, RunConfig}; struct CliConfig; diff --git a/docs/contributor/commands-readme.md b/docs/contributor/commands-readme.md index 861c3ac784d5..3a0fadc3bb25 100644 --- a/docs/contributor/commands-readme.md +++ b/docs/contributor/commands-readme.md @@ -44,4 +44,5 @@ the default branch. The regex in cmd.yml is: `^(\/cmd )([-\/\s\w.=:]+)$` accepts only alphanumeric, space, "-", "/", "=", ":", "." chars. `/cmd bench --runtime bridge-hub-westend --pallet=pallet_name` +`/cmd prdoc --audience runtime_dev runtime_user --bump patch --force` `/cmd update-ui --image=docker.io/paritytech/ci-unified:bullseye-1.77.0-2024-04-10-v202407161507 --clean` diff --git a/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs b/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs index 14a0b6107966..812e674d163b 100644 --- a/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs +++ b/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs @@ -85,7 +85,7 @@ //! This phase consists of plugging in the new slot-based collator. //! //! 1. In `node/src/service.rs` import the slot based collator instead of the lookahead collator. -#![doc = docify::embed!("../../cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs", slot_based_colator_import)] +#![doc = docify::embed!("../../cumulus/polkadot-omni-node/lib/src/nodes/aura.rs", slot_based_colator_import)] //! //! 2. In `start_consensus()` //! - Remove the `overseer_handle` param (also remove the @@ -94,7 +94,7 @@ //! `slot_drift` field with a value of `Duration::from_secs(1)`. //! - Replace the single future returned by `aura::run` with the two futures returned by it and //! spawn them as separate tasks: -#![doc = docify::embed!("../../cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs", launch_slot_based_collator)] +#![doc = docify::embed!("../../cumulus/polkadot-omni-node/lib/src/nodes/aura.rs", launch_slot_based_collator)] //! //! 3. In `start_parachain_node()` remove the `overseer_handle` param passed to `start_consensus`. //! diff --git a/polkadot/node/core/approval-voting/src/lib.rs b/polkadot/node/core/approval-voting/src/lib.rs index 835098293050..0cb977c58021 100644 --- a/polkadot/node/core/approval-voting/src/lib.rs +++ b/polkadot/node/core/approval-voting/src/lib.rs @@ -38,7 +38,7 @@ use polkadot_node_subsystem::{ ApprovalVotingMessage, AssignmentCheckError, AssignmentCheckResult, AvailabilityRecoveryMessage, BlockDescription, CandidateValidationMessage, ChainApiMessage, ChainSelectionMessage, CheckedIndirectAssignment, CheckedIndirectSignedApprovalVote, - DisputeCoordinatorMessage, HighestApprovedAncestorBlock, RuntimeApiMessage, + DisputeCoordinatorMessage, HighestApprovedAncestorBlock, PvfExecKind, RuntimeApiMessage, RuntimeApiRequest, }, overseer, FromOrchestra, OverseerSignal, SpawnedSubsystem, SubsystemError, SubsystemResult, @@ -53,8 +53,8 @@ use polkadot_node_subsystem_util::{ }; use polkadot_primitives::{ ApprovalVoteMultipleCandidates, ApprovalVotingParams, BlockNumber, CandidateHash, - CandidateIndex, CandidateReceipt, CoreIndex, ExecutorParams, GroupIndex, Hash, PvfExecKind, - SessionIndex, SessionInfo, ValidatorId, ValidatorIndex, ValidatorPair, ValidatorSignature, + CandidateIndex, CandidateReceipt, CoreIndex, ExecutorParams, GroupIndex, Hash, SessionIndex, + SessionInfo, ValidatorId, ValidatorIndex, ValidatorPair, ValidatorSignature, }; use sc_keystore::LocalKeystore; use sp_application_crypto::Pair; diff --git a/polkadot/node/core/backing/Cargo.toml b/polkadot/node/core/backing/Cargo.toml index 1b52afc309bc..bd56a3ad693b 100644 --- a/polkadot/node/core/backing/Cargo.toml +++ b/polkadot/node/core/backing/Cargo.toml @@ -14,6 +14,7 @@ futures = { workspace = true } sp-keystore = { workspace = true, default-features = true } polkadot-primitives = { workspace = true, default-features = true } polkadot-node-primitives = { workspace = true, default-features = true } +polkadot-parachain-primitives = { workspace = true, default-features = true } polkadot-node-subsystem = { workspace = true, default-features = true } polkadot-node-subsystem-util = { workspace = true, default-features = true } polkadot-erasure-coding = { workspace = true, default-features = true } diff --git a/polkadot/node/core/backing/src/lib.rs b/polkadot/node/core/backing/src/lib.rs index f276321c87ed..4463fb34b510 100644 --- a/polkadot/node/core/backing/src/lib.rs +++ b/polkadot/node/core/backing/src/lib.rs @@ -89,8 +89,9 @@ use polkadot_node_subsystem::{ AvailabilityDistributionMessage, AvailabilityStoreMessage, CanSecondRequest, CandidateBackingMessage, CandidateValidationMessage, CollatorProtocolMessage, HypotheticalCandidate, HypotheticalMembershipRequest, IntroduceSecondedCandidateRequest, - ProspectiveParachainsMessage, ProvisionableData, ProvisionerMessage, RuntimeApiMessage, - RuntimeApiRequest, StatementDistributionMessage, StoreAvailableDataError, + ProspectiveParachainsMessage, ProvisionableData, ProvisionerMessage, PvfExecKind, + RuntimeApiMessage, RuntimeApiRequest, StatementDistributionMessage, + StoreAvailableDataError, }, overseer, ActiveLeavesUpdate, FromOrchestra, OverseerSignal, SpawnedSubsystem, SubsystemError, }; @@ -105,12 +106,13 @@ use polkadot_node_subsystem_util::{ }, Validator, }; +use polkadot_parachain_primitives::primitives::IsSystem; use polkadot_primitives::{ node_features::FeatureIndex, BackedCandidate, CandidateCommitments, CandidateHash, CandidateReceipt, CommittedCandidateReceipt, CoreIndex, CoreState, ExecutorParams, GroupIndex, GroupRotationInfo, Hash, Id as ParaId, IndexedVec, NodeFeatures, PersistedValidationData, - PvfExecKind, SessionIndex, SigningContext, ValidationCode, ValidatorId, ValidatorIndex, - ValidatorSignature, ValidityAttestation, + SessionIndex, SigningContext, ValidationCode, ValidatorId, ValidatorIndex, ValidatorSignature, + ValidityAttestation, }; use polkadot_statement_table::{ generic::AttestedCandidate as TableAttestedCandidate, @@ -625,6 +627,7 @@ async fn request_candidate_validation( executor_params: ExecutorParams, ) -> Result { let (tx, rx) = oneshot::channel(); + let is_system = candidate_receipt.descriptor.para_id.is_system(); sender .send_message(CandidateValidationMessage::ValidateFromExhaustive { @@ -633,7 +636,11 @@ async fn request_candidate_validation( candidate_receipt, pov, executor_params, - exec_kind: PvfExecKind::Backing, + exec_kind: if is_system { + PvfExecKind::BackingSystemParas + } else { + PvfExecKind::Backing + }, response_sender: tx, }) .await; diff --git a/polkadot/node/core/backing/src/tests/mod.rs b/polkadot/node/core/backing/src/tests/mod.rs index 10eb45b82d12..d9c1fc9499e5 100644 --- a/polkadot/node/core/backing/src/tests/mod.rs +++ b/polkadot/node/core/backing/src/tests/mod.rs @@ -30,7 +30,7 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_primitives::{ node_features, CandidateDescriptor, GroupRotationInfo, HeadData, PersistedValidationData, - PvfExecKind, ScheduledCore, SessionIndex, LEGACY_MIN_BACKING_VOTES, + ScheduledCore, SessionIndex, LEGACY_MIN_BACKING_VOTES, }; use polkadot_primitives_test_helpers::{ dummy_candidate_receipt_bad_sig, dummy_collator, dummy_collator_signature, @@ -434,7 +434,7 @@ async fn assert_validate_from_exhaustive( ) if validation_data == *assert_pvd && validation_code == *assert_validation_code && *pov == *assert_pov && &candidate_receipt.descriptor == assert_candidate.descriptor() && - exec_kind == PvfExecKind::Backing && + exec_kind == PvfExecKind::BackingSystemParas && candidate_receipt.commitments_hash == assert_candidate.commitments.hash() => { response_sender.send(Ok(ValidationResult::Valid( @@ -651,7 +651,7 @@ fn backing_works(#[case] elastic_scaling_mvp: bool) { ) if validation_data == pvd_ab && validation_code == validation_code_ab && *pov == pov_ab && &candidate_receipt.descriptor == candidate_a.descriptor() && - exec_kind == PvfExecKind::Backing && + exec_kind == PvfExecKind::BackingSystemParas && candidate_receipt.commitments_hash == candidate_a_commitments_hash => { response_sender.send(Ok( @@ -1287,7 +1287,7 @@ fn backing_works_while_validation_ongoing() { ) if validation_data == pvd_abc && validation_code == validation_code_abc && *pov == pov_abc && &candidate_receipt.descriptor == candidate_a.descriptor() && - exec_kind == PvfExecKind::Backing && + exec_kind == PvfExecKind::BackingSystemParas && candidate_a_commitments_hash == candidate_receipt.commitments_hash => { // we never validate the candidate. our local node @@ -1454,7 +1454,7 @@ fn backing_misbehavior_works() { ) if validation_data == pvd_a && validation_code == validation_code_a && *pov == pov_a && &candidate_receipt.descriptor == candidate_a.descriptor() && - exec_kind == PvfExecKind::Backing && + exec_kind == PvfExecKind::BackingSystemParas && candidate_a_commitments_hash == candidate_receipt.commitments_hash => { response_sender.send(Ok( @@ -1621,7 +1621,7 @@ fn backing_dont_second_invalid() { ) if validation_data == pvd_a && validation_code == validation_code_a && *pov == pov_block_a && &candidate_receipt.descriptor == candidate_a.descriptor() && - exec_kind == PvfExecKind::Backing && + exec_kind == PvfExecKind::BackingSystemParas && candidate_a.commitments.hash() == candidate_receipt.commitments_hash => { response_sender.send(Ok(ValidationResult::Invalid(InvalidCandidate::BadReturn))).unwrap(); @@ -1661,7 +1661,7 @@ fn backing_dont_second_invalid() { ) if validation_data == pvd_b && validation_code == validation_code_b && *pov == pov_block_b && &candidate_receipt.descriptor == candidate_b.descriptor() && - exec_kind == PvfExecKind::Backing && + exec_kind == PvfExecKind::BackingSystemParas && candidate_b.commitments.hash() == candidate_receipt.commitments_hash => { response_sender.send(Ok( @@ -1788,7 +1788,7 @@ fn backing_second_after_first_fails_works() { ) if validation_data == pvd_a && validation_code == validation_code_a && *pov == pov_a && &candidate_receipt.descriptor == candidate.descriptor() && - exec_kind == PvfExecKind::Backing && + exec_kind == PvfExecKind::BackingSystemParas && candidate.commitments.hash() == candidate_receipt.commitments_hash => { response_sender.send(Ok(ValidationResult::Invalid(InvalidCandidate::BadReturn))).unwrap(); @@ -1932,7 +1932,7 @@ fn backing_works_after_failed_validation() { ) if validation_data == pvd_a && validation_code == validation_code_a && *pov == pov_a && &candidate_receipt.descriptor == candidate.descriptor() && - exec_kind == PvfExecKind::Backing && + exec_kind == PvfExecKind::BackingSystemParas && candidate.commitments.hash() == candidate_receipt.commitments_hash => { response_sender.send(Err(ValidationFailed("Internal test error".into()))).unwrap(); @@ -2211,7 +2211,7 @@ fn retry_works() { ) if validation_data == pvd_a && validation_code == validation_code_a && *pov == pov_a && &candidate_receipt.descriptor == candidate.descriptor() && - exec_kind == PvfExecKind::Backing && + exec_kind == PvfExecKind::BackingSystemParas && candidate.commitments.hash() == candidate_receipt.commitments_hash ); virtual_overseer @@ -2753,7 +2753,7 @@ fn validator_ignores_statements_from_disabled_validators() { ) if validation_data == pvd && validation_code == expected_validation_code && *pov == expected_pov && &candidate_receipt.descriptor == candidate.descriptor() && - exec_kind == PvfExecKind::Backing && + exec_kind == PvfExecKind::BackingSystemParas && candidate_commitments_hash == candidate_receipt.commitments_hash => { response_sender.send(Ok( diff --git a/polkadot/node/core/backing/src/tests/prospective_parachains.rs b/polkadot/node/core/backing/src/tests/prospective_parachains.rs index 15bc0b4a1139..57b2fabd43b0 100644 --- a/polkadot/node/core/backing/src/tests/prospective_parachains.rs +++ b/polkadot/node/core/backing/src/tests/prospective_parachains.rs @@ -276,7 +276,7 @@ async fn assert_validate_seconded_candidate( &validation_code == assert_validation_code && &*pov == assert_pov && &candidate_receipt.descriptor == candidate.descriptor() && - exec_kind == PvfExecKind::Backing && + exec_kind == PvfExecKind::BackingSystemParas && candidate.commitments.hash() == candidate_receipt.commitments_hash => { response_sender.send(Ok(ValidationResult::Valid( diff --git a/polkadot/node/core/candidate-validation/src/lib.rs b/polkadot/node/core/candidate-validation/src/lib.rs index 50505d733916..e875be9b5df9 100644 --- a/polkadot/node/core/candidate-validation/src/lib.rs +++ b/polkadot/node/core/candidate-validation/src/lib.rs @@ -31,8 +31,8 @@ use polkadot_node_primitives::{InvalidCandidate, PoV, ValidationResult}; use polkadot_node_subsystem::{ errors::RuntimeApiError, messages::{ - CandidateValidationMessage, PreCheckOutcome, RuntimeApiMessage, RuntimeApiRequest, - ValidationFailed, + CandidateValidationMessage, PreCheckOutcome, PvfExecKind, RuntimeApiMessage, + RuntimeApiRequest, ValidationFailed, }, overseer, FromOrchestra, OverseerSignal, SpawnedSubsystem, SubsystemError, SubsystemResult, SubsystemSender, @@ -46,8 +46,9 @@ use polkadot_primitives::{ DEFAULT_LENIENT_PREPARATION_TIMEOUT, DEFAULT_PRECHECK_PREPARATION_TIMEOUT, }, AuthorityDiscoveryId, CandidateCommitments, CandidateDescriptor, CandidateEvent, - CandidateReceipt, ExecutorParams, Hash, PersistedValidationData, PvfExecKind, PvfPrepKind, - SessionIndex, ValidationCode, ValidationCodeHash, ValidatorId, + CandidateReceipt, ExecutorParams, Hash, PersistedValidationData, + PvfExecKind as RuntimePvfExecKind, PvfPrepKind, SessionIndex, ValidationCode, + ValidationCodeHash, ValidatorId, }; use sp_application_crypto::{AppCrypto, ByteArray}; use sp_keystore::KeystorePtr; @@ -667,9 +668,9 @@ async fn validate_candidate_exhaustive( let result = match exec_kind { // Retry is disabled to reduce the chance of nondeterministic blocks getting backed and // honest backers getting slashed. - PvfExecKind::Backing => { + PvfExecKind::Backing | PvfExecKind::BackingSystemParas => { let prep_timeout = pvf_prep_timeout(&executor_params, PvfPrepKind::Prepare); - let exec_timeout = pvf_exec_timeout(&executor_params, exec_kind); + let exec_timeout = pvf_exec_timeout(&executor_params, exec_kind.into()); let pvf = PvfPrepData::from_code( validation_code.0, executor_params, @@ -683,20 +684,22 @@ async fn validate_candidate_exhaustive( exec_timeout, persisted_validation_data.clone(), pov, - polkadot_node_core_pvf::Priority::Normal, + exec_kind.into(), + exec_kind, ) .await }, - PvfExecKind::Approval => + PvfExecKind::Approval | PvfExecKind::Dispute => validation_backend .validate_candidate_with_retry( validation_code.0, - pvf_exec_timeout(&executor_params, exec_kind), + pvf_exec_timeout(&executor_params, exec_kind.into()), persisted_validation_data.clone(), pov, executor_params, PVF_APPROVAL_EXECUTION_RETRY_DELAY, - polkadot_node_core_pvf::Priority::Critical, + exec_kind.into(), + exec_kind, ) .await, }; @@ -784,6 +787,8 @@ trait ValidationBackend { pov: Arc, // The priority for the preparation job. prepare_priority: polkadot_node_core_pvf::Priority, + // The kind for the execution job. + exec_kind: PvfExecKind, ) -> Result; /// Tries executing a PVF. Will retry once if an error is encountered that may have @@ -804,6 +809,8 @@ trait ValidationBackend { retry_delay: Duration, // The priority for the preparation job. prepare_priority: polkadot_node_core_pvf::Priority, + // The kind for the execution job. + exec_kind: PvfExecKind, ) -> Result { let prep_timeout = pvf_prep_timeout(&executor_params, PvfPrepKind::Prepare); // Construct the PVF a single time, since it is an expensive operation. Cloning it is cheap. @@ -825,6 +832,7 @@ trait ValidationBackend { pvd.clone(), pov.clone(), prepare_priority, + exec_kind, ) .await; if validation_result.is_ok() { @@ -905,6 +913,7 @@ trait ValidationBackend { pvd.clone(), pov.clone(), prepare_priority, + exec_kind, ) .await; } @@ -929,9 +938,13 @@ impl ValidationBackend for ValidationHost { pov: Arc, // The priority for the preparation job. prepare_priority: polkadot_node_core_pvf::Priority, + // The kind for the execution job. + exec_kind: PvfExecKind, ) -> Result { let (tx, rx) = oneshot::channel(); - if let Err(err) = self.execute_pvf(pvf, exec_timeout, pvd, pov, prepare_priority, tx).await + if let Err(err) = self + .execute_pvf(pvf, exec_timeout, pvd, pov, prepare_priority, exec_kind, tx) + .await { return Err(InternalValidationError::HostCommunication(format!( "cannot send pvf to the validation host, it might have shut down: {:?}", @@ -1023,12 +1036,12 @@ fn pvf_prep_timeout(executor_params: &ExecutorParams, kind: PvfPrepKind) -> Dura /// This should be much longer than the backing execution timeout to ensure that in the /// absence of extremely large disparities between hardware, blocks that pass backing are /// considered executable by approval checkers or dispute participants. -fn pvf_exec_timeout(executor_params: &ExecutorParams, kind: PvfExecKind) -> Duration { +fn pvf_exec_timeout(executor_params: &ExecutorParams, kind: RuntimePvfExecKind) -> Duration { if let Some(timeout) = executor_params.pvf_exec_timeout(kind) { return timeout } match kind { - PvfExecKind::Backing => DEFAULT_BACKING_EXECUTION_TIMEOUT, - PvfExecKind::Approval => DEFAULT_APPROVAL_EXECUTION_TIMEOUT, + RuntimePvfExecKind::Backing => DEFAULT_BACKING_EXECUTION_TIMEOUT, + RuntimePvfExecKind::Approval => DEFAULT_APPROVAL_EXECUTION_TIMEOUT, } } diff --git a/polkadot/node/core/candidate-validation/src/tests.rs b/polkadot/node/core/candidate-validation/src/tests.rs index 46de55e4836e..2f7baf4abb61 100644 --- a/polkadot/node/core/candidate-validation/src/tests.rs +++ b/polkadot/node/core/candidate-validation/src/tests.rs @@ -17,6 +17,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use super::*; +use crate::PvfExecKind; use assert_matches::assert_matches; use futures::executor; use polkadot_node_core_pvf::PrepareError; @@ -441,6 +442,7 @@ impl ValidationBackend for MockValidateCandidateBackend { _pvd: Arc, _pov: Arc, _prepare_priority: polkadot_node_core_pvf::Priority, + _exec_kind: PvfExecKind, ) -> Result { // This is expected to panic if called more times than expected, indicating an error in the // test. @@ -1023,6 +1025,7 @@ impl ValidationBackend for MockPreCheckBackend { _pvd: Arc, _pov: Arc, _prepare_priority: polkadot_node_core_pvf::Priority, + _exec_kind: PvfExecKind, ) -> Result { unreachable!() } @@ -1177,6 +1180,7 @@ impl ValidationBackend for MockHeadsUp { _pvd: Arc, _pov: Arc, _prepare_priority: polkadot_node_core_pvf::Priority, + _exec_kind: PvfExecKind, ) -> Result { unreachable!() } diff --git a/polkadot/node/core/dispute-coordinator/src/participation/mod.rs b/polkadot/node/core/dispute-coordinator/src/participation/mod.rs index b58ce570f8ff..2220f65e20a7 100644 --- a/polkadot/node/core/dispute-coordinator/src/participation/mod.rs +++ b/polkadot/node/core/dispute-coordinator/src/participation/mod.rs @@ -27,13 +27,11 @@ use futures_timer::Delay; use polkadot_node_primitives::ValidationResult; use polkadot_node_subsystem::{ - messages::{AvailabilityRecoveryMessage, CandidateValidationMessage}, + messages::{AvailabilityRecoveryMessage, CandidateValidationMessage, PvfExecKind}, overseer, ActiveLeavesUpdate, RecoveryError, }; use polkadot_node_subsystem_util::runtime::get_validation_code_by_hash; -use polkadot_primitives::{ - BlockNumber, CandidateHash, CandidateReceipt, Hash, PvfExecKind, SessionIndex, -}; +use polkadot_primitives::{BlockNumber, CandidateHash, CandidateReceipt, Hash, SessionIndex}; use crate::LOG_TARGET; @@ -387,7 +385,7 @@ async fn participate( candidate_receipt: req.candidate_receipt().clone(), pov: available_data.pov, executor_params: req.executor_params(), - exec_kind: PvfExecKind::Approval, + exec_kind: PvfExecKind::Dispute, response_sender: validation_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 a80553828ac6..a6ab6f16df05 100644 --- a/polkadot/node/core/dispute-coordinator/src/participation/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/participation/tests.rs @@ -26,7 +26,7 @@ use codec::Encode; use polkadot_node_primitives::{AvailableData, BlockData, InvalidCandidate, PoV}; use polkadot_node_subsystem::{ messages::{ - AllMessages, ChainApiMessage, DisputeCoordinatorMessage, RuntimeApiMessage, + AllMessages, ChainApiMessage, DisputeCoordinatorMessage, PvfExecKind, RuntimeApiMessage, RuntimeApiRequest, }, ActiveLeavesUpdate, SpawnGlue, @@ -116,7 +116,7 @@ pub async fn participation_full_happy_path( ctx_handle.recv().await, AllMessages::CandidateValidation( CandidateValidationMessage::ValidateFromExhaustive { candidate_receipt, exec_kind, response_sender, .. } - ) if exec_kind == PvfExecKind::Approval => { + ) if exec_kind == PvfExecKind::Dispute => { if expected_commitments_hash != candidate_receipt.commitments_hash { response_sender.send(Ok(ValidationResult::Invalid(InvalidCandidate::CommitmentsHashMismatch))).unwrap(); } else { @@ -450,7 +450,7 @@ fn cast_invalid_vote_if_validation_fails_or_is_invalid() { ctx_handle.recv().await, AllMessages::CandidateValidation( CandidateValidationMessage::ValidateFromExhaustive { exec_kind, response_sender, .. } - ) if exec_kind == PvfExecKind::Approval => { + ) if exec_kind == PvfExecKind::Dispute => { response_sender.send(Ok(ValidationResult::Invalid(InvalidCandidate::Timeout))).unwrap(); }, "overseer did not receive candidate validation message", @@ -487,7 +487,7 @@ fn cast_invalid_vote_if_commitments_dont_match() { ctx_handle.recv().await, AllMessages::CandidateValidation( CandidateValidationMessage::ValidateFromExhaustive { exec_kind, response_sender, .. } - ) if exec_kind == PvfExecKind::Approval => { + ) if exec_kind == PvfExecKind::Dispute => { response_sender.send(Ok(ValidationResult::Invalid(InvalidCandidate::CommitmentsHashMismatch))).unwrap(); }, "overseer did not receive candidate validation message", @@ -524,7 +524,7 @@ fn cast_valid_vote_if_validation_passes() { ctx_handle.recv().await, AllMessages::CandidateValidation( CandidateValidationMessage::ValidateFromExhaustive { exec_kind, response_sender, .. } - ) if exec_kind == PvfExecKind::Approval => { + ) if exec_kind == PvfExecKind::Dispute => { response_sender.send(Ok(ValidationResult::Valid(dummy_candidate_commitments(None), PersistedValidationData::default()))).unwrap(); }, "overseer did not receive candidate validation message", diff --git a/polkadot/node/core/pvf/Cargo.toml b/polkadot/node/core/pvf/Cargo.toml index d603af04bf06..13fcdc69a99a 100644 --- a/polkadot/node/core/pvf/Cargo.toml +++ b/polkadot/node/core/pvf/Cargo.toml @@ -24,6 +24,7 @@ slotmap = { workspace = true } tempfile = { workspace = true } thiserror = { workspace = true } tokio = { features = ["fs", "process"], workspace = true, default-features = true } +strum = { features = ["derive"], workspace = true, default-features = true } codec = { features = [ "derive", diff --git a/polkadot/node/core/pvf/src/execute/queue.rs b/polkadot/node/core/pvf/src/execute/queue.rs index 11031bf1074a..2ac5116912eb 100644 --- a/polkadot/node/core/pvf/src/execute/queue.rs +++ b/polkadot/node/core/pvf/src/execute/queue.rs @@ -35,15 +35,17 @@ use polkadot_node_core_pvf_common::{ SecurityStatus, }; use polkadot_node_primitives::PoV; +use polkadot_node_subsystem::messages::PvfExecKind; use polkadot_primitives::{ExecutorParams, ExecutorParamsHash, PersistedValidationData}; use slotmap::HopSlotMap; use std::{ - collections::VecDeque, + collections::{HashMap, VecDeque}, fmt, path::PathBuf, sync::Arc, time::{Duration, Instant}, }; +use strum::IntoEnumIterator; /// The amount of time a job for which the queue does not have a compatible worker may wait in the /// queue. After that time passes, the queue will kill the first worker which becomes idle to @@ -74,6 +76,7 @@ pub struct PendingExecutionRequest { pub pov: Arc, pub executor_params: ExecutorParams, pub result_tx: ResultSender, + pub exec_kind: PvfExecKind, } struct ExecuteJob { @@ -140,7 +143,7 @@ impl Workers { enum QueueEvent { Spawn(IdleWorker, WorkerHandle, ExecuteJob), - StartWork( + FinishWork( Worker, Result, ArtifactId, @@ -166,7 +169,7 @@ struct Queue { security_status: SecurityStatus, /// The queue of jobs that are waiting for a worker to pick up. - queue: VecDeque, + unscheduled: Unscheduled, workers: Workers, mux: Mux, } @@ -192,7 +195,7 @@ impl Queue { security_status, to_queue_rx, from_queue_tx, - queue: VecDeque::new(), + unscheduled: Unscheduled::new(), mux: Mux::new(), workers: Workers { running: HopSlotMap::with_capacity_and_key(10), @@ -226,9 +229,13 @@ impl Queue { /// If all the workers are busy or the queue is empty, it does nothing. /// Should be called every time a new job arrives to the queue or a job finishes. fn try_assign_next_job(&mut self, finished_worker: Option) { - // New jobs are always pushed to the tail of the queue; the one at its head is always - // the eldest one. - let eldest = if let Some(eldest) = self.queue.get(0) { eldest } else { return }; + // We always work at the same priority level + let priority = self.unscheduled.select_next_priority(); + let Some(queue) = self.unscheduled.get_mut(priority) else { return }; + + // New jobs are always pushed to the tail of the queue based on their priority; + // the one at its head of each queue is always the eldest one. + let eldest = if let Some(eldest) = queue.get(0) { eldest } else { return }; // By default, we're going to execute the eldest job on any worker slot available, even if // we have to kill and re-spawn a worker @@ -240,7 +247,7 @@ impl Queue { if eldest.waiting_since.elapsed() < MAX_KEEP_WAITING { if let Some(finished_worker) = finished_worker { if let Some(worker_data) = self.workers.running.get(finished_worker) { - for (i, job) in self.queue.iter().enumerate() { + for (i, job) in queue.iter().enumerate() { if worker_data.executor_params_hash == job.executor_params.hash() { (worker, job_index) = (Some(finished_worker), i); break @@ -252,7 +259,7 @@ impl Queue { if worker.is_none() { // Try to obtain a worker for the job - worker = self.workers.find_available(self.queue[job_index].executor_params.hash()); + worker = self.workers.find_available(queue[job_index].executor_params.hash()); } if worker.is_none() { @@ -270,13 +277,15 @@ impl Queue { return } - let job = self.queue.remove(job_index).expect("Job is just checked to be in queue; qed"); + let job = queue.remove(job_index).expect("Job is just checked to be in queue; qed"); if let Some(worker) = worker { assign(self, worker, job); } else { spawn_extra_worker(self, job); } + self.metrics.on_execute_kind(priority); + self.unscheduled.mark_scheduled(priority); } } @@ -297,7 +306,7 @@ async fn purge_dead(metrics: &Metrics, workers: &mut Workers) { fn handle_to_queue(queue: &mut Queue, to_queue: ToQueue) { let ToQueue::Enqueue { artifact, pending_execution_request } = to_queue; - let PendingExecutionRequest { exec_timeout, pvd, pov, executor_params, result_tx } = + let PendingExecutionRequest { exec_timeout, pvd, pov, executor_params, result_tx, exec_kind } = pending_execution_request; gum::debug!( target: LOG_TARGET, @@ -315,7 +324,7 @@ fn handle_to_queue(queue: &mut Queue, to_queue: ToQueue) { result_tx, waiting_since: Instant::now(), }; - queue.queue.push_back(job); + queue.unscheduled.add(job, exec_kind); queue.try_assign_next_job(None); } @@ -324,7 +333,7 @@ async fn handle_mux(queue: &mut Queue, event: QueueEvent) { QueueEvent::Spawn(idle, handle, job) => { handle_worker_spawned(queue, idle, handle, job); }, - QueueEvent::StartWork(worker, outcome, artifact_id, result_tx) => { + QueueEvent::FinishWork(worker, outcome, artifact_id, result_tx) => { handle_job_finish(queue, worker, outcome, artifact_id, result_tx).await; }, } @@ -606,7 +615,7 @@ fn assign(queue: &mut Queue, worker: Worker, job: ExecuteJob) { job.pov, ) .await; - QueueEvent::StartWork(worker, result, job.artifact.id, job.result_tx) + QueueEvent::FinishWork(worker, result, job.artifact.id, job.result_tx) } .boxed(), ); @@ -638,3 +647,297 @@ pub fn start( .run(); (to_queue_tx, from_queue_rx, run) } + +struct Unscheduled { + unscheduled: HashMap>, + counter: HashMap, +} + +impl Unscheduled { + /// We keep track of every scheduled job in the `counter`, but reset it if the total number of + /// counted jobs reaches the threshold. This number is set as the maximum amount of jobs per + /// relay chain block possible with 4 CPU cores and 2 seconds of execution time. Under normal + /// conditions, the maximum expected queue size is at least vrf_module_samples(6) + 1 for + /// backing a parachain candidate. A buffer is added to cover situations where more work + /// arrives in the queue. + const SCHEDULING_WINDOW_SIZE: usize = 12; + + /// A threshold in percentages indicates how much time a current priority can "steal" from lower + /// priorities. Given the `SCHEDULING_WINDOW_SIZE` is 12 and all job priorities are present: + /// - Disputes consume 70% or 8 jobs in a row. + /// - The remaining 30% of original 100% is allocated for approval and all backing jobs. + /// - 80% or 3 jobs of the remaining goes to approvals. + /// - The remaining 6% of original 100% is allocated for all backing jobs. + /// - 100% or 1 job of the remaining goes to backing system parachains. + /// - Nothing is left for backing. + /// - The counter is restarted and the distribution starts from the beginning. + /// + /// This system might seem complex, but we operate with the remaining percentages because: + /// - Not all job types are present in each block. If we used parts of the original 100%, + /// approvals could not exceed 24%, even if there are no disputes. + /// - We cannot fully prioritize backing system parachains over backing other parachains based + /// on the distribution of the original 100%. + const PRIORITY_ALLOCATION_THRESHOLDS: &'static [(PvfExecKind, usize)] = &[ + (PvfExecKind::Dispute, 70), + (PvfExecKind::Approval, 80), + (PvfExecKind::BackingSystemParas, 100), + (PvfExecKind::Backing, 100), + ]; + + fn new() -> Self { + Self { + unscheduled: PvfExecKind::iter().map(|priority| (priority, VecDeque::new())).collect(), + counter: PvfExecKind::iter().map(|priority| (priority, 0)).collect(), + } + } + + fn select_next_priority(&self) -> PvfExecKind { + gum::debug!( + target: LOG_TARGET, + unscheduled = ?self.unscheduled.iter().map(|(p, q)| (*p, q.len())).collect::>(), + counter = ?self.counter, + "Selecting next execution priority...", + ); + + let priority = PvfExecKind::iter() + .find(|priority| self.has_pending(priority) && !self.has_reached_threshold(priority)) + .unwrap_or_else(|| { + PvfExecKind::iter() + .find(|priority| self.has_pending(priority)) + .unwrap_or(PvfExecKind::Backing) + }); + + gum::debug!( + target: LOG_TARGET, + ?priority, + "Selected next execution priority", + ); + + priority + } + + fn get_mut(&mut self, priority: PvfExecKind) -> Option<&mut VecDeque> { + self.unscheduled.get_mut(&priority) + } + + fn add(&mut self, job: ExecuteJob, priority: PvfExecKind) { + self.unscheduled.entry(priority).or_default().push_back(job); + } + + fn has_pending(&self, priority: &PvfExecKind) -> bool { + !self.unscheduled.get(priority).unwrap_or(&VecDeque::new()).is_empty() + } + + fn priority_allocation_threshold(priority: &PvfExecKind) -> Option { + Self::PRIORITY_ALLOCATION_THRESHOLDS.iter().find_map(|&(p, value)| { + if p == *priority { + Some(value) + } else { + None + } + }) + } + + /// Checks if a given priority has reached its allocated threshold + /// The thresholds are defined in `PRIORITY_ALLOCATION_THRESHOLDS`. + fn has_reached_threshold(&self, priority: &PvfExecKind) -> bool { + let Some(threshold) = Self::priority_allocation_threshold(priority) else { return false }; + let Some(count) = self.counter.get(&priority) else { return false }; + // Every time we iterate by lower level priorities + let total_scheduled_at_priority_or_lower: usize = self + .counter + .iter() + .filter_map(|(p, c)| if *p >= *priority { Some(c) } else { None }) + .sum(); + if total_scheduled_at_priority_or_lower == 0 { + return false + } + + let has_reached_threshold = count * 100 / total_scheduled_at_priority_or_lower >= threshold; + + gum::debug!( + target: LOG_TARGET, + ?priority, + ?count, + ?total_scheduled_at_priority_or_lower, + "Execution priority has {}reached threshold: {}/{}%", + if has_reached_threshold {""} else {"not "}, + count * 100 / total_scheduled_at_priority_or_lower, + threshold + ); + + has_reached_threshold + } + + fn mark_scheduled(&mut self, priority: PvfExecKind) { + *self.counter.entry(priority).or_default() += 1; + + if self.counter.values().sum::() >= Self::SCHEDULING_WINDOW_SIZE { + self.reset_counter(); + } + } + + fn reset_counter(&mut self) { + self.counter = PvfExecKind::iter().map(|kind| (kind, 0)).collect(); + } +} + +#[cfg(test)] +mod tests { + use polkadot_node_primitives::BlockData; + use sp_core::H256; + + use super::*; + use crate::testing::artifact_id; + use std::time::Duration; + + fn create_execution_job() -> ExecuteJob { + let (result_tx, _result_rx) = oneshot::channel(); + let pvd = Arc::new(PersistedValidationData { + parent_head: Default::default(), + relay_parent_number: 1u32, + relay_parent_storage_root: H256::default(), + max_pov_size: 4096 * 1024, + }); + let pov = Arc::new(PoV { block_data: BlockData(b"pov".to_vec()) }); + ExecuteJob { + artifact: ArtifactPathId { id: artifact_id(0), path: PathBuf::new() }, + exec_timeout: Duration::from_secs(10), + pvd, + pov, + executor_params: ExecutorParams::default(), + result_tx, + waiting_since: Instant::now(), + } + } + + #[test] + fn test_unscheduled_add() { + let mut unscheduled = Unscheduled::new(); + + PvfExecKind::iter().for_each(|priority| { + unscheduled.add(create_execution_job(), priority); + }); + + PvfExecKind::iter().for_each(|priority| { + let queue = unscheduled.unscheduled.get(&priority).unwrap(); + assert_eq!(queue.len(), 1); + }); + } + + #[test] + fn test_unscheduled_priority_distribution() { + use PvfExecKind::*; + + let mut priorities = vec![]; + + let mut unscheduled = Unscheduled::new(); + for _ in 0..Unscheduled::SCHEDULING_WINDOW_SIZE { + unscheduled.add(create_execution_job(), Dispute); + unscheduled.add(create_execution_job(), Approval); + unscheduled.add(create_execution_job(), BackingSystemParas); + unscheduled.add(create_execution_job(), Backing); + } + + for _ in 0..Unscheduled::SCHEDULING_WINDOW_SIZE { + let priority = unscheduled.select_next_priority(); + priorities.push(priority); + unscheduled.mark_scheduled(priority); + } + + assert_eq!(priorities.iter().filter(|v| **v == Dispute).count(), 8); + assert_eq!(priorities.iter().filter(|v| **v == Approval).count(), 3); + assert_eq!(priorities.iter().filter(|v| **v == BackingSystemParas).count(), 1); + } + + #[test] + fn test_unscheduled_priority_distribution_without_backing_system_paras() { + use PvfExecKind::*; + + let mut priorities = vec![]; + + let mut unscheduled = Unscheduled::new(); + for _ in 0..Unscheduled::SCHEDULING_WINDOW_SIZE { + unscheduled.add(create_execution_job(), Dispute); + unscheduled.add(create_execution_job(), Approval); + unscheduled.add(create_execution_job(), Backing); + } + + for _ in 0..Unscheduled::SCHEDULING_WINDOW_SIZE { + let priority = unscheduled.select_next_priority(); + priorities.push(priority); + unscheduled.mark_scheduled(priority); + } + + assert_eq!(priorities.iter().filter(|v| **v == Dispute).count(), 8); + assert_eq!(priorities.iter().filter(|v| **v == Approval).count(), 3); + assert_eq!(priorities.iter().filter(|v| **v == Backing).count(), 1); + } + + #[test] + fn test_unscheduled_priority_distribution_without_disputes() { + use PvfExecKind::*; + + let mut priorities = vec![]; + + let mut unscheduled = Unscheduled::new(); + for _ in 0..Unscheduled::SCHEDULING_WINDOW_SIZE { + unscheduled.add(create_execution_job(), Approval); + unscheduled.add(create_execution_job(), BackingSystemParas); + unscheduled.add(create_execution_job(), Backing); + } + + for _ in 0..Unscheduled::SCHEDULING_WINDOW_SIZE { + let priority = unscheduled.select_next_priority(); + priorities.push(priority); + unscheduled.mark_scheduled(priority); + } + + assert_eq!(priorities.iter().filter(|v| **v == Approval).count(), 9); + assert_eq!(priorities.iter().filter(|v| **v == BackingSystemParas).count(), 2); + assert_eq!(priorities.iter().filter(|v| **v == Backing).count(), 1); + } + + #[test] + fn test_unscheduled_priority_distribution_without_disputes_and_only_one_backing() { + use PvfExecKind::*; + + let mut priorities = vec![]; + + let mut unscheduled = Unscheduled::new(); + for _ in 0..Unscheduled::SCHEDULING_WINDOW_SIZE { + unscheduled.add(create_execution_job(), Approval); + } + unscheduled.add(create_execution_job(), Backing); + + for _ in 0..Unscheduled::SCHEDULING_WINDOW_SIZE { + let priority = unscheduled.select_next_priority(); + priorities.push(priority); + unscheduled.mark_scheduled(priority); + } + + assert_eq!(priorities.iter().filter(|v| **v == Approval).count(), 11); + assert_eq!(priorities.iter().filter(|v| **v == Backing).count(), 1); + } + + #[test] + fn test_unscheduled_does_not_postpone_backing() { + use PvfExecKind::*; + + let mut priorities = vec![]; + + let mut unscheduled = Unscheduled::new(); + for _ in 0..Unscheduled::SCHEDULING_WINDOW_SIZE { + unscheduled.add(create_execution_job(), Approval); + } + unscheduled.add(create_execution_job(), Backing); + + for _ in 0..Unscheduled::SCHEDULING_WINDOW_SIZE { + let priority = unscheduled.select_next_priority(); + priorities.push(priority); + unscheduled.mark_scheduled(priority); + } + + assert_eq!(&priorities[..4], &[Approval, Backing, Approval, Approval]); + } +} diff --git a/polkadot/node/core/pvf/src/host.rs b/polkadot/node/core/pvf/src/host.rs index 22943a06c43c..37cd6fcbf74a 100644 --- a/polkadot/node/core/pvf/src/host.rs +++ b/polkadot/node/core/pvf/src/host.rs @@ -37,7 +37,7 @@ use polkadot_node_core_pvf_common::{ pvf::PvfPrepData, }; use polkadot_node_primitives::PoV; -use polkadot_node_subsystem::{SubsystemError, SubsystemResult}; +use polkadot_node_subsystem::{messages::PvfExecKind, SubsystemError, SubsystemResult}; use polkadot_parachain_primitives::primitives::ValidationResult; use polkadot_primitives::PersistedValidationData; use std::{ @@ -114,6 +114,7 @@ impl ValidationHost { pvd: Arc, pov: Arc, priority: Priority, + exec_kind: PvfExecKind, result_tx: ResultSender, ) -> Result<(), String> { self.to_host_tx @@ -123,6 +124,7 @@ impl ValidationHost { pvd, pov, priority, + exec_kind, result_tx, })) .await @@ -155,6 +157,7 @@ struct ExecutePvfInputs { pvd: Arc, pov: Arc, priority: Priority, + exec_kind: PvfExecKind, result_tx: ResultSender, } @@ -545,7 +548,7 @@ async fn handle_execute_pvf( awaiting_prepare: &mut AwaitingPrepare, inputs: ExecutePvfInputs, ) -> Result<(), Fatal> { - let ExecutePvfInputs { pvf, exec_timeout, pvd, pov, priority, result_tx } = inputs; + let ExecutePvfInputs { pvf, exec_timeout, pvd, pov, priority, exec_kind, result_tx } = inputs; let artifact_id = ArtifactId::from_pvf_prep_data(&pvf); let executor_params = (*pvf.executor_params()).clone(); @@ -567,6 +570,7 @@ async fn handle_execute_pvf( pvd, pov, executor_params, + exec_kind, result_tx, }, }, @@ -597,6 +601,7 @@ async fn handle_execute_pvf( pvd, pov, executor_params, + exec_kind, result_tx, }, ) @@ -606,7 +611,14 @@ async fn handle_execute_pvf( ArtifactState::Preparing { .. } => { awaiting_prepare.add( artifact_id, - PendingExecutionRequest { exec_timeout, pvd, pov, executor_params, result_tx }, + PendingExecutionRequest { + exec_timeout, + pvd, + pov, + executor_params, + result_tx, + exec_kind, + }, ); }, ArtifactState::FailedToProcess { last_time_failed, num_failures, error } => { @@ -638,6 +650,7 @@ async fn handle_execute_pvf( pvd, pov, executor_params, + exec_kind, result_tx, }, ) @@ -657,7 +670,14 @@ async fn handle_execute_pvf( pvf, priority, artifact_id, - PendingExecutionRequest { exec_timeout, pvd, pov, executor_params, result_tx }, + PendingExecutionRequest { + exec_timeout, + pvd, + pov, + executor_params, + result_tx, + exec_kind, + }, ) .await?; } @@ -779,7 +799,7 @@ async fn handle_prepare_done( // It's finally time to dispatch all the execution requests that were waiting for this artifact // to be prepared. let pending_requests = awaiting_prepare.take(&artifact_id); - for PendingExecutionRequest { exec_timeout, pvd, pov, executor_params, result_tx } in + for PendingExecutionRequest { exec_timeout, pvd, pov, executor_params, result_tx, exec_kind } in pending_requests { if result_tx.is_canceled() { @@ -805,6 +825,7 @@ async fn handle_prepare_done( pvd, pov, executor_params, + exec_kind, result_tx, }, }, @@ -1234,6 +1255,7 @@ pub(crate) mod tests { pvd.clone(), pov1.clone(), Priority::Normal, + PvfExecKind::Backing, result_tx, ) .await @@ -1246,6 +1268,7 @@ pub(crate) mod tests { pvd.clone(), pov1, Priority::Critical, + PvfExecKind::Backing, result_tx, ) .await @@ -1258,6 +1281,7 @@ pub(crate) mod tests { pvd, pov2, Priority::Normal, + PvfExecKind::Backing, result_tx, ) .await @@ -1407,6 +1431,7 @@ pub(crate) mod tests { pvd.clone(), pov.clone(), Priority::Critical, + PvfExecKind::Backing, result_tx, ) .await @@ -1455,6 +1480,7 @@ pub(crate) mod tests { pvd, pov, Priority::Critical, + PvfExecKind::Backing, result_tx, ) .await @@ -1565,6 +1591,7 @@ pub(crate) mod tests { pvd.clone(), pov.clone(), Priority::Critical, + PvfExecKind::Backing, result_tx, ) .await @@ -1596,6 +1623,7 @@ pub(crate) mod tests { pvd.clone(), pov.clone(), Priority::Critical, + PvfExecKind::Backing, result_tx_2, ) .await @@ -1619,6 +1647,7 @@ pub(crate) mod tests { pvd.clone(), pov.clone(), Priority::Critical, + PvfExecKind::Backing, result_tx_3, ) .await @@ -1677,6 +1706,7 @@ pub(crate) mod tests { pvd.clone(), pov.clone(), Priority::Critical, + PvfExecKind::Backing, result_tx, ) .await @@ -1708,6 +1738,7 @@ pub(crate) mod tests { pvd.clone(), pov.clone(), Priority::Critical, + PvfExecKind::Backing, result_tx_2, ) .await @@ -1731,6 +1762,7 @@ pub(crate) mod tests { pvd.clone(), pov.clone(), Priority::Critical, + PvfExecKind::Backing, result_tx_3, ) .await @@ -1805,6 +1837,7 @@ pub(crate) mod tests { pvd, pov, Priority::Normal, + PvfExecKind::Backing, result_tx, ) .await diff --git a/polkadot/node/core/pvf/src/metrics.rs b/polkadot/node/core/pvf/src/metrics.rs index c59cab464180..745f2de99e58 100644 --- a/polkadot/node/core/pvf/src/metrics.rs +++ b/polkadot/node/core/pvf/src/metrics.rs @@ -18,6 +18,7 @@ use polkadot_node_core_pvf_common::prepare::MemoryStats; use polkadot_node_metrics::metrics::{self, prometheus}; +use polkadot_node_subsystem::messages::PvfExecKind; /// Validation host metrics. #[derive(Default, Clone)] @@ -120,6 +121,13 @@ impl Metrics { .observe(pov_size as f64); } } + + /// When preparation pipeline concluded working on an item. + pub(crate) fn on_execute_kind(&self, kind: PvfExecKind) { + if let Some(metrics) = &self.0 { + metrics.exec_kind_selected.with_label_values(&[kind.as_str()]).inc(); + } + } } #[derive(Clone)] @@ -146,6 +154,7 @@ struct MetricsInner { preparation_peak_tracked_allocation: prometheus::Histogram, pov_size: prometheus::HistogramVec, code_size: prometheus::Histogram, + exec_kind_selected: prometheus::CounterVec, } impl metrics::Metrics for Metrics { @@ -369,6 +378,16 @@ impl metrics::Metrics for Metrics { )?, registry, )?, + exec_kind_selected: prometheus::register( + prometheus::CounterVec::new( + prometheus::Opts::new( + "polkadot_pvf_exec_kind_selected", + "The total number of selected execute kinds", + ), + &["priority"], + )?, + registry, + )?, }; Ok(Metrics(Some(inner))) } diff --git a/polkadot/node/core/pvf/src/priority.rs b/polkadot/node/core/pvf/src/priority.rs index 0d18d4b484ca..7aaeacf36220 100644 --- a/polkadot/node/core/pvf/src/priority.rs +++ b/polkadot/node/core/pvf/src/priority.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . +use polkadot_node_subsystem::messages::PvfExecKind; + /// A priority assigned to preparation of a PVF. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum Priority { @@ -35,3 +37,14 @@ impl Priority { self == Priority::Critical } } + +impl From for Priority { + fn from(priority: PvfExecKind) -> Self { + match priority { + PvfExecKind::Dispute => Priority::Critical, + PvfExecKind::Approval => Priority::Critical, + PvfExecKind::BackingSystemParas => Priority::Normal, + PvfExecKind::Backing => Priority::Normal, + } + } +} diff --git a/polkadot/node/core/pvf/tests/it/main.rs b/polkadot/node/core/pvf/tests/it/main.rs index a4a085318957..4cbc6fb04a8e 100644 --- a/polkadot/node/core/pvf/tests/it/main.rs +++ b/polkadot/node/core/pvf/tests/it/main.rs @@ -25,9 +25,11 @@ use polkadot_node_core_pvf::{ ValidationHost, JOB_TIMEOUT_WALL_CLOCK_FACTOR, }; use polkadot_node_primitives::{PoV, POV_BOMB_LIMIT, VALIDATION_CODE_BOMB_LIMIT}; +use polkadot_node_subsystem::messages::PvfExecKind; use polkadot_parachain_primitives::primitives::{BlockData, ValidationResult}; use polkadot_primitives::{ - ExecutorParam, ExecutorParams, PersistedValidationData, PvfExecKind, PvfPrepKind, + ExecutorParam, ExecutorParams, PersistedValidationData, PvfExecKind as RuntimePvfExecKind, + PvfPrepKind, }; use sp_core::H256; @@ -123,6 +125,7 @@ impl TestHost { Arc::new(pvd), Arc::new(pov), polkadot_node_core_pvf::Priority::Normal, + PvfExecKind::Backing, result_tx, ) .await @@ -580,8 +583,9 @@ async fn artifact_does_not_reprepare_on_non_meaningful_exec_parameter_change() { let cache_dir = host.cache_dir.path(); let set1 = ExecutorParams::default(); - let set2 = - ExecutorParams::from(&[ExecutorParam::PvfExecTimeout(PvfExecKind::Backing, 2500)][..]); + let set2 = ExecutorParams::from( + &[ExecutorParam::PvfExecTimeout(RuntimePvfExecKind::Backing, 2500)][..], + ); let _stats = host .precheck_pvf(test_parachain_halt::wasm_binary_unwrap(), set1) diff --git a/polkadot/node/malus/src/variants/common.rs b/polkadot/node/malus/src/variants/common.rs index 50a5af63db44..66926f48c5e7 100644 --- a/polkadot/node/malus/src/variants/common.rs +++ b/polkadot/node/malus/src/variants/common.rs @@ -241,7 +241,7 @@ where }, } => { match self.fake_validation { - x if x.misbehaves_valid() && x.should_misbehave(exec_kind) => { + x if x.misbehaves_valid() && x.should_misbehave(exec_kind.into()) => { // Behave normally if the `PoV` is not known to be malicious. if pov.block_data.0.as_slice() != MALICIOUS_POV { return Some(FromOrchestra::Communication { @@ -296,7 +296,7 @@ where }, } }, - x if x.misbehaves_invalid() && x.should_misbehave(exec_kind) => { + x if x.misbehaves_invalid() && x.should_misbehave(exec_kind.into()) => { // Set the validation result to invalid with probability `p` and trigger a // dispute let behave_maliciously = self.distribution.sample(&mut rand::thread_rng()); diff --git a/polkadot/node/network/protocol/src/request_response/mod.rs b/polkadot/node/network/protocol/src/request_response/mod.rs index b498de55dce4..296c462b508d 100644 --- a/polkadot/node/network/protocol/src/request_response/mod.rs +++ b/polkadot/node/network/protocol/src/request_response/mod.rs @@ -123,10 +123,12 @@ const DEFAULT_REQUEST_TIMEOUT_CONNECTED: Duration = Duration::from_secs(1); /// Timeout for requesting availability chunks. pub const CHUNK_REQUEST_TIMEOUT: Duration = DEFAULT_REQUEST_TIMEOUT_CONNECTED; -/// This timeout is based on what seems sensible from a time budget perspective, considering 6 -/// second block time. This is going to be tough, if we have multiple forks and large PoVs, but we -/// only have so much time. -const POV_REQUEST_TIMEOUT_CONNECTED: Duration = Duration::from_millis(1200); +/// This timeout is based on the following parameters, assuming we use asynchronous backing with no +/// time budget within a relay block: +/// - 500 Mbit/s networking speed +/// - 10 MB PoV +/// - 10 parallel executions +const POV_REQUEST_TIMEOUT_CONNECTED: Duration = Duration::from_millis(2000); /// We want timeout statement requests fast, so we don't waste time on slow nodes. Responders will /// try their best to either serve within that timeout or return an error immediately. (We need to diff --git a/polkadot/node/overseer/examples/minimal-example.rs b/polkadot/node/overseer/examples/minimal-example.rs index c2cb1817312c..807e7405ff1b 100644 --- a/polkadot/node/overseer/examples/minimal-example.rs +++ b/polkadot/node/overseer/examples/minimal-example.rs @@ -24,14 +24,14 @@ use orchestra::async_trait; use std::time::Duration; use polkadot_node_primitives::{BlockData, PoV}; -use polkadot_node_subsystem_types::messages::CandidateValidationMessage; +use polkadot_node_subsystem_types::messages::{CandidateValidationMessage, PvfExecKind}; use polkadot_overseer::{ self as overseer, dummy::dummy_overseer_builder, gen::{FromOrchestra, SpawnedSubsystem}, HeadSupportsParachains, SubsystemError, }; -use polkadot_primitives::{CandidateReceipt, Hash, PersistedValidationData, PvfExecKind}; +use polkadot_primitives::{CandidateReceipt, Hash, PersistedValidationData}; use polkadot_primitives_test_helpers::{ dummy_candidate_descriptor, dummy_hash, dummy_validation_code, }; diff --git a/polkadot/node/overseer/src/tests.rs b/polkadot/node/overseer/src/tests.rs index 47c26186b518..46864a482e2a 100644 --- a/polkadot/node/overseer/src/tests.rs +++ b/polkadot/node/overseer/src/tests.rs @@ -25,11 +25,11 @@ use polkadot_node_primitives::{ }; use polkadot_node_subsystem_test_helpers::mock::{dummy_unpin_handle, new_leaf}; use polkadot_node_subsystem_types::messages::{ - NetworkBridgeEvent, ReportPeerMessage, RuntimeApiRequest, + NetworkBridgeEvent, PvfExecKind, ReportPeerMessage, RuntimeApiRequest, }; use polkadot_primitives::{ CandidateHash, CandidateReceipt, CollatorPair, Id as ParaId, InvalidDisputeStatementKind, - PersistedValidationData, PvfExecKind, SessionIndex, ValidDisputeStatementKind, ValidatorIndex, + PersistedValidationData, SessionIndex, ValidDisputeStatementKind, ValidatorIndex, }; use polkadot_primitives_test_helpers::{ dummy_candidate_descriptor, dummy_candidate_receipt, dummy_hash, dummy_validation_code, diff --git a/polkadot/node/subsystem-types/Cargo.toml b/polkadot/node/subsystem-types/Cargo.toml index b5686ec96be1..b8bad8f8a295 100644 --- a/polkadot/node/subsystem-types/Cargo.toml +++ b/polkadot/node/subsystem-types/Cargo.toml @@ -32,3 +32,4 @@ prometheus-endpoint = { workspace = true, default-features = true } thiserror = { workspace = true } async-trait = { workspace = true } bitvec = { features = ["alloc"], workspace = true } +strum = { features = ["derive"], workspace = true, default-features = true } diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index a520e85f52a9..0017adb45568 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -24,6 +24,7 @@ use futures::channel::oneshot; use sc_network::{Multiaddr, ReputationChange}; +use strum::EnumIter; use thiserror::Error; pub use sc_network::IfDisconnected; @@ -47,9 +48,10 @@ use polkadot_primitives::{ CandidateReceipt, CollatorId, CommittedCandidateReceipt, CoreIndex, CoreState, DisputeState, ExecutorParams, GroupIndex, GroupRotationInfo, Hash, HeadData, Header as BlockHeader, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, MultiDisputeStatementSet, - NodeFeatures, OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, PvfExecKind, - SessionIndex, SessionInfo, SignedAvailabilityBitfield, SignedAvailabilityBitfields, - ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, + NodeFeatures, OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, + PvfExecKind as RuntimePvfExecKind, SessionIndex, SessionInfo, SignedAvailabilityBitfield, + SignedAvailabilityBitfields, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, + ValidatorSignature, }; use polkadot_statement_table::v2::Misbehavior; use std::{ @@ -182,6 +184,45 @@ pub enum CandidateValidationMessage { }, } +/// Extends primitives::PvfExecKind, which is a runtime parameter we don't want to change, +/// to separate and prioritize execution jobs by request type. +/// The order is important, because we iterate through the values and assume it is going from higher +/// to lowest priority. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumIter)] +pub enum PvfExecKind { + /// For dispute requests + Dispute, + /// For approval requests + Approval, + /// For backing requests from system parachains. + BackingSystemParas, + /// For backing requests. + Backing, +} + +impl PvfExecKind { + /// Converts priority level to &str + pub fn as_str(&self) -> &str { + match *self { + Self::Dispute => "dispute", + Self::Approval => "approval", + Self::BackingSystemParas => "backing_system_paras", + Self::Backing => "backing", + } + } +} + +impl From for RuntimePvfExecKind { + fn from(exec: PvfExecKind) -> Self { + match exec { + PvfExecKind::Dispute => RuntimePvfExecKind::Approval, + PvfExecKind::Approval => RuntimePvfExecKind::Approval, + PvfExecKind::BackingSystemParas => RuntimePvfExecKind::Backing, + PvfExecKind::Backing => RuntimePvfExecKind::Backing, + } + } +} + /// Messages received by the Collator Protocol subsystem. #[derive(Debug, derive_more::From)] pub enum CollatorProtocolMessage { diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index ab6563525ff7..1b5f7b5157d8 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -33,6 +33,7 @@ use frame_support::{ dynamic_params::{dynamic_pallet_params, dynamic_params}, traits::FromContains, }; +use pallet_balances::WeightInfo; use pallet_nis::WithMaximumOf; use polkadot_primitives::{ slashing, @@ -1601,6 +1602,8 @@ pub mod migrations { pub const TechnicalMembershipPalletName: &'static str = "TechnicalMembership"; pub const TipsPalletName: &'static str = "Tips"; pub const PhragmenElectionPalletId: LockIdentifier = *b"phrelect"; + /// Weight for balance unreservations + pub BalanceUnreserveWeight: Weight = weights::pallet_balances_balances::WeightInfo::::force_unreserve(); } // Special Config for Gov V1 pallets, allowing us to run migrations for them without @@ -1656,6 +1659,7 @@ pub mod migrations { pallet_elections_phragmen::migrations::unlock_and_unreserve_all_funds::UnlockAndUnreserveAllFunds, pallet_democracy::migrations::unlock_and_unreserve_all_funds::UnlockAndUnreserveAllFunds, pallet_tips::migrations::unreserve_deposits::UnreserveDeposits, + pallet_treasury::migration::cleanup_proposals::Migration, // Delete all Gov v1 pallet storage key/values. diff --git a/polkadot/xcm/xcm-builder/src/universal_exports.rs b/polkadot/xcm/xcm-builder/src/universal_exports.rs index 30e0b7c72b03..5c754f01ec0a 100644 --- a/polkadot/xcm/xcm-builder/src/universal_exports.rs +++ b/polkadot/xcm/xcm-builder/src/universal_exports.rs @@ -337,15 +337,15 @@ impl InspectMessageQueues +impl InspectMessageQueues for SovereignPaidRemoteExporter { - fn clear_messages() { - Router::clear_messages() - } + fn clear_messages() {} + /// This router needs to implement `InspectMessageQueues` but doesn't have to + /// return any messages, since it just reuses the `XcmpQueue` router. fn get_messages() -> Vec<(VersionedLocation, Vec>)> { - Router::get_messages() + Vec::new() } } diff --git a/polkadot/zombienet_tests/functional/0003-beefy-and-mmr.zndsl b/polkadot/zombienet_tests/functional/0003-beefy-and-mmr.zndsl index 8300ef051f09..4fc066a13b07 100644 --- a/polkadot/zombienet_tests/functional/0003-beefy-and-mmr.zndsl +++ b/polkadot/zombienet_tests/functional/0003-beefy-and-mmr.zndsl @@ -18,22 +18,22 @@ validator-unstable: reports substrate_beefy_best_block is at least 1 within 60 s validator-unstable: pause # Verify validator sets get changed on new sessions. -validator: reports substrate_beefy_validator_set_id is at least 1 within 70 seconds +validator: reports substrate_beefy_validator_set_id is at least 1 within 180 seconds # Check next session too. -validator: reports substrate_beefy_validator_set_id is at least 2 within 130 seconds +validator: reports substrate_beefy_validator_set_id is at least 2 within 180 seconds # Verify voting happens and blocks are being finalized for new sessions too: # since we verified we're at least in the 3rd session, verify BEEFY finalized mandatory #21. -validator: reports substrate_beefy_best_block is at least 21 within 130 seconds +validator: reports substrate_beefy_best_block is at least 21 within 180 seconds # Custom JS to test BEEFY RPCs. -validator-0: js-script ./0003-beefy-finalized-heads.js with "validator-0,validator-1,validator-2" return is 1 within 5 seconds +validator-0: js-script ./0003-beefy-finalized-heads.js with "validator-0,validator-1,validator-2" return is 1 within 60 seconds # Custom JS to test MMR RPCs. -validator: js-script ./0003-mmr-leaves.js with "21" return is 1 within 5 seconds -validator: js-script ./0003-mmr-generate-and-verify-proof.js with "validator-0,validator-1,validator-2" return is 1 within 5 seconds +validator: js-script ./0003-mmr-leaves.js with "21" return is 1 within 60 seconds +validator: js-script ./0003-mmr-generate-and-verify-proof.js with "validator-0,validator-1,validator-2" return is 1 within 60 seconds # Resume validator-unstable and verify it imports all BEEFY justification and catches up. validator-unstable: resume -validator-unstable: reports substrate_beefy_validator_set_id is at least 2 within 30 seconds -validator-unstable: reports substrate_beefy_best_block is at least 21 within 30 seconds +validator-unstable: reports substrate_beefy_validator_set_id is at least 2 within 60 seconds +validator-unstable: reports substrate_beefy_best_block is at least 21 within 60 seconds diff --git a/prdoc/pr_4837.prdoc b/prdoc/pr_4837.prdoc new file mode 100644 index 000000000000..55c12cc92a1c --- /dev/null +++ b/prdoc/pr_4837.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: Add PVF execution priority + +doc: + - audience: Node Dev + description: | + The new logic optimizes the distribution of execution jobs for disputes, approvals, and backings. + The main goal is to create back pressure for backing in the presence of disputes or numerous approval jobs. + +crates: + - name: polkadot-node-core-pvf + bump: major + - name: polkadot-overseer + bump: patch + - name: polkadot-node-subsystem-types + bump: patch + - name: polkadot-node-core-approval-voting + bump: patch + - name: polkadot-node-core-backing + bump: patch + - name: polkadot-node-core-candidate-validation + bump: patch + - name: polkadot-node-core-dispute-coordinator + bump: patch diff --git a/prdoc/pr_5630.prdoc b/prdoc/pr_5630.prdoc new file mode 100644 index 000000000000..bafb9e746d40 --- /dev/null +++ b/prdoc/pr_5630.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: Introduce and Implement the `VestedTransfer` Trait + +doc: + - audience: Runtime Dev + description: | + This PR introduces a new trait `VestedTransfer` which is implemented by `pallet_vesting`. With this, other pallets can easily introduce vested transfers into their logic. + +crates: + - name: frame-support + bump: minor + - name: pallet-vesting + bump: minor diff --git a/prdoc/pr_5872.prdoc b/prdoc/pr_5872.prdoc new file mode 100644 index 000000000000..cf4f0b24f8db --- /dev/null +++ b/prdoc/pr_5872.prdoc @@ -0,0 +1,13 @@ +title: '[omni-bencher] Make all runtimes work' +doc: +- audience: Runtime Dev + description: |- + Changes: + - Add `--exclude-pallets` to exclude some pallets from runtimes where we dont have genesis presets yet + - Make `--genesis-builder-policy=none` work with `--runtime` + - CI: Run the frame-omni-bencher for all runtimes +crates: +- name: frame-benchmarking-cli + bump: major +- name: contracts-rococo-runtime + bump: patch diff --git a/prdoc/pr_5886.prdoc b/prdoc/pr_5886.prdoc new file mode 100644 index 000000000000..f5e597281197 --- /dev/null +++ b/prdoc/pr_5886.prdoc @@ -0,0 +1,18 @@ +title: Bump some dependencies +doc: +- audience: Runtime Dev + description: |- + This bumps `ethbloom`, `ethereum-types`, `primitive-types` and `rlp` to their latest version. + + Fixes: https://github.com/paritytech/polkadot-sdk/issues/5870 +crates: +- name: sc-consensus-babe + bump: patch +- name: pallet-babe + bump: patch +- name: pallet-revive + bump: patch +- name: sp-runtime + bump: patch +- name: bp-polkadot-core + bump: major diff --git a/prdoc/pr_5892.prdoc b/prdoc/pr_5892.prdoc new file mode 100644 index 000000000000..b909e443328b --- /dev/null +++ b/prdoc/pr_5892.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: "Treasury: add migration to clean up unapproved deprecated proposals" + +doc: + - audience: Runtime Dev + description: | + It is no longer possible to create `Proposals` storage item in `pallet-treasury` due to migration from + governance v1 model but there are some `Proposals` whose bonds are still on hold with no way to release them. + The purpose of this migration is to clear `Proposals` which are stuck and return bonds to the proposers. + +crates: + - name: pallet-treasury + bump: patch + - name: rococo-runtime + bump: patch diff --git a/prdoc/pr_5913.prdoc b/prdoc/pr_5913.prdoc new file mode 100644 index 000000000000..f50cd722c714 --- /dev/null +++ b/prdoc/pr_5913.prdoc @@ -0,0 +1,20 @@ +# 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 redundant XCMs from dry run's forwarded xcms + +doc: + - audience: Runtime User + description: | + The DryRunApi was returning the same message repeated multiple times in the + `forwarded_xcms` field. This is no longer the case. + +crates: + - name: pallet-xcm-bridge-hub-router + bump: patch + - name: cumulus-pallet-parachain-system + bump: patch + - name: staging-xcm-builder + bump: patch + - name: emulated-integration-tests-common + bump: minor diff --git a/prdoc/pr_5915.prdoc b/prdoc/pr_5915.prdoc new file mode 100644 index 000000000000..a9303e2563d1 --- /dev/null +++ b/prdoc/pr_5915.prdoc @@ -0,0 +1,18 @@ +# 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: Omni-Node renamings + +doc: + - audience: Node Dev + description: | + This PR renames the `polkadot-parachain-lib` crate to `polkadot-omni-node-lib` and introduces a new + `polkadot-omni-node` binary. + +crates: + - name: polkadot-omni-node-lib + bump: patch + - name: polkadot-parachain-bin + bump: patch + - name: polkadot-sdk + bump: patch diff --git a/prdoc/pr_5924.prdoc b/prdoc/pr_5924.prdoc new file mode 100644 index 000000000000..26bde8eec0de --- /dev/null +++ b/prdoc/pr_5924.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: Bump PoV request timeout + +doc: + - audience: Node Dev + description: | + With asynchronous backing and PoV size 10MB, we can increase the PoV request timeout from 1.2s to 2s. + +crates: + - name: polkadot-node-network-protocol + bump: patch diff --git a/prdoc/pr_5939.prdoc b/prdoc/pr_5939.prdoc new file mode 100644 index 000000000000..babb26281ecd --- /dev/null +++ b/prdoc/pr_5939.prdoc @@ -0,0 +1,14 @@ +title: "[pallet-revive] Bump PolkaVM and add static code validation" + +doc: + - audience: Runtime Dev + description: | + Statically validate basic block sizes and instructions. + +crates: + - name: pallet-revive + bump: major + - name: pallet-revive-fixtures + bump: minor + - name: pallet-revive-uapi + bump: patch diff --git a/prdoc/pr_5941.prdoc b/prdoc/pr_5941.prdoc new file mode 100644 index 000000000000..4e88400f4ef0 --- /dev/null +++ b/prdoc/pr_5941.prdoc @@ -0,0 +1,16 @@ +title: "`SolochainDefaultConfig`: Use correct `AccountData`" + +doc: + - audience: Runtime Dev + description: | + `SolochainDefaultConfig` by default was setting `AccountData` to `AccountInfo`. + Thus, the actual account data was recursively nested the same type. By default + it should be set `()`, because this is the only reasonable `AccountData`. + + If you have used `SolochainDefaultConfig` before and did not overwrite, `AccountData` + you should now overwrite it to `AccountInfo` or you will need to write a migration to + change the data. + +crates: + - name: frame-system + bump: patch diff --git a/prdoc/pr_5946.prdoc b/prdoc/pr_5946.prdoc new file mode 100644 index 000000000000..9a858c980a19 --- /dev/null +++ b/prdoc/pr_5946.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: "[FRAME] fix: Do not emit `Issued { amount: 0 }` event" + +doc: + - audience: + - Runtime Dev + - Runtime User + description: | + Filter out `Issued` events in `pallet-balances` module when its balance amount is zero. + +crates: + - name: pallet-balances + bump: patch diff --git a/prdoc/pr_5994.prdoc b/prdoc/pr_5994.prdoc new file mode 100644 index 000000000000..425653e52646 --- /dev/null +++ b/prdoc/pr_5994.prdoc @@ -0,0 +1,3 @@ +crates: + - name: sc-consensus-babe + bump: none diff --git a/prdoc/pr_6015.prdoc b/prdoc/pr_6015.prdoc new file mode 100644 index 000000000000..d5a7d1e18d5d --- /dev/null +++ b/prdoc/pr_6015.prdoc @@ -0,0 +1,9 @@ +title: Rename QueueEvent::StartWork +doc: +- audience: Node Dev + description: |- + When we send `QueueEvent::StartWork`, we have already completed the execution. Therefore, `QueueEvent::FinishWork` is a better match. + +crates: +- name: polkadot-node-core-pvf + bump: patch diff --git a/substrate/bin/node/cli/Cargo.toml b/substrate/bin/node/cli/Cargo.toml index 6e734a723cd3..04dcb909b8c1 100644 --- a/substrate/bin/node/cli/Cargo.toml +++ b/substrate/bin/node/cli/Cargo.toml @@ -48,7 +48,91 @@ rand = { workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } # The Polkadot-SDK: -polkadot-sdk = { features = ["node"], workspace = true, default-features = true } +polkadot-sdk = { features = [ + "fork-tree", + "frame-benchmarking-cli", + "frame-remote-externalities", + "frame-support-procedural-tools", + "generate-bags", + "mmr-gadget", + "mmr-rpc", + "pallet-contracts-mock-network", + "pallet-revive-mock-network", + "pallet-transaction-payment-rpc", + "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", + "sp-blockchain", + "sp-consensus", + "sp-core-hashing", + "sp-core-hashing-proc-macro", + "sp-database", + "sp-maybe-compressed-blob", + "sp-panic-handler", + "sp-rpc", + "staging-chain-spec-builder", + "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", +], workspace = true, default-features = true } # Shared code between the staging node and kitchensink runtime: kitchensink-runtime = { workspace = true } diff --git a/substrate/client/consensus/babe/src/authorship.rs b/substrate/client/consensus/babe/src/authorship.rs index 57ee706a04f6..aa54da2a4434 100644 --- a/substrate/client/consensus/babe/src/authorship.rs +++ b/substrate/client/consensus/babe/src/authorship.rs @@ -108,7 +108,8 @@ pub(super) fn secondary_slot_author( return None } - let rand = U256::from((randomness, slot).using_encoded(sp_crypto_hashing::blake2_256)); + let rand = + U256::from_big_endian(&(randomness, slot).using_encoded(sp_crypto_hashing::blake2_256)); let authorities_len = U256::from(authorities.len()); let idx = rand % authorities_len; @@ -271,7 +272,9 @@ fn claim_primary_slot( #[cfg(test)] mod tests { use super::*; - use sp_consensus_babe::{AllowedSlots, AuthorityId, BabeEpochConfiguration, Epoch}; + use sp_consensus_babe::{ + AllowedSlots, AuthorityId, BabeEpochConfiguration, Epoch, RANDOMNESS_LENGTH, + }; use sp_core::{crypto::Pair as _, sr25519::Pair}; use sp_keystore::testing::MemoryKeystore; @@ -305,4 +308,18 @@ mod tests { epoch.authorities.push((valid_public_key.into(), 10)); assert_eq!(claim_slot(10.into(), &epoch, &keystore).unwrap().1, valid_public_key.into()); } + + #[test] + fn secondary_slot_author_selection_works() { + let authorities = (0..1000) + .map(|i| (AuthorityId::from(Pair::generate().0.public()), i)) + .collect::>(); + + let randomness = [3; RANDOMNESS_LENGTH]; + + assert_eq!( + *secondary_slot_author(100.into(), &authorities, randomness).unwrap(), + authorities[167].0 + ); + } } diff --git a/substrate/frame/babe/src/mock.rs b/substrate/frame/babe/src/mock.rs index 4e4052b2b566..d416e31b25f7 100644 --- a/substrate/frame/babe/src/mock.rs +++ b/substrate/frame/babe/src/mock.rs @@ -291,7 +291,7 @@ pub fn new_test_ext_with_pairs( authorities_len: usize, ) -> (Vec, sp_io::TestExternalities) { let pairs = (0..authorities_len) - .map(|i| AuthorityPair::from_seed(&U256::from(i).into())) + .map(|i| AuthorityPair::from_seed(&U256::from(i).to_little_endian())) .collect::>(); let public = pairs.iter().map(|p| p.public()).collect(); diff --git a/substrate/frame/balances/src/impl_fungible.rs b/substrate/frame/balances/src/impl_fungible.rs index cf95a97d191f..4470c3cc9eb1 100644 --- a/substrate/frame/balances/src/impl_fungible.rs +++ b/substrate/frame/balances/src/impl_fungible.rs @@ -354,7 +354,9 @@ impl, I: 'static> fungible::Balanced for Pallet Self::deposit_event(Event::::Withdraw { who: who.clone(), amount }); } fn done_issue(amount: Self::Balance) { - Self::deposit_event(Event::::Issued { amount }); + if !amount.is_zero() { + Self::deposit_event(Event::::Issued { amount }); + } } fn done_rescind(amount: Self::Balance) { Self::deposit_event(Event::::Rescinded { amount }); diff --git a/substrate/frame/delegated-staking/src/impls.rs b/substrate/frame/delegated-staking/src/impls.rs index 4e6812dee249..a443df7b20f5 100644 --- a/substrate/frame/delegated-staking/src/impls.rs +++ b/substrate/frame/delegated-staking/src/impls.rs @@ -124,7 +124,7 @@ impl DelegationMigrator for Pallet { /// Only used for testing. #[cfg(feature = "runtime-benchmarks")] - fn migrate_to_direct_staker(agent: Agent) { + fn force_kill_agent(agent: Agent) { >::remove(agent.clone().get()); >::iter() .filter(|(_, delegation)| delegation.agent == agent.clone().get()) @@ -136,8 +136,6 @@ impl DelegationMigrator for Pallet { ); >::remove(&delegator); }); - - T::CoreStaking::migrate_to_direct_staker(&agent.get()); } } diff --git a/substrate/frame/delegated-staking/src/tests.rs b/substrate/frame/delegated-staking/src/tests.rs index 2c965e18b1b3..b7b82a43771e 100644 --- a/substrate/frame/delegated-staking/src/tests.rs +++ b/substrate/frame/delegated-staking/src/tests.rs @@ -676,7 +676,7 @@ mod staking_integration { // in equal parts. lets try to migrate this nominator into delegate based stake. // all balance currently is in 200 - assert_eq!(Balances::free_balance(agent), agent_amount); + assert_eq!(pallet_staking::asset::stakeable_balance::(&agent), 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 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 0dc202ff2115..135149694387 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,24 +322,24 @@ fn automatic_unbonding_pools() { assert_eq!(::MaxUnbonding::get(), 1); // init state of pool members. - let init_free_balance_2 = Balances::free_balance(2); - let init_free_balance_3 = Balances::free_balance(3); + let init_stakeable_balance_2 = pallet_staking::asset::stakeable_balance::(&2); + let init_stakeable_balance_3 = pallet_staking::asset::stakeable_balance::(&3); 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)); - assert_eq!(locked_amount_for(pool_bonded_account), 5); + assert_eq!(staked_amount_for(pool_bonded_account), 5); let init_tvl = TotalValueLocked::::get(); // 2 joins the pool. assert_ok!(Pools::join(RuntimeOrigin::signed(2), 10, 1)); - assert_eq!(locked_amount_for(pool_bonded_account), 15); + assert_eq!(staked_amount_for(pool_bonded_account), 15); // 3 joins the pool. assert_ok!(Pools::join(RuntimeOrigin::signed(3), 10, 1)); - assert_eq!(locked_amount_for(pool_bonded_account), 25); + assert_eq!(staked_amount_for(pool_bonded_account), 25); assert_eq!(TotalValueLocked::::get(), 25); @@ -350,7 +350,7 @@ fn automatic_unbonding_pools() { assert_ok!(Pools::unbond(RuntimeOrigin::signed(2), 2, 10)); // amount is still locked in the pool, needs to wait for unbonding period. - assert_eq!(locked_amount_for(pool_bonded_account), 25); + assert_eq!(staked_amount_for(pool_bonded_account), 25); // max chunks in the ledger are now filled up (`MaxUnlockingChunks == 1`). assert_eq!(unlocking_chunks_of(pool_bonded_account), 1); @@ -372,8 +372,8 @@ fn automatic_unbonding_pools() { assert_eq!(current_era(), 3); System::reset_events(); - let locked_before_withdraw_pool = locked_amount_for(pool_bonded_account); - assert_eq!(Balances::free_balance(pool_bonded_account), 26); + let staked_before_withdraw_pool = staked_amount_for(pool_bonded_account); + assert_eq!(pallet_staking::asset::stakeable_balance::(&pool_bonded_account), 26); // now unbonding 3 will work, although the pool's ledger still has the unlocking chunks // filled up. @@ -391,20 +391,21 @@ fn automatic_unbonding_pools() { ); // balance of the pool remains the same, it hasn't withdraw explicitly from the pool yet. - assert_eq!(Balances::free_balance(pool_bonded_account), 26); + assert_eq!(pallet_staking::asset::stakeable_balance::(&pool_bonded_account), 26); // but the locked amount in the pool's account decreases due to the auto-withdraw: - assert_eq!(locked_before_withdraw_pool - 10, locked_amount_for(pool_bonded_account)); + assert_eq!(staked_before_withdraw_pool - 10, staked_amount_for(pool_bonded_account)); // TVL correctly updated. assert_eq!(TotalValueLocked::::get(), 25 - 10); // however, note that the withdrawing from the pool still works for 2, the funds are taken - // from the pool's free balance. - assert_eq!(Balances::free_balance(pool_bonded_account), 26); + // from the pool's non staked balance. + assert_eq!(pallet_staking::asset::stakeable_balance::(&pool_bonded_account), 26); + assert_eq!(pallet_staking::asset::staked::(&pool_bonded_account), 15); assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(2), 2, 10)); - assert_eq!(Balances::free_balance(pool_bonded_account), 16); + assert_eq!(pallet_staking::asset::stakeable_balance::(&pool_bonded_account), 16); - assert_eq!(Balances::free_balance(2), 20); + assert_eq!(pallet_staking::asset::stakeable_balance::(&2), 20); assert_eq!(TotalValueLocked::::get(), 15); // 3 cannot withdraw yet. @@ -423,9 +424,15 @@ fn automatic_unbonding_pools() { assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(3), 3, 10)); // final conditions are the expected. - assert_eq!(Balances::free_balance(pool_bonded_account), 6); // 5 init bonded + ED - assert_eq!(Balances::free_balance(2), init_free_balance_2); - assert_eq!(Balances::free_balance(3), init_free_balance_3); + assert_eq!(pallet_staking::asset::stakeable_balance::(&pool_bonded_account), 6); // 5 init bonded + ED + assert_eq!( + pallet_staking::asset::stakeable_balance::(&2), + init_stakeable_balance_2 + ); + assert_eq!( + pallet_staking::asset::stakeable_balance::(&3), + init_stakeable_balance_3 + ); assert_eq!(TotalValueLocked::::get(), init_tvl); }); 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 e45452c1ddf9..f20e3983b09d 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 @@ -915,9 +915,8 @@ pub(crate) fn set_minimum_election_score( .map_err(|_| ()) } -pub(crate) fn locked_amount_for(account_id: AccountId) -> Balance { - let lock = pallet_balances::Locks::::get(account_id); - lock[0].amount +pub(crate) fn staked_amount_for(account_id: AccountId) -> Balance { + pallet_staking::asset::staked::(&account_id) } pub(crate) fn staking_events() -> Vec> { diff --git a/substrate/frame/fast-unstake/src/tests.rs b/substrate/frame/fast-unstake/src/tests.rs index 77128872f285..7c11f381ca10 100644 --- a/substrate/frame/fast-unstake/src/tests.rs +++ b/substrate/frame/fast-unstake/src/tests.rs @@ -137,15 +137,16 @@ fn deregister_works() { ExtBuilder::default().build_and_execute(|| { ErasToCheckPerBlock::::put(1); - assert_eq!(::Currency::reserved_balance(&1), 0); + // reserved balance prior to registering for fast unstake. + let pre_reserved = ::Currency::reserved_balance(&1); // Controller account registers for fast unstake. assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1))); - assert_eq!(::Currency::reserved_balance(&1), Deposit::get()); + assert_eq!(::Currency::reserved_balance(&1) - pre_reserved, Deposit::get()); // Controller then changes mind and deregisters. assert_ok!(FastUnstake::deregister(RuntimeOrigin::signed(1))); - assert_eq!(::Currency::reserved_balance(&1), 0); + assert_eq!(::Currency::reserved_balance(&1) - pre_reserved, 0); // Ensure stash no longer exists in the queue. assert_eq!(Queue::::get(1), None); @@ -243,7 +244,8 @@ mod on_idle { CurrentEra::::put(BondingDuration::get()); // given - assert_eq!(::Currency::reserved_balance(&1), 0); + // reserved balance prior to registering for fast unstake. + let pre_reserved = ::Currency::reserved_balance(&1); assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1))); assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(3))); @@ -251,7 +253,10 @@ mod on_idle { assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(7))); assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(9))); - assert_eq!(::Currency::reserved_balance(&1), Deposit::get()); + assert_eq!( + ::Currency::reserved_balance(&1) - pre_reserved, + Deposit::get() + ); assert_eq!(Queue::::count(), 5); assert_eq!(Head::::get(), None); @@ -279,6 +284,9 @@ mod on_idle { // when next_block(true); + // pre_reserve may change due to unstaked amount. + let pre_reserved = ::Currency::reserved_balance(&1); + // then assert_eq!( Head::::get(), @@ -289,7 +297,7 @@ mod on_idle { ); assert_eq!(Queue::::count(), 3); - assert_eq!(::Currency::reserved_balance(&1), 0); + assert_eq!(::Currency::reserved_balance(&1) - pre_reserved, 0); assert_eq!( fast_unstake_events_since_last_call(), diff --git a/substrate/frame/nomination-pools/benchmarking/src/inner.rs b/substrate/frame/nomination-pools/benchmarking/src/inner.rs index 2a4559425111..b0c8f3655a50 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/inner.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/inner.rs @@ -41,7 +41,7 @@ use sp_runtime::{ traits::{Bounded, StaticLookup, Zero}, Perbill, }; -use sp_staking::EraIndex; +use sp_staking::{EraIndex, StakingUnchecked}; // `frame_benchmarking::benchmarks!` macro needs this use pallet_nomination_pools::Call; @@ -131,6 +131,8 @@ fn migrate_to_transfer_stake(pool_id: PoolId) { ) .expect("member should have enough balance to transfer"); }); + + pallet_staking::Pallet::::migrate_to_direct_staker(&pool_acc); } fn vote_to_balance( diff --git a/substrate/frame/nomination-pools/src/adapter.rs b/substrate/frame/nomination-pools/src/adapter.rs index 272b3b60612b..f125919dabfa 100644 --- a/substrate/frame/nomination-pools/src/adapter.rs +++ b/substrate/frame/nomination-pools/src/adapter.rs @@ -460,6 +460,6 @@ impl< #[cfg(feature = "runtime-benchmarks")] fn remove_as_agent(pool: Pool) { - Delegation::migrate_to_direct_staker(pool.into()) + Delegation::force_kill_agent(pool.into()) } } diff --git a/substrate/frame/offences/benchmarking/src/inner.rs b/substrate/frame/offences/benchmarking/src/inner.rs index b16e5be653d1..573114de0742 100644 --- a/substrate/frame/offences/benchmarking/src/inner.rs +++ b/substrate/frame/offences/benchmarking/src/inner.rs @@ -20,7 +20,7 @@ use alloc::{vec, vec::Vec}; use frame_benchmarking::v1::{account, benchmarks}; -use frame_support::traits::{Currency, Get}; +use frame_support::traits::Get; use frame_system::{Config as SystemConfig, Pallet as System, RawOrigin}; use sp_runtime::{ @@ -77,8 +77,7 @@ where } type LookupSourceOf = <::Lookup as StaticLookup>::Source; -type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; +type BalanceOf = ::CurrencyBalance; struct Offender { pub controller: T::AccountId, @@ -89,7 +88,7 @@ struct Offender { } fn bond_amount() -> BalanceOf { - T::Currency::minimum_balance().saturating_mul(10_000u32.into()) + pallet_staking::asset::existential_deposit::().saturating_mul(10_000u32.into()) } fn create_offender(n: u32, nominators: u32) -> Result, &'static str> { @@ -99,7 +98,7 @@ fn create_offender(n: u32, nominators: u32) -> Result, &' let amount = bond_amount::(); // add twice as much balance to prevent the account from being killed. let free_amount = amount.saturating_mul(2u32.into()); - T::Currency::make_free_balance_be(&stash, free_amount); + pallet_staking::asset::set_stakeable_balance::(&stash, free_amount); Staking::::bond( RawOrigin::Signed(stash.clone()).into(), amount, @@ -116,7 +115,7 @@ fn create_offender(n: u32, nominators: u32) -> Result, &' for i in 0..nominators { let nominator_stash: T::AccountId = account("nominator stash", n * MAX_NOMINATORS + i, SEED); - T::Currency::make_free_balance_be(&nominator_stash, free_amount); + pallet_staking::asset::set_stakeable_balance::(&nominator_stash, free_amount); Staking::::bond( RawOrigin::Signed(nominator_stash.clone()).into(), @@ -172,6 +171,14 @@ fn make_offenders( } benchmarks! { + where_clause { + where + ::RuntimeEvent: TryInto>, + ::RuntimeEvent: TryInto>, + ::RuntimeEvent: TryInto, + ::RuntimeEvent: TryInto>, + } + report_offence_grandpa { let n in 0 .. MAX_NOMINATORS.min(MaxNominationsOf::::get()); @@ -196,17 +203,19 @@ benchmarks! { let _ = Offences::::report_offence(reporters, offence); } verify { - // make sure that all slashes have been applied #[cfg(test)] - assert_eq!( - System::::event_count(), 0 - + 1 // offence - + 3 // reporter (reward + endowment) - + 1 // offenders reported - + 3 // offenders slashed - + 1 // offenders chilled - + 3 * n // nominators slashed - ); + { + // make sure that all slashes have been applied + // (n nominators + one validator) * (slashed + unlocked) + deposit to reporter + reporter + // account endowed + some funds rescinded from issuance. + assert_eq!(System::::read_events_for_pallet::>().len(), 2 * (n + 1) as usize + 3); + // (n nominators + one validator) * slashed + Slash Reported + assert_eq!(System::::read_events_for_pallet::>().len(), 1 * (n + 1) as usize + 1); + // offence + assert_eq!(System::::read_events_for_pallet::().len(), 1); + // reporter new account + assert_eq!(System::::read_events_for_pallet::>().len(), 1); + } } report_offence_babe { @@ -233,17 +242,19 @@ benchmarks! { let _ = Offences::::report_offence(reporters, offence); } verify { - // make sure that all slashes have been applied #[cfg(test)] - assert_eq!( - System::::event_count(), 0 - + 1 // offence - + 3 // reporter (reward + endowment) - + 1 // offenders reported - + 3 // offenders slashed - + 1 // offenders chilled - + 3 * n // nominators slashed - ); + { + // make sure that all slashes have been applied + // (n nominators + one validator) * (slashed + unlocked) + deposit to reporter + reporter + // account endowed + some funds rescinded from issuance. + assert_eq!(System::::read_events_for_pallet::>().len(), 2 * (n + 1) as usize + 3); + // (n nominators + one validator) * slashed + Slash Reported + assert_eq!(System::::read_events_for_pallet::>().len(), 1 * (n + 1) as usize + 1); + // offence + assert_eq!(System::::read_events_for_pallet::().len(), 1); + // reporter new account + assert_eq!(System::::read_events_for_pallet::>().len(), 1); + } } impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/substrate/frame/revive/Cargo.toml b/substrate/frame/revive/Cargo.toml index 177b3c3e9eec..e896d9e8fa26 100644 --- a/substrate/frame/revive/Cargo.toml +++ b/substrate/frame/revive/Cargo.toml @@ -19,7 +19,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] environmental = { workspace = true } paste = { workspace = true } -polkavm = { version = "0.11.0", default-features = false } +polkavm = { version = "0.12.0", default-features = false } +polkavm-common = { version = "0.12.0", default-features = false } bitflags = { workspace = true } codec = { features = [ "derive", @@ -83,6 +84,7 @@ std = [ "pallet-revive-fixtures/std", "pallet-timestamp/std", "pallet-utility/std", + "polkavm-common/std", "polkavm/std", "rlp/std", "scale-info/std", diff --git a/substrate/frame/revive/fixtures/Cargo.toml b/substrate/frame/revive/fixtures/Cargo.toml index 53db08a3911a..75b23fdd44d1 100644 --- a/substrate/frame/revive/fixtures/Cargo.toml +++ b/substrate/frame/revive/fixtures/Cargo.toml @@ -1,6 +1,5 @@ [package] name = "pallet-revive-fixtures" -publish = true version = "0.1.0" authors.workspace = true edition.workspace = true @@ -22,7 +21,7 @@ log = { workspace = true } parity-wasm = { workspace = true } tempfile = { workspace = true } toml = { workspace = true } -polkavm-linker = { version = "0.11.0" } +polkavm-linker = { version = "0.12.0" } anyhow = { workspace = true, default-features = true } [features] diff --git a/substrate/frame/revive/fixtures/build.rs b/substrate/frame/revive/fixtures/build.rs index 944ae246c1b8..3178baf6bbe4 100644 --- a/substrate/frame/revive/fixtures/build.rs +++ b/substrate/frame/revive/fixtures/build.rs @@ -115,6 +115,7 @@ mod build { fn invoke_build(current_dir: &Path) -> Result<()> { let encoded_rustflags = [ + "-Dwarnings", "-Crelocation-model=pie", "-Clink-arg=--emit-relocs", "-Clink-arg=--export-dynamic-symbol=__polkavm_symbol_export_hack__*", @@ -158,8 +159,8 @@ mod build { /// Post-process the compiled code. fn post_process(input_path: &Path, output_path: &Path) -> Result<()> { let mut config = polkavm_linker::Config::default(); - config.set_strip(true); - config.set_optimize(false); + config.set_strip(false); + config.set_optimize(true); let orig = fs::read(input_path).with_context(|| format!("Failed to read {:?}", input_path))?; let linked = polkavm_linker::program_from_elf(config, orig.as_ref()) diff --git a/substrate/frame/revive/fixtures/build/Cargo.toml b/substrate/frame/revive/fixtures/build/Cargo.toml index 5b3a21b5122e..948d7438cf98 100644 --- a/substrate/frame/revive/fixtures/build/Cargo.toml +++ b/substrate/frame/revive/fixtures/build/Cargo.toml @@ -11,7 +11,7 @@ edition = "2021" [dependencies] uapi = { package = 'pallet-revive-uapi', path = "", default-features = false } common = { package = 'pallet-revive-fixtures-common', path = "" } -polkavm-derive = { version = "0.11.0" } +polkavm-derive = { version = "0.12.0" } [profile.release] opt-level = 3 diff --git a/substrate/frame/revive/fixtures/contracts/basic_block.rs b/substrate/frame/revive/fixtures/contracts/basic_block.rs new file mode 100644 index 000000000000..0cde7a264632 --- /dev/null +++ b/substrate/frame/revive/fixtures/contracts/basic_block.rs @@ -0,0 +1,47 @@ +// 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. + +//! Create a basic block that is larger than we allow. + +#![no_std] +#![no_main] + +extern crate common; + +use core::arch::asm; + +// Export that is never called. We can put code here that should be in the binary +// but is never supposed to be run. +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call_never() { + // Stores cannot be optimized away because the optimizer cannot + // know whether they have side effects. + let value: u32 = 42; + unsafe { + // Repeat 1001 times to intentionally exceed the allowed basic block limit (1000) + asm!(".rept 1001", "sw {x}, 0(sp)", ".endr", x = in(reg) value); + } +} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() {} diff --git a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs index e13162f8fb43..129adde2cec9 100644 --- a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs +++ b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs @@ -26,7 +26,8 @@ #![no_std] #![no_main] -use common::input; +extern crate common; + use uapi::{HostFn, HostFnImpl as api}; const BUF_SIZE: usize = 8; @@ -36,7 +37,7 @@ static DATA: [u8; BUF_SIZE] = [1, 2, 3, 4, 5, 6, 7, 8]; /// and expect the call output to match `expected_output`. fn assert_call(callee_address: &[u8; 20], expected_output: [u8; BUF_SIZE]) { let mut output_buf = [0u8; BUF_SIZE]; - let mut output_buf_capped = &mut &mut output_buf[..N]; + let output_buf_capped = &mut &mut output_buf[..N]; api::call( uapi::CallFlags::ALLOW_REENTRY, @@ -62,7 +63,7 @@ fn assert_instantiate(expected_output: [u8; BUF_SIZE]) { api::own_code_hash(&mut code_hash); let mut output_buf = [0u8; BUF_SIZE]; - let mut output_buf_capped = &mut &mut output_buf[..N]; + let output_buf_capped = &mut &mut output_buf[..N]; api::instantiate( &code_hash, diff --git a/substrate/frame/revive/fixtures/contracts/call_return_code.rs b/substrate/frame/revive/fixtures/contracts/call_return_code.rs index d0d7c1bee2a5..2d13b9f70956 100644 --- a/substrate/frame/revive/fixtures/contracts/call_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/call_return_code.rs @@ -21,7 +21,7 @@ #![no_std] #![no_main] -use common::{input, u256_bytes}; +use common::input; use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] diff --git a/substrate/frame/revive/fixtures/contracts/sbrk.rs b/substrate/frame/revive/fixtures/contracts/sbrk.rs new file mode 100644 index 000000000000..5b0bba99df81 --- /dev/null +++ b/substrate/frame/revive/fixtures/contracts/sbrk.rs @@ -0,0 +1,39 @@ +// 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. + +//! Uses the sbrk instruction in order to test that it is rejected. + +#![no_std] +#![no_main] + +extern crate common; + +// Export that is never called. We can put code here that should be in the binary +// but is never supposed to be run. +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call_never() { + polkavm_derive::sbrk(4); +} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() {} diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 6d87fd904c3f..9986da472c96 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -533,6 +533,10 @@ pub mod pallet { /// The static memory consumption of the blob will be larger than /// [`limits::code::STATIC_MEMORY_BYTES`]. StaticMemoryTooLarge, + /// The program contains a basic block that is larger than allowed. + BasicBlockTooLarge, + /// The program contains an invalid instruction. + InvalidInstruction, /// The contract has reached its maximum number of delegate dependencies. MaxDelegateDependenciesReached, /// The dependency was not found in the contract's delegate dependencies. diff --git a/substrate/frame/revive/src/limits.rs b/substrate/frame/revive/src/limits.rs index 50cdba6d0c91..c6d5ef8d8b1b 100644 --- a/substrate/frame/revive/src/limits.rs +++ b/substrate/frame/revive/src/limits.rs @@ -82,7 +82,6 @@ pub mod code { use super::PAGE_SIZE; use crate::{CodeVec, Config, Error, LOG_TARGET}; use alloc::vec::Vec; - use frame_support::ensure; use sp_runtime::DispatchError; /// The maximum length of a code blob in bytes. @@ -109,6 +108,13 @@ pub mod code { /// The code is stored multiple times as part of the compiled program. const EXTRA_OVERHEAD_PER_CODE_BYTE: u32 = 4; + /// The maximum size of a basic block in number of instructions. + /// + /// We need to limit the size of basic blocks because the interpreters lazy compilation + /// compiles one basic block at a time. A malicious program could trigger the compilation + /// of the whole program by creating one giant basic block otherwise. + const BASIC_BLOCK_SIZE: u32 = 1000; + /// Make sure that the various program parts are within the defined limits. pub fn enforce(blob: Vec) -> Result { fn round_page(n: u32) -> u64 { @@ -123,8 +129,30 @@ pub mod code { Error::::CodeRejected })?; - // this is O(n) but it allows us to be more precise - let num_instructions = program.instructions().count() as u64; + // This scans the whole program but we only do it once on code deployment. + // It is safe to do unchecked math in u32 because the size of the program + // was already checked above. + use polkavm_common::program::ISA32_V1_NoSbrk as ISA; + let mut num_instructions: u32 = 0; + let mut max_basic_block_size: u32 = 0; + let mut basic_block_size: u32 = 0; + for inst in program.instructions(ISA) { + num_instructions += 1; + basic_block_size += 1; + if inst.kind.opcode().starts_new_basic_block() { + max_basic_block_size = max_basic_block_size.max(basic_block_size); + basic_block_size = 0; + } + if matches!(inst.kind, polkavm::program::Instruction::invalid) { + log::debug!(target: LOG_TARGET, "invalid instruction at offset {}", inst.offset); + return Err(>::InvalidInstruction.into()) + } + } + + if max_basic_block_size > BASIC_BLOCK_SIZE { + log::debug!(target: LOG_TARGET, "basic block too large: {max_basic_block_size} limit: {BASIC_BLOCK_SIZE}"); + return Err(Error::::BasicBlockTooLarge.into()) + } // The memory consumptions is the byte size of the whole blob, // minus the RO data payload in the blob, @@ -139,12 +167,17 @@ pub mod code { .saturating_add(round_page(program.rw_data_size())) .saturating_sub(program.rw_data().len() as u64) .saturating_add(round_page(program.stack_size())) - .saturating_add((num_instructions).saturating_mul(BYTES_PER_INSTRUCTION.into())) + .saturating_add( + u64::from(num_instructions).saturating_mul(BYTES_PER_INSTRUCTION.into()), + ) .saturating_add( (program.code().len() as u64).saturating_mul(EXTRA_OVERHEAD_PER_CODE_BYTE.into()), ); - ensure!(memory_size <= STATIC_MEMORY_BYTES as u64, >::StaticMemoryTooLarge); + if memory_size > STATIC_MEMORY_BYTES.into() { + log::debug!(target: LOG_TARGET, "static memory too large: {memory_size} limit: {STATIC_MEMORY_BYTES}"); + return Err(Error::::StaticMemoryTooLarge.into()) + } Ok(blob) } diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index c7d1a8b2cf0d..4816e65f8f5c 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -4396,4 +4396,50 @@ mod run_tests { assert_ok!(builder::call(addr).data(data.to_vec()).build()); }); } + + #[test] + fn sbrk_cannot_be_deployed() { + let (code, _) = compile_module("sbrk").unwrap(); + + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::set_balance(&ALICE, 1_000_000); + + assert_err!( + Contracts::upload_code( + RuntimeOrigin::signed(ALICE), + code.clone(), + deposit_limit::(), + ), + >::InvalidInstruction + ); + + assert_err!( + builder::bare_instantiate(Code::Upload(code)).build().result, + >::InvalidInstruction + ); + }); + } + + #[test] + fn overweight_basic_block_cannot_be_deployed() { + let (code, _) = compile_module("basic_block").unwrap(); + + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::set_balance(&ALICE, 1_000_000); + + assert_err!( + Contracts::upload_code( + RuntimeOrigin::signed(ALICE), + code.clone(), + deposit_limit::(), + ), + >::BasicBlockTooLarge + ); + + assert_err!( + builder::bare_instantiate(Code::Upload(code)).build().result, + >::BasicBlockTooLarge + ); + }); + } } diff --git a/substrate/frame/revive/src/wasm/mod.rs b/substrate/frame/revive/src/wasm/mod.rs index cd274873975d..e2256d7dcea7 100644 --- a/substrate/frame/revive/src/wasm/mod.rs +++ b/substrate/frame/revive/src/wasm/mod.rs @@ -291,6 +291,7 @@ impl WasmBlob { let mut module_config = polkavm::ModuleConfig::new(); module_config.set_page_size(limits::PAGE_SIZE); module_config.set_gas_metering(Some(polkavm::GasMeteringKind::Sync)); + module_config.set_allow_sbrk(false); let module = polkavm::Module::new(&engine, &module_config, self.code.into_inner().into()) .map_err(|err| { log::debug!(target: LOG_TARGET, "failed to create polkavm module: {err:?}"); diff --git a/substrate/frame/revive/src/wasm/runtime.rs b/substrate/frame/revive/src/wasm/runtime.rs index 485abbfda225..245c91278a7f 100644 --- a/substrate/frame/revive/src/wasm/runtime.rs +++ b/substrate/frame/revive/src/wasm/runtime.rs @@ -46,9 +46,7 @@ const MAX_DECODE_NESTING: u32 = 256; /// Encode a `U256` into a 32 byte buffer. fn as_bytes(u: U256) -> [u8; 32] { - let mut bytes = [0u8; 32]; - u.to_little_endian(&mut bytes); - bytes + u.to_little_endian() } #[derive(Clone, Copy)] diff --git a/substrate/frame/revive/src/weights.rs b/substrate/frame/revive/src/weights.rs index 5e549de3a9fb..9a1b2310b4eb 100644 --- a/substrate/frame/revive/src/weights.rs +++ b/substrate/frame/revive/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for `pallet_revive` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-10-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-10-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `runner-jniz7bxx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` @@ -126,7 +126,7 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `1594` - // Minimum execution time: 2_700_000 picoseconds. + // Minimum execution time: 2_712_000 picoseconds. Weight::from_parts(2_882_000, 1594) .saturating_add(T::DbWeight::get().reads(1_u64)) } @@ -137,10 +137,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `392 + k * (69 ±0)` // Estimated: `382 + k * (70 ±0)` - // Minimum execution time: 13_819_000 picoseconds. - Weight::from_parts(14_021_000, 382) - // Standard Error: 843 - .saturating_add(Weight::from_parts(1_222_715, 0).saturating_mul(k.into())) + // Minimum execution time: 13_394_000 picoseconds. + Weight::from_parts(13_668_000, 382) + // Standard Error: 2_208 + .saturating_add(Weight::from_parts(1_340_842, 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)) @@ -158,12 +158,14 @@ impl WeightInfo for SubstrateWeight { /// 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 `c` is `[0, 262144]`. - fn call_with_code_per_byte(_c: u32, ) -> Weight { + fn call_with_code_per_byte(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `838` - // Estimated: `4303` - // Minimum execution time: 79_748_000 picoseconds. - Weight::from_parts(82_727_773, 4303) + // Measured: `1466` + // Estimated: `4931` + // Minimum execution time: 80_390_000 picoseconds. + Weight::from_parts(83_627_295, 4931) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -181,16 +183,14 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) /// The range of component `c` is `[0, 262144]`. /// The range of component `i` is `[0, 262144]`. - fn instantiate_with_code(c: u32, i: u32, ) -> Weight { + fn instantiate_with_code(_c: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `303` // Estimated: `6232` - // Minimum execution time: 179_270_000 picoseconds. - Weight::from_parts(149_933_578, 6232) - // Standard Error: 11 - .saturating_add(Weight::from_parts(16, 0).saturating_mul(c.into())) + // Minimum execution time: 184_708_000 picoseconds. + Weight::from_parts(177_995_416, 6232) // Standard Error: 11 - .saturating_add(Weight::from_parts(4_675, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(4_609, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -209,12 +209,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 262144]`. fn instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `657` - // Estimated: `4111` - // Minimum execution time: 156_112_000 picoseconds. - Weight::from_parts(132_715_336, 4111) + // Measured: `1261` + // Estimated: `4706` + // Minimum execution time: 150_137_000 picoseconds. + Weight::from_parts(136_548_469, 4706) // Standard Error: 16 - .saturating_add(Weight::from_parts(4_599, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(4_531, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -230,10 +230,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `838` - // Estimated: `4303` - // Minimum execution time: 82_111_000 picoseconds. - Weight::from_parts(83_659_000, 4303) + // Measured: `1466` + // Estimated: `4931` + // Minimum execution time: 83_178_000 picoseconds. + Weight::from_parts(84_633_000, 4931) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -248,8 +248,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3574` - // Minimum execution time: 49_154_000 picoseconds. - Weight::from_parts(50_856_127, 3574) + // Minimum execution time: 51_526_000 picoseconds. + Weight::from_parts(54_565_973, 3574) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -263,8 +263,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `285` // Estimated: `3750` - // Minimum execution time: 41_347_000 picoseconds. - Weight::from_parts(42_272_000, 3750) + // Minimum execution time: 41_885_000 picoseconds. + Weight::from_parts(42_467_000, 3750) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -274,10 +274,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `495` - // Estimated: `6435` - // Minimum execution time: 25_234_000 picoseconds. - Weight::from_parts(26_339_000, 6435) + // Measured: `492` + // Estimated: `6432` + // Minimum execution time: 24_905_000 picoseconds. + Weight::from_parts(25_483_000, 6432) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -286,17 +286,17 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_509_000 picoseconds. - Weight::from_parts(9_047_452, 0) - // Standard Error: 165 - .saturating_add(Weight::from_parts(197_103, 0).saturating_mul(r.into())) + // Minimum execution time: 6_979_000 picoseconds. + Weight::from_parts(8_272_348, 0) + // Standard Error: 137 + .saturating_add(Weight::from_parts(172_489, 0).saturating_mul(r.into())) } fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 257_000 picoseconds. - Weight::from_parts(300_000, 0) + // Minimum execution time: 251_000 picoseconds. + Weight::from_parts(318_000, 0) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) @@ -304,8 +304,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `272` // Estimated: `3737` - // Minimum execution time: 6_537_000 picoseconds. - Weight::from_parts(7_024_000, 3737) + // Minimum execution time: 6_966_000 picoseconds. + Weight::from_parts(7_240_000, 3737) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) @@ -314,51 +314,51 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `369` // Estimated: `3834` - // Minimum execution time: 7_571_000 picoseconds. - Weight::from_parts(8_060_000, 3834) + // Minimum execution time: 7_589_000 picoseconds. + Weight::from_parts(7_958_000, 3834) .saturating_add(T::DbWeight::get().reads(1_u64)) } fn seal_own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 254_000 picoseconds. - Weight::from_parts(281_000, 0) + // Minimum execution time: 235_000 picoseconds. + Weight::from_parts(285_000, 0) } fn seal_caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 279_000 picoseconds. - Weight::from_parts(338_000, 0) + // Minimum execution time: 283_000 picoseconds. + Weight::from_parts(326_000, 0) } fn seal_caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 240_000 picoseconds. - Weight::from_parts(286_000, 0) + // Minimum execution time: 266_000 picoseconds. + Weight::from_parts(298_000, 0) } fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 198_000 picoseconds. - Weight::from_parts(262_000, 0) + // Minimum execution time: 240_000 picoseconds. + Weight::from_parts(290_000, 0) } fn seal_weight_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 593_000 picoseconds. - Weight::from_parts(665_000, 0) + // Minimum execution time: 651_000 picoseconds. + Weight::from_parts(714_000, 0) } fn seal_balance() -> Weight { // Proof Size summary in bytes: - // Measured: `140` + // Measured: `103` // Estimated: `0` - // Minimum execution time: 5_393_000 picoseconds. - Weight::from_parts(5_688_000, 0) + // Minimum execution time: 4_476_000 picoseconds. + Weight::from_parts(4_671_000, 0) } /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) @@ -366,8 +366,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `52` // Estimated: `3517` - // Minimum execution time: 3_907_000 picoseconds. - Weight::from_parts(4_154_000, 3517) + // Minimum execution time: 3_800_000 picoseconds. + Weight::from_parts(3_968_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Revive::ImmutableDataOf` (r:1 w:0) @@ -377,10 +377,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `205 + n * (1 ±0)` // Estimated: `3670 + n * (1 ±0)` - // Minimum execution time: 5_700_000 picoseconds. - Weight::from_parts(6_362_270, 3670) + // Minimum execution time: 5_845_000 picoseconds. + Weight::from_parts(6_473_478, 3670) // Standard Error: 4 - .saturating_add(Weight::from_parts(749, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(651, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -391,39 +391,39 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_041_000 picoseconds. - Weight::from_parts(2_216_694, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(620, 0).saturating_mul(n.into())) + // Minimum execution time: 1_980_000 picoseconds. + Weight::from_parts(2_324_567, 0) + // Standard Error: 3 + .saturating_add(Weight::from_parts(512, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 229_000 picoseconds. - Weight::from_parts(261_000, 0) + // Minimum execution time: 259_000 picoseconds. + Weight::from_parts(285_000, 0) } fn seal_minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 226_000 picoseconds. - Weight::from_parts(270_000, 0) + // Minimum execution time: 244_000 picoseconds. + Weight::from_parts(291_000, 0) } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 215_000 picoseconds. - Weight::from_parts(273_000, 0) + // Minimum execution time: 252_000 picoseconds. + Weight::from_parts(291_000, 0) } fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 242_000 picoseconds. - Weight::from_parts(271_000, 0) + // Minimum execution time: 245_000 picoseconds. + Weight::from_parts(277_000, 0) } /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) @@ -431,8 +431,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `67` // Estimated: `1552` - // Minimum execution time: 5_438_000 picoseconds. - Weight::from_parts(5_695_000, 1552) + // Minimum execution time: 5_650_000 picoseconds. + Weight::from_parts(5_783_000, 1552) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// The range of component `n` is `[0, 262140]`. @@ -440,20 +440,20 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 405_000 picoseconds. - Weight::from_parts(539_737, 0) + // Minimum execution time: 427_000 picoseconds. + Weight::from_parts(351_577, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(148, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(114, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262140]`. fn seal_return(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 222_000 picoseconds. - Weight::from_parts(539_301, 0) + // Minimum execution time: 265_000 picoseconds. + Weight::from_parts(746_316, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(294, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(202, 0).saturating_mul(n.into())) } /// Storage: `Revive::DeletionQueueCounter` (r:1 w:1) /// Proof: `Revive::DeletionQueueCounter` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) @@ -467,11 +467,11 @@ impl WeightInfo for SubstrateWeight { fn seal_terminate(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `272 + n * (88 ±0)` - // Estimated: `3738 + n * (2563 ±0)` - // Minimum execution time: 15_971_000 picoseconds. - Weight::from_parts(18_759_349, 3738) - // Standard Error: 10_298 - .saturating_add(Weight::from_parts(4_194_635, 0).saturating_mul(n.into())) + // Estimated: `3737 + n * (2563 ±0)` + // Minimum execution time: 15_988_000 picoseconds. + Weight::from_parts(18_796_705, 3737) + // Standard Error: 10_437 + .saturating_add(Weight::from_parts(4_338_085, 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(4_u64)) @@ -484,22 +484,22 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_341_000 picoseconds. - Weight::from_parts(4_292_048, 0) - // Standard Error: 2_476 - .saturating_add(Weight::from_parts(193_480, 0).saturating_mul(t.into())) - // Standard Error: 22 - .saturating_add(Weight::from_parts(959, 0).saturating_mul(n.into())) + // Minimum execution time: 4_237_000 picoseconds. + Weight::from_parts(4_128_112, 0) + // Standard Error: 2_947 + .saturating_add(Weight::from_parts(198_825, 0).saturating_mul(t.into())) + // Standard Error: 26 + .saturating_add(Weight::from_parts(1_007, 0).saturating_mul(n.into())) } /// The range of component `i` is `[0, 262144]`. fn seal_debug_message(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 287_000 picoseconds. - Weight::from_parts(758_020, 0) + // Minimum execution time: 292_000 picoseconds. + Weight::from_parts(1_297_376, 0) // Standard Error: 1 - .saturating_add(Weight::from_parts(814, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(724, 0).saturating_mul(i.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -507,8 +507,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `744` // Estimated: `744` - // Minimum execution time: 7_944_000 picoseconds. - Weight::from_parts(8_358_000, 744) + // Minimum execution time: 7_812_000 picoseconds. + Weight::from_parts(8_171_000, 744) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -517,8 +517,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `10754` // Estimated: `10754` - // Minimum execution time: 44_950_000 picoseconds. - Weight::from_parts(45_575_000, 10754) + // Minimum execution time: 44_179_000 picoseconds. + Weight::from_parts(45_068_000, 10754) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -527,8 +527,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `744` // Estimated: `744` - // Minimum execution time: 9_095_000 picoseconds. - Weight::from_parts(9_484_000, 744) + // Minimum execution time: 8_964_000 picoseconds. + Weight::from_parts(9_336_000, 744) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -538,8 +538,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `10754` // Estimated: `10754` - // Minimum execution time: 46_814_000 picoseconds. - Weight::from_parts(47_710_000, 10754) + // Minimum execution time: 45_606_000 picoseconds. + Weight::from_parts(47_190_000, 10754) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -551,12 +551,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + o * (1 ±0)` // Estimated: `247 + o * (1 ±0)` - // Minimum execution time: 9_496_000 picoseconds. - Weight::from_parts(9_875_533, 247) - // Standard Error: 34 - .saturating_add(Weight::from_parts(712, 0).saturating_mul(n.into())) - // Standard Error: 34 - .saturating_add(Weight::from_parts(777, 0).saturating_mul(o.into())) + // Minimum execution time: 9_077_000 picoseconds. + Weight::from_parts(9_823_489, 247) + // Standard Error: 54 + .saturating_add(Weight::from_parts(392, 0).saturating_mul(n.into())) + // Standard Error: 54 + .saturating_add(Weight::from_parts(408, 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(o.into())) @@ -568,10 +568,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 9_185_000 picoseconds. - Weight::from_parts(9_912_715, 247) - // Standard Error: 59 - .saturating_add(Weight::from_parts(567, 0).saturating_mul(n.into())) + // Minimum execution time: 8_812_000 picoseconds. + Weight::from_parts(9_626_925, 247) + // Standard Error: 77 + .saturating_add(Weight::from_parts(269, 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())) @@ -583,10 +583,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_586_000 picoseconds. - Weight::from_parts(9_536_041, 247) - // Standard Error: 54 - .saturating_add(Weight::from_parts(1_456, 0).saturating_mul(n.into())) + // Minimum execution time: 8_143_000 picoseconds. + Weight::from_parts(9_229_363, 247) + // Standard Error: 77 + .saturating_add(Weight::from_parts(1_198, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -597,10 +597,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_162_000 picoseconds. - Weight::from_parts(8_813_128, 247) - // Standard Error: 43 - .saturating_add(Weight::from_parts(880, 0).saturating_mul(n.into())) + // Minimum execution time: 7_899_000 picoseconds. + Weight::from_parts(8_591_860, 247) + // Standard Error: 56 + .saturating_add(Weight::from_parts(461, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -611,10 +611,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 9_717_000 picoseconds. - Weight::from_parts(10_635_621, 247) - // Standard Error: 58 - .saturating_add(Weight::from_parts(1_430, 0).saturating_mul(n.into())) + // Minimum execution time: 9_215_000 picoseconds. + Weight::from_parts(10_198_528, 247) + // Standard Error: 75 + .saturating_add(Weight::from_parts(1_521, 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())) @@ -623,36 +623,36 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_503_000 picoseconds. - Weight::from_parts(1_592_000, 0) + // Minimum execution time: 1_406_000 picoseconds. + Weight::from_parts(1_515_000, 0) } fn set_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_903_000 picoseconds. - Weight::from_parts(1_996_000, 0) + // Minimum execution time: 1_782_000 picoseconds. + Weight::from_parts(1_890_000, 0) } fn get_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_432_000 picoseconds. - Weight::from_parts(1_534_000, 0) + // Minimum execution time: 1_380_000 picoseconds. + Weight::from_parts(1_422_000, 0) } fn get_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_606_000 picoseconds. - Weight::from_parts(1_669_000, 0) + // Minimum execution time: 1_504_000 picoseconds. + Weight::from_parts(1_583_000, 0) } fn rollback_transient_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 960_000 picoseconds. - Weight::from_parts(1_089_000, 0) + // Minimum execution time: 1_045_000 picoseconds. + Weight::from_parts(1_138_000, 0) } /// The range of component `n` is `[0, 512]`. /// The range of component `o` is `[0, 512]`. @@ -660,59 +660,59 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_317_000 picoseconds. - Weight::from_parts(2_449_933, 0) - // Standard Error: 11 - .saturating_add(Weight::from_parts(315, 0).saturating_mul(n.into())) - // Standard Error: 11 - .saturating_add(Weight::from_parts(387, 0).saturating_mul(o.into())) + // Minimum execution time: 2_039_000 picoseconds. + Weight::from_parts(2_317_406, 0) + // Standard Error: 13 + .saturating_add(Weight::from_parts(283, 0).saturating_mul(n.into())) + // Standard Error: 13 + .saturating_add(Weight::from_parts(347, 0).saturating_mul(o.into())) } /// The range of component `n` is `[0, 512]`. fn seal_clear_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_980_000 picoseconds. - Weight::from_parts(2_352_243, 0) + // Minimum execution time: 1_880_000 picoseconds. + Weight::from_parts(2_251_392, 0) // Standard Error: 17 - .saturating_add(Weight::from_parts(372, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(313, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. fn seal_get_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_857_000 picoseconds. - Weight::from_parts(2_082_050, 0) + // Minimum execution time: 1_763_000 picoseconds. + Weight::from_parts(1_951_912, 0) // Standard Error: 13 - .saturating_add(Weight::from_parts(373, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(268, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. fn seal_contains_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_693_000 picoseconds. - Weight::from_parts(1_892_600, 0) - // Standard Error: 13 - .saturating_add(Weight::from_parts(193, 0).saturating_mul(n.into())) + // Minimum execution time: 1_536_000 picoseconds. + Weight::from_parts(1_779_085, 0) + // Standard Error: 14 + .saturating_add(Weight::from_parts(148, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. fn seal_take_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_620_000 picoseconds. - Weight::from_parts(2_818_388, 0) - // Standard Error: 15 - .saturating_add(Weight::from_parts(39, 0).saturating_mul(n.into())) + // Minimum execution time: 2_343_000 picoseconds. + Weight::from_parts(2_587_750, 0) + // Standard Error: 22 + .saturating_add(Weight::from_parts(30, 0).saturating_mul(n.into())) } fn seal_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `140` + // Measured: `103` // Estimated: `0` - // Minimum execution time: 10_207_000 picoseconds. - Weight::from_parts(10_627_000, 0) + // Minimum execution time: 9_250_000 picoseconds. + Weight::from_parts(9_637_000, 0) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) @@ -724,17 +724,17 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 262144]`. fn seal_call(t: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `630 + t * (140 ±0)` - // Estimated: `4095 + t * (140 ±0)` - // Minimum execution time: 34_452_000 picoseconds. - Weight::from_parts(34_837_900, 4095) - // Standard Error: 30_385 - .saturating_add(Weight::from_parts(1_981_565, 0).saturating_mul(t.into())) + // Measured: `1221 + t * (103 ±0)` + // Estimated: `4686 + t * (103 ±0)` + // Minimum execution time: 33_333_000 picoseconds. + Weight::from_parts(34_378_774, 4686) + // Standard Error: 41_131 + .saturating_add(Weight::from_parts(1_756_626, 0).saturating_mul(t.into())) // Standard Error: 0 .saturating_add(Weight::from_parts(3, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 140).saturating_mul(t.into())) + .saturating_add(Weight::from_parts(0, 103).saturating_mul(t.into())) } /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) @@ -742,10 +742,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) fn seal_delegate_call() -> Weight { // Proof Size summary in bytes: - // Measured: `457` - // Estimated: `3922` - // Minimum execution time: 27_287_000 picoseconds. - Weight::from_parts(28_450_000, 3922) + // Measured: `1048` + // Estimated: `4513` + // Minimum execution time: 27_096_000 picoseconds. + Weight::from_parts(27_934_000, 4513) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) @@ -759,12 +759,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 262144]`. fn seal_instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `703` - // Estimated: `4160` - // Minimum execution time: 118_660_000 picoseconds. - Weight::from_parts(104_638_796, 4160) - // Standard Error: 11 - .saturating_add(Weight::from_parts(4_296, 0).saturating_mul(i.into())) + // Measured: `1257` + // Estimated: `4715` + // Minimum execution time: 118_412_000 picoseconds. + Weight::from_parts(106_130_041, 4715) + // Standard Error: 12 + .saturating_add(Weight::from_parts(4_235, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -773,64 +773,64 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 683_000 picoseconds. - Weight::from_parts(3_836_563, 0) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_456, 0).saturating_mul(n.into())) + // Minimum execution time: 614_000 picoseconds. + Weight::from_parts(4_320_897, 0) + // Standard Error: 3 + .saturating_add(Weight::from_parts(1_371, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_082_000 picoseconds. - Weight::from_parts(5_027_764, 0) + // Minimum execution time: 1_062_000 picoseconds. + Weight::from_parts(4_571_371, 0) // Standard Error: 3 - .saturating_add(Weight::from_parts(3_644, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_572, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 660_000 picoseconds. - Weight::from_parts(3_585_640, 0) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_586, 0).saturating_mul(n.into())) + // Minimum execution time: 609_000 picoseconds. + Weight::from_parts(4_008_056, 0) + // Standard Error: 3 + .saturating_add(Weight::from_parts(1_497, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 638_000 picoseconds. - Weight::from_parts(3_763_242, 0) + // Minimum execution time: 608_000 picoseconds. + Weight::from_parts(3_839_383, 0) // Standard Error: 3 - .saturating_add(Weight::from_parts(1_582, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_504, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 261889]`. fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 42_962_000 picoseconds. - Weight::from_parts(27_938_396, 0) - // Standard Error: 13 - .saturating_add(Weight::from_parts(5_269, 0).saturating_mul(n.into())) + // Minimum execution time: 43_110_000 picoseconds. + Weight::from_parts(31_941_593, 0) + // Standard Error: 12 + .saturating_add(Weight::from_parts(5_233, 0).saturating_mul(n.into())) } fn seal_ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 47_133_000 picoseconds. - Weight::from_parts(48_458_000, 0) + // Minimum execution time: 47_798_000 picoseconds. + Weight::from_parts(49_225_000, 0) } fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_249_000 picoseconds. - Weight::from_parts(13_518_000, 0) + // Minimum execution time: 12_576_000 picoseconds. + Weight::from_parts(12_731_000, 0) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) @@ -838,8 +838,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `266` // Estimated: `3731` - // Minimum execution time: 14_696_000 picoseconds. - Weight::from_parts(15_106_000, 3731) + // Minimum execution time: 14_306_000 picoseconds. + Weight::from_parts(15_011_000, 3731) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -847,10 +847,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn lock_delegate_dependency() -> Weight { // Proof Size summary in bytes: - // Measured: `304` - // Estimated: `3769` - // Minimum execution time: 10_292_000 picoseconds. - Weight::from_parts(10_670_000, 3769) + // Measured: `303` + // Estimated: `3768` + // Minimum execution time: 10_208_000 picoseconds. + Weight::from_parts(10_514_000, 3768) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -858,10 +858,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `MaxEncodedLen`) fn unlock_delegate_dependency() -> Weight { // Proof Size summary in bytes: - // Measured: `304` + // Measured: `303` // Estimated: `3561` - // Minimum execution time: 9_056_000 picoseconds. - Weight::from_parts(9_350_000, 3561) + // Minimum execution time: 9_062_000 picoseconds. + Weight::from_parts(9_414_000, 3561) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -870,10 +870,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_145_000 picoseconds. - Weight::from_parts(10_744_073, 0) - // Standard Error: 72 - .saturating_add(Weight::from_parts(84_813, 0).saturating_mul(r.into())) + // Minimum execution time: 8_074_000 picoseconds. + Weight::from_parts(9_646_158, 0) + // Standard Error: 58 + .saturating_add(Weight::from_parts(84_694, 0).saturating_mul(r.into())) } } @@ -885,7 +885,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `109` // Estimated: `1594` - // Minimum execution time: 2_700_000 picoseconds. + // Minimum execution time: 2_712_000 picoseconds. Weight::from_parts(2_882_000, 1594) .saturating_add(RocksDbWeight::get().reads(1_u64)) } @@ -896,10 +896,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `392 + k * (69 ±0)` // Estimated: `382 + k * (70 ±0)` - // Minimum execution time: 13_819_000 picoseconds. - Weight::from_parts(14_021_000, 382) - // Standard Error: 843 - .saturating_add(Weight::from_parts(1_222_715, 0).saturating_mul(k.into())) + // Minimum execution time: 13_394_000 picoseconds. + Weight::from_parts(13_668_000, 382) + // Standard Error: 2_208 + .saturating_add(Weight::from_parts(1_340_842, 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)) @@ -917,12 +917,14 @@ impl WeightInfo for () { /// 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 `c` is `[0, 262144]`. - fn call_with_code_per_byte(_c: u32, ) -> Weight { + fn call_with_code_per_byte(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `838` - // Estimated: `4303` - // Minimum execution time: 79_748_000 picoseconds. - Weight::from_parts(82_727_773, 4303) + // Measured: `1466` + // Estimated: `4931` + // Minimum execution time: 80_390_000 picoseconds. + Weight::from_parts(83_627_295, 4931) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -940,16 +942,14 @@ impl WeightInfo for () { /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) /// The range of component `c` is `[0, 262144]`. /// The range of component `i` is `[0, 262144]`. - fn instantiate_with_code(c: u32, i: u32, ) -> Weight { + fn instantiate_with_code(_c: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `303` // Estimated: `6232` - // Minimum execution time: 179_270_000 picoseconds. - Weight::from_parts(149_933_578, 6232) - // Standard Error: 11 - .saturating_add(Weight::from_parts(16, 0).saturating_mul(c.into())) + // Minimum execution time: 184_708_000 picoseconds. + Weight::from_parts(177_995_416, 6232) // Standard Error: 11 - .saturating_add(Weight::from_parts(4_675, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(4_609, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -968,12 +968,12 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 262144]`. fn instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `657` - // Estimated: `4111` - // Minimum execution time: 156_112_000 picoseconds. - Weight::from_parts(132_715_336, 4111) + // Measured: `1261` + // Estimated: `4706` + // Minimum execution time: 150_137_000 picoseconds. + Weight::from_parts(136_548_469, 4706) // Standard Error: 16 - .saturating_add(Weight::from_parts(4_599, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(4_531, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -989,10 +989,10 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `838` - // Estimated: `4303` - // Minimum execution time: 82_111_000 picoseconds. - Weight::from_parts(83_659_000, 4303) + // Measured: `1466` + // Estimated: `4931` + // Minimum execution time: 83_178_000 picoseconds. + Weight::from_parts(84_633_000, 4931) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1007,8 +1007,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3574` - // Minimum execution time: 49_154_000 picoseconds. - Weight::from_parts(50_856_127, 3574) + // Minimum execution time: 51_526_000 picoseconds. + Weight::from_parts(54_565_973, 3574) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1022,8 +1022,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `285` // Estimated: `3750` - // Minimum execution time: 41_347_000 picoseconds. - Weight::from_parts(42_272_000, 3750) + // Minimum execution time: 41_885_000 picoseconds. + Weight::from_parts(42_467_000, 3750) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1033,10 +1033,10 @@ impl WeightInfo for () { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `495` - // Estimated: `6435` - // Minimum execution time: 25_234_000 picoseconds. - Weight::from_parts(26_339_000, 6435) + // Measured: `492` + // Estimated: `6432` + // Minimum execution time: 24_905_000 picoseconds. + Weight::from_parts(25_483_000, 6432) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1045,17 +1045,17 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_509_000 picoseconds. - Weight::from_parts(9_047_452, 0) - // Standard Error: 165 - .saturating_add(Weight::from_parts(197_103, 0).saturating_mul(r.into())) + // Minimum execution time: 6_979_000 picoseconds. + Weight::from_parts(8_272_348, 0) + // Standard Error: 137 + .saturating_add(Weight::from_parts(172_489, 0).saturating_mul(r.into())) } fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 257_000 picoseconds. - Weight::from_parts(300_000, 0) + // Minimum execution time: 251_000 picoseconds. + Weight::from_parts(318_000, 0) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) @@ -1063,8 +1063,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `272` // Estimated: `3737` - // Minimum execution time: 6_537_000 picoseconds. - Weight::from_parts(7_024_000, 3737) + // Minimum execution time: 6_966_000 picoseconds. + Weight::from_parts(7_240_000, 3737) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) @@ -1073,51 +1073,51 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `369` // Estimated: `3834` - // Minimum execution time: 7_571_000 picoseconds. - Weight::from_parts(8_060_000, 3834) + // Minimum execution time: 7_589_000 picoseconds. + Weight::from_parts(7_958_000, 3834) .saturating_add(RocksDbWeight::get().reads(1_u64)) } fn seal_own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 254_000 picoseconds. - Weight::from_parts(281_000, 0) + // Minimum execution time: 235_000 picoseconds. + Weight::from_parts(285_000, 0) } fn seal_caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 279_000 picoseconds. - Weight::from_parts(338_000, 0) + // Minimum execution time: 283_000 picoseconds. + Weight::from_parts(326_000, 0) } fn seal_caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 240_000 picoseconds. - Weight::from_parts(286_000, 0) + // Minimum execution time: 266_000 picoseconds. + Weight::from_parts(298_000, 0) } fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 198_000 picoseconds. - Weight::from_parts(262_000, 0) + // Minimum execution time: 240_000 picoseconds. + Weight::from_parts(290_000, 0) } fn seal_weight_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 593_000 picoseconds. - Weight::from_parts(665_000, 0) + // Minimum execution time: 651_000 picoseconds. + Weight::from_parts(714_000, 0) } fn seal_balance() -> Weight { // Proof Size summary in bytes: - // Measured: `140` + // Measured: `103` // Estimated: `0` - // Minimum execution time: 5_393_000 picoseconds. - Weight::from_parts(5_688_000, 0) + // Minimum execution time: 4_476_000 picoseconds. + Weight::from_parts(4_671_000, 0) } /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) @@ -1125,8 +1125,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `52` // Estimated: `3517` - // Minimum execution time: 3_907_000 picoseconds. - Weight::from_parts(4_154_000, 3517) + // Minimum execution time: 3_800_000 picoseconds. + Weight::from_parts(3_968_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Revive::ImmutableDataOf` (r:1 w:0) @@ -1136,10 +1136,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `205 + n * (1 ±0)` // Estimated: `3670 + n * (1 ±0)` - // Minimum execution time: 5_700_000 picoseconds. - Weight::from_parts(6_362_270, 3670) + // Minimum execution time: 5_845_000 picoseconds. + Weight::from_parts(6_473_478, 3670) // Standard Error: 4 - .saturating_add(Weight::from_parts(749, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(651, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1150,39 +1150,39 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_041_000 picoseconds. - Weight::from_parts(2_216_694, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(620, 0).saturating_mul(n.into())) + // Minimum execution time: 1_980_000 picoseconds. + Weight::from_parts(2_324_567, 0) + // Standard Error: 3 + .saturating_add(Weight::from_parts(512, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().writes(1_u64)) } fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 229_000 picoseconds. - Weight::from_parts(261_000, 0) + // Minimum execution time: 259_000 picoseconds. + Weight::from_parts(285_000, 0) } fn seal_minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 226_000 picoseconds. - Weight::from_parts(270_000, 0) + // Minimum execution time: 244_000 picoseconds. + Weight::from_parts(291_000, 0) } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 215_000 picoseconds. - Weight::from_parts(273_000, 0) + // Minimum execution time: 252_000 picoseconds. + Weight::from_parts(291_000, 0) } fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 242_000 picoseconds. - Weight::from_parts(271_000, 0) + // Minimum execution time: 245_000 picoseconds. + Weight::from_parts(277_000, 0) } /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) @@ -1190,8 +1190,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `67` // Estimated: `1552` - // Minimum execution time: 5_438_000 picoseconds. - Weight::from_parts(5_695_000, 1552) + // Minimum execution time: 5_650_000 picoseconds. + Weight::from_parts(5_783_000, 1552) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// The range of component `n` is `[0, 262140]`. @@ -1199,20 +1199,20 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 405_000 picoseconds. - Weight::from_parts(539_737, 0) + // Minimum execution time: 427_000 picoseconds. + Weight::from_parts(351_577, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(148, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(114, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262140]`. fn seal_return(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 222_000 picoseconds. - Weight::from_parts(539_301, 0) + // Minimum execution time: 265_000 picoseconds. + Weight::from_parts(746_316, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(294, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(202, 0).saturating_mul(n.into())) } /// Storage: `Revive::DeletionQueueCounter` (r:1 w:1) /// Proof: `Revive::DeletionQueueCounter` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) @@ -1226,11 +1226,11 @@ impl WeightInfo for () { fn seal_terminate(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `272 + n * (88 ±0)` - // Estimated: `3738 + n * (2563 ±0)` - // Minimum execution time: 15_971_000 picoseconds. - Weight::from_parts(18_759_349, 3738) - // Standard Error: 10_298 - .saturating_add(Weight::from_parts(4_194_635, 0).saturating_mul(n.into())) + // Estimated: `3737 + n * (2563 ±0)` + // Minimum execution time: 15_988_000 picoseconds. + Weight::from_parts(18_796_705, 3737) + // Standard Error: 10_437 + .saturating_add(Weight::from_parts(4_338_085, 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(4_u64)) @@ -1243,22 +1243,22 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_341_000 picoseconds. - Weight::from_parts(4_292_048, 0) - // Standard Error: 2_476 - .saturating_add(Weight::from_parts(193_480, 0).saturating_mul(t.into())) - // Standard Error: 22 - .saturating_add(Weight::from_parts(959, 0).saturating_mul(n.into())) + // Minimum execution time: 4_237_000 picoseconds. + Weight::from_parts(4_128_112, 0) + // Standard Error: 2_947 + .saturating_add(Weight::from_parts(198_825, 0).saturating_mul(t.into())) + // Standard Error: 26 + .saturating_add(Weight::from_parts(1_007, 0).saturating_mul(n.into())) } /// The range of component `i` is `[0, 262144]`. fn seal_debug_message(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 287_000 picoseconds. - Weight::from_parts(758_020, 0) + // Minimum execution time: 292_000 picoseconds. + Weight::from_parts(1_297_376, 0) // Standard Error: 1 - .saturating_add(Weight::from_parts(814, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(724, 0).saturating_mul(i.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1266,8 +1266,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `744` // Estimated: `744` - // Minimum execution time: 7_944_000 picoseconds. - Weight::from_parts(8_358_000, 744) + // Minimum execution time: 7_812_000 picoseconds. + Weight::from_parts(8_171_000, 744) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1276,8 +1276,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `10754` // Estimated: `10754` - // Minimum execution time: 44_950_000 picoseconds. - Weight::from_parts(45_575_000, 10754) + // Minimum execution time: 44_179_000 picoseconds. + Weight::from_parts(45_068_000, 10754) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1286,8 +1286,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `744` // Estimated: `744` - // Minimum execution time: 9_095_000 picoseconds. - Weight::from_parts(9_484_000, 744) + // Minimum execution time: 8_964_000 picoseconds. + Weight::from_parts(9_336_000, 744) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1297,8 +1297,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `10754` // Estimated: `10754` - // Minimum execution time: 46_814_000 picoseconds. - Weight::from_parts(47_710_000, 10754) + // Minimum execution time: 45_606_000 picoseconds. + Weight::from_parts(47_190_000, 10754) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1310,12 +1310,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + o * (1 ±0)` // Estimated: `247 + o * (1 ±0)` - // Minimum execution time: 9_496_000 picoseconds. - Weight::from_parts(9_875_533, 247) - // Standard Error: 34 - .saturating_add(Weight::from_parts(712, 0).saturating_mul(n.into())) - // Standard Error: 34 - .saturating_add(Weight::from_parts(777, 0).saturating_mul(o.into())) + // Minimum execution time: 9_077_000 picoseconds. + Weight::from_parts(9_823_489, 247) + // Standard Error: 54 + .saturating_add(Weight::from_parts(392, 0).saturating_mul(n.into())) + // Standard Error: 54 + .saturating_add(Weight::from_parts(408, 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(o.into())) @@ -1327,10 +1327,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 9_185_000 picoseconds. - Weight::from_parts(9_912_715, 247) - // Standard Error: 59 - .saturating_add(Weight::from_parts(567, 0).saturating_mul(n.into())) + // Minimum execution time: 8_812_000 picoseconds. + Weight::from_parts(9_626_925, 247) + // Standard Error: 77 + .saturating_add(Weight::from_parts(269, 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())) @@ -1342,10 +1342,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_586_000 picoseconds. - Weight::from_parts(9_536_041, 247) - // Standard Error: 54 - .saturating_add(Weight::from_parts(1_456, 0).saturating_mul(n.into())) + // Minimum execution time: 8_143_000 picoseconds. + Weight::from_parts(9_229_363, 247) + // Standard Error: 77 + .saturating_add(Weight::from_parts(1_198, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1356,10 +1356,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_162_000 picoseconds. - Weight::from_parts(8_813_128, 247) - // Standard Error: 43 - .saturating_add(Weight::from_parts(880, 0).saturating_mul(n.into())) + // Minimum execution time: 7_899_000 picoseconds. + Weight::from_parts(8_591_860, 247) + // Standard Error: 56 + .saturating_add(Weight::from_parts(461, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1370,10 +1370,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 9_717_000 picoseconds. - Weight::from_parts(10_635_621, 247) - // Standard Error: 58 - .saturating_add(Weight::from_parts(1_430, 0).saturating_mul(n.into())) + // Minimum execution time: 9_215_000 picoseconds. + Weight::from_parts(10_198_528, 247) + // Standard Error: 75 + .saturating_add(Weight::from_parts(1_521, 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())) @@ -1382,36 +1382,36 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_503_000 picoseconds. - Weight::from_parts(1_592_000, 0) + // Minimum execution time: 1_406_000 picoseconds. + Weight::from_parts(1_515_000, 0) } fn set_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_903_000 picoseconds. - Weight::from_parts(1_996_000, 0) + // Minimum execution time: 1_782_000 picoseconds. + Weight::from_parts(1_890_000, 0) } fn get_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_432_000 picoseconds. - Weight::from_parts(1_534_000, 0) + // Minimum execution time: 1_380_000 picoseconds. + Weight::from_parts(1_422_000, 0) } fn get_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_606_000 picoseconds. - Weight::from_parts(1_669_000, 0) + // Minimum execution time: 1_504_000 picoseconds. + Weight::from_parts(1_583_000, 0) } fn rollback_transient_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 960_000 picoseconds. - Weight::from_parts(1_089_000, 0) + // Minimum execution time: 1_045_000 picoseconds. + Weight::from_parts(1_138_000, 0) } /// The range of component `n` is `[0, 512]`. /// The range of component `o` is `[0, 512]`. @@ -1419,59 +1419,59 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_317_000 picoseconds. - Weight::from_parts(2_449_933, 0) - // Standard Error: 11 - .saturating_add(Weight::from_parts(315, 0).saturating_mul(n.into())) - // Standard Error: 11 - .saturating_add(Weight::from_parts(387, 0).saturating_mul(o.into())) + // Minimum execution time: 2_039_000 picoseconds. + Weight::from_parts(2_317_406, 0) + // Standard Error: 13 + .saturating_add(Weight::from_parts(283, 0).saturating_mul(n.into())) + // Standard Error: 13 + .saturating_add(Weight::from_parts(347, 0).saturating_mul(o.into())) } /// The range of component `n` is `[0, 512]`. fn seal_clear_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_980_000 picoseconds. - Weight::from_parts(2_352_243, 0) + // Minimum execution time: 1_880_000 picoseconds. + Weight::from_parts(2_251_392, 0) // Standard Error: 17 - .saturating_add(Weight::from_parts(372, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(313, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. fn seal_get_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_857_000 picoseconds. - Weight::from_parts(2_082_050, 0) + // Minimum execution time: 1_763_000 picoseconds. + Weight::from_parts(1_951_912, 0) // Standard Error: 13 - .saturating_add(Weight::from_parts(373, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(268, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. fn seal_contains_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_693_000 picoseconds. - Weight::from_parts(1_892_600, 0) - // Standard Error: 13 - .saturating_add(Weight::from_parts(193, 0).saturating_mul(n.into())) + // Minimum execution time: 1_536_000 picoseconds. + Weight::from_parts(1_779_085, 0) + // Standard Error: 14 + .saturating_add(Weight::from_parts(148, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. fn seal_take_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_620_000 picoseconds. - Weight::from_parts(2_818_388, 0) - // Standard Error: 15 - .saturating_add(Weight::from_parts(39, 0).saturating_mul(n.into())) + // Minimum execution time: 2_343_000 picoseconds. + Weight::from_parts(2_587_750, 0) + // Standard Error: 22 + .saturating_add(Weight::from_parts(30, 0).saturating_mul(n.into())) } fn seal_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `140` + // Measured: `103` // Estimated: `0` - // Minimum execution time: 10_207_000 picoseconds. - Weight::from_parts(10_627_000, 0) + // Minimum execution time: 9_250_000 picoseconds. + Weight::from_parts(9_637_000, 0) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) @@ -1483,17 +1483,17 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 262144]`. fn seal_call(t: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `630 + t * (140 ±0)` - // Estimated: `4095 + t * (140 ±0)` - // Minimum execution time: 34_452_000 picoseconds. - Weight::from_parts(34_837_900, 4095) - // Standard Error: 30_385 - .saturating_add(Weight::from_parts(1_981_565, 0).saturating_mul(t.into())) + // Measured: `1221 + t * (103 ±0)` + // Estimated: `4686 + t * (103 ±0)` + // Minimum execution time: 33_333_000 picoseconds. + Weight::from_parts(34_378_774, 4686) + // Standard Error: 41_131 + .saturating_add(Weight::from_parts(1_756_626, 0).saturating_mul(t.into())) // Standard Error: 0 .saturating_add(Weight::from_parts(3, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 140).saturating_mul(t.into())) + .saturating_add(Weight::from_parts(0, 103).saturating_mul(t.into())) } /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) @@ -1501,10 +1501,10 @@ impl WeightInfo for () { /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) fn seal_delegate_call() -> Weight { // Proof Size summary in bytes: - // Measured: `457` - // Estimated: `3922` - // Minimum execution time: 27_287_000 picoseconds. - Weight::from_parts(28_450_000, 3922) + // Measured: `1048` + // Estimated: `4513` + // Minimum execution time: 27_096_000 picoseconds. + Weight::from_parts(27_934_000, 4513) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) @@ -1518,12 +1518,12 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 262144]`. fn seal_instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `703` - // Estimated: `4160` - // Minimum execution time: 118_660_000 picoseconds. - Weight::from_parts(104_638_796, 4160) - // Standard Error: 11 - .saturating_add(Weight::from_parts(4_296, 0).saturating_mul(i.into())) + // Measured: `1257` + // Estimated: `4715` + // Minimum execution time: 118_412_000 picoseconds. + Weight::from_parts(106_130_041, 4715) + // Standard Error: 12 + .saturating_add(Weight::from_parts(4_235, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1532,64 +1532,64 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 683_000 picoseconds. - Weight::from_parts(3_836_563, 0) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_456, 0).saturating_mul(n.into())) + // Minimum execution time: 614_000 picoseconds. + Weight::from_parts(4_320_897, 0) + // Standard Error: 3 + .saturating_add(Weight::from_parts(1_371, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_082_000 picoseconds. - Weight::from_parts(5_027_764, 0) + // Minimum execution time: 1_062_000 picoseconds. + Weight::from_parts(4_571_371, 0) // Standard Error: 3 - .saturating_add(Weight::from_parts(3_644, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_572, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 660_000 picoseconds. - Weight::from_parts(3_585_640, 0) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_586, 0).saturating_mul(n.into())) + // Minimum execution time: 609_000 picoseconds. + Weight::from_parts(4_008_056, 0) + // Standard Error: 3 + .saturating_add(Weight::from_parts(1_497, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 638_000 picoseconds. - Weight::from_parts(3_763_242, 0) + // Minimum execution time: 608_000 picoseconds. + Weight::from_parts(3_839_383, 0) // Standard Error: 3 - .saturating_add(Weight::from_parts(1_582, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_504, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 261889]`. fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 42_962_000 picoseconds. - Weight::from_parts(27_938_396, 0) - // Standard Error: 13 - .saturating_add(Weight::from_parts(5_269, 0).saturating_mul(n.into())) + // Minimum execution time: 43_110_000 picoseconds. + Weight::from_parts(31_941_593, 0) + // Standard Error: 12 + .saturating_add(Weight::from_parts(5_233, 0).saturating_mul(n.into())) } fn seal_ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 47_133_000 picoseconds. - Weight::from_parts(48_458_000, 0) + // Minimum execution time: 47_798_000 picoseconds. + Weight::from_parts(49_225_000, 0) } fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_249_000 picoseconds. - Weight::from_parts(13_518_000, 0) + // Minimum execution time: 12_576_000 picoseconds. + Weight::from_parts(12_731_000, 0) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) @@ -1597,8 +1597,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `266` // Estimated: `3731` - // Minimum execution time: 14_696_000 picoseconds. - Weight::from_parts(15_106_000, 3731) + // Minimum execution time: 14_306_000 picoseconds. + Weight::from_parts(15_011_000, 3731) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1606,10 +1606,10 @@ impl WeightInfo for () { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn lock_delegate_dependency() -> Weight { // Proof Size summary in bytes: - // Measured: `304` - // Estimated: `3769` - // Minimum execution time: 10_292_000 picoseconds. - Weight::from_parts(10_670_000, 3769) + // Measured: `303` + // Estimated: `3768` + // Minimum execution time: 10_208_000 picoseconds. + Weight::from_parts(10_514_000, 3768) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1617,10 +1617,10 @@ impl WeightInfo for () { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `MaxEncodedLen`) fn unlock_delegate_dependency() -> Weight { // Proof Size summary in bytes: - // Measured: `304` + // Measured: `303` // Estimated: `3561` - // Minimum execution time: 9_056_000 picoseconds. - Weight::from_parts(9_350_000, 3561) + // Minimum execution time: 9_062_000 picoseconds. + Weight::from_parts(9_414_000, 3561) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1629,9 +1629,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_145_000 picoseconds. - Weight::from_parts(10_744_073, 0) - // Standard Error: 72 - .saturating_add(Weight::from_parts(84_813, 0).saturating_mul(r.into())) + // Minimum execution time: 8_074_000 picoseconds. + Weight::from_parts(9_646_158, 0) + // Standard Error: 58 + .saturating_add(Weight::from_parts(84_694, 0).saturating_mul(r.into())) } } diff --git a/substrate/frame/revive/uapi/Cargo.toml b/substrate/frame/revive/uapi/Cargo.toml index 52de77a10944..8705781db002 100644 --- a/substrate/frame/revive/uapi/Cargo.toml +++ b/substrate/frame/revive/uapi/Cargo.toml @@ -21,7 +21,7 @@ codec = { features = [ ], optional = true, workspace = true } [target.'cfg(target_arch = "riscv32")'.dependencies] -polkavm-derive = { version = "0.11.0" } +polkavm-derive = { version = "0.12.0" } [package.metadata.docs.rs] default-target = ["wasm32-unknown-unknown"] diff --git a/substrate/frame/root-offences/src/tests.rs b/substrate/frame/root-offences/src/tests.rs index f96884d750da..289bb708efbb 100644 --- a/substrate/frame/root-offences/src/tests.rs +++ b/substrate/frame/root-offences/src/tests.rs @@ -17,7 +17,8 @@ use super::*; use frame_support::{assert_err, assert_ok}; -use mock::{active_era, start_session, Balances, ExtBuilder, RootOffences, RuntimeOrigin, System}; +use mock::{active_era, start_session, ExtBuilder, RootOffences, RuntimeOrigin, System, Test as T}; +use pallet_staking::asset; #[test] fn create_offence_fails_given_signed_origin() { @@ -35,18 +36,18 @@ fn create_offence_works_given_root_origin() { assert_eq!(active_era(), 0); - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::staked::(&11), 1000); let offenders = [(11, Perbill::from_percent(50))].to_vec(); assert_ok!(RootOffences::create_offence(RuntimeOrigin::root(), offenders.clone())); System::assert_last_event(Event::OffenceCreated { offenders }.into()); // the slash should be applied right away. - assert_eq!(Balances::free_balance(11), 500); + assert_eq!(asset::staked::(&11), 500); // the other validator should keep their balance, because we only created // an offences for the first validator. - assert_eq!(Balances::free_balance(21), 1000); + assert_eq!(asset::staked::(&21), 1000); }) } @@ -58,7 +59,7 @@ fn create_offence_wont_slash_non_active_validators() { assert_eq!(active_era(), 0); // 31 is not an active validator. - assert_eq!(Balances::free_balance(31), 500); + assert_eq!(asset::staked::(&31), 500); let offenders = [(31, Perbill::from_percent(20)), (11, Perbill::from_percent(20))].to_vec(); assert_ok!(RootOffences::create_offence(RuntimeOrigin::root(), offenders.clone())); @@ -66,10 +67,10 @@ fn create_offence_wont_slash_non_active_validators() { System::assert_last_event(Event::OffenceCreated { offenders }.into()); // so 31 didn't get slashed. - assert_eq!(Balances::free_balance(31), 500); + assert_eq!(asset::staked::(&31), 500); // but 11 is an active validator so they got slashed. - assert_eq!(Balances::free_balance(11), 800); + assert_eq!(asset::staked::(&11), 800); }) } @@ -81,7 +82,7 @@ fn create_offence_wont_slash_idle() { assert_eq!(active_era(), 0); // 41 is idle. - assert_eq!(Balances::free_balance(41), 1000); + assert_eq!(asset::staked::(&41), 1000); let offenders = [(41, Perbill::from_percent(50))].to_vec(); assert_ok!(RootOffences::create_offence(RuntimeOrigin::root(), offenders.clone())); @@ -89,6 +90,6 @@ fn create_offence_wont_slash_idle() { System::assert_last_event(Event::OffenceCreated { offenders }.into()); // 41 didn't get slashed. - assert_eq!(Balances::free_balance(41), 1000); + assert_eq!(asset::staked::(&41), 1000); }) } diff --git a/substrate/frame/sassafras/src/mock.rs b/substrate/frame/sassafras/src/mock.rs index f145bffa3a05..d2b329e8a2ba 100644 --- a/substrate/frame/sassafras/src/mock.rs +++ b/substrate/frame/sassafras/src/mock.rs @@ -89,7 +89,7 @@ pub fn new_test_ext_with_pairs( with_ring_context: bool, ) -> (Vec, sp_io::TestExternalities) { let pairs = (0..authorities_len) - .map(|i| AuthorityPair::from_seed(&U256::from(i).into())) + .map(|i| AuthorityPair::from_seed(&U256::from(i).to_big_endian())) .collect::>(); let authorities: Vec<_> = pairs.iter().map(|p| p.public()).collect(); diff --git a/substrate/frame/staking/src/asset.rs b/substrate/frame/staking/src/asset.rs new file mode 100644 index 000000000000..23368b1f8fca --- /dev/null +++ b/substrate/frame/staking/src/asset.rs @@ -0,0 +1,125 @@ +// 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. + +//! Contains all the interactions with [`Config::Currency`] to manipulate the underlying staking +//! asset. + +use frame_support::traits::{Currency, InspectLockableCurrency, LockableCurrency}; + +use crate::{BalanceOf, Config, NegativeImbalanceOf, PositiveImbalanceOf}; + +/// Existential deposit for the chain. +pub fn existential_deposit() -> BalanceOf { + T::Currency::minimum_balance() +} + +/// Total issuance of the chain. +pub fn total_issuance() -> BalanceOf { + T::Currency::total_issuance() +} + +/// Total balance of `who`. Includes both, free and reserved. +pub fn total_balance(who: &T::AccountId) -> BalanceOf { + T::Currency::total_balance(who) +} + +/// Stakeable balance of `who`. +/// +/// This includes balance free to stake along with any balance that is already staked. +pub fn stakeable_balance(who: &T::AccountId) -> BalanceOf { + T::Currency::free_balance(who) +} + +/// Balance of `who` that is currently at stake. +/// +/// The staked amount is locked and cannot be transferred out of `who`s account. +pub fn staked(who: &T::AccountId) -> BalanceOf { + T::Currency::balance_locked(crate::STAKING_ID, who) +} + +/// Set balance that can be staked for `who`. +/// +/// This includes any balance that is already staked. +#[cfg(any(test, feature = "runtime-benchmarks"))] +pub fn set_stakeable_balance(who: &T::AccountId, value: BalanceOf) { + T::Currency::make_free_balance_be(who, value); +} + +/// Update `amount` at stake for `who`. +/// +/// Overwrites the existing stake amount. If passed amount is lower than the existing stake, the +/// difference is unlocked. +pub fn update_stake(who: &T::AccountId, amount: BalanceOf) { + T::Currency::set_lock( + crate::STAKING_ID, + who, + amount, + frame_support::traits::WithdrawReasons::all(), + ); +} + +/// Kill the stake of `who`. +/// +/// All locked amount is unlocked. +pub fn kill_stake(who: &T::AccountId) { + T::Currency::remove_lock(crate::STAKING_ID, who); +} + +/// Slash the value from `who`. +/// +/// A negative imbalance is returned which can be resolved to deposit the slashed value. +pub fn slash( + who: &T::AccountId, + value: BalanceOf, +) -> (NegativeImbalanceOf, BalanceOf) { + T::Currency::slash(who, value) +} + +/// Mint `value` into an existing account `who`. +/// +/// This does not increase the total issuance. +pub fn mint_existing( + who: &T::AccountId, + value: BalanceOf, +) -> Option> { + T::Currency::deposit_into_existing(who, value).ok() +} + +/// Mint reward and create account for `who` if it does not exist. +/// +/// This does not increase the total issuance. +pub fn mint_creating(who: &T::AccountId, value: BalanceOf) -> PositiveImbalanceOf { + T::Currency::deposit_creating(who, value) +} + +/// Deposit newly issued or slashed `value` into `who`. +pub fn deposit_slashed(who: &T::AccountId, value: NegativeImbalanceOf) { + T::Currency::resolve_creating(who, value) +} + +/// Issue `value` increasing total issuance. +/// +/// Creates a negative imbalance. +pub fn issue(value: BalanceOf) -> NegativeImbalanceOf { + T::Currency::issue(value) +} + +/// Burn the amount from the total issuance. +#[cfg(feature = "runtime-benchmarks")] +pub fn burn(amount: BalanceOf) -> PositiveImbalanceOf { + T::Currency::burn(amount) +} diff --git a/substrate/frame/staking/src/benchmarking.rs b/substrate/frame/staking/src/benchmarking.rs index 1f8580d7a3e6..a25085a18036 100644 --- a/substrate/frame/staking/src/benchmarking.rs +++ b/substrate/frame/staking/src/benchmarking.rs @@ -18,7 +18,7 @@ //! Staking pallet benchmarking. use super::*; -use crate::{ConfigOp, Pallet as Staking}; +use crate::{asset, ConfigOp, Pallet as Staking}; use testing_utils::*; use codec::Decode; @@ -26,7 +26,7 @@ use frame_election_provider_support::{bounds::DataProviderBounds, SortedListProv use frame_support::{ pallet_prelude::*, storage::bounded_vec::BoundedVec, - traits::{Currency, Get, Imbalance, UnfilteredDispatchable}, + traits::{Get, Imbalance, UnfilteredDispatchable}, }; use sp_runtime::{ traits::{Bounded, One, StaticLookup, TrailingZeroInput, Zero}, @@ -132,7 +132,7 @@ pub fn create_validator_with_nominators( ErasRewardPoints::::insert(current_era, reward); // Create reward pool - let total_payout = T::Currency::minimum_balance() + let total_payout = asset::existential_deposit::() .saturating_mul(upper_bound.into()) .saturating_mul(1000u32.into()); >::insert(current_era, total_payout); @@ -167,7 +167,7 @@ impl ListScenario { ensure!(!origin_weight.is_zero(), "origin weight must be greater than 0"); // burn the entire issuance. - let i = T::Currency::burn(T::Currency::total_issuance()); + let i = asset::burn::(asset::total_issuance::()); core::mem::forget(i); // create accounts with the origin weight @@ -197,7 +197,7 @@ impl ListScenario { let dest_weight_as_vote = T::VoterList::score_update_worst_case(&origin_stash1, is_increase); - let total_issuance = T::Currency::total_issuance(); + let total_issuance = asset::total_issuance::(); let dest_weight = T::CurrencyToVote::to_currency(dest_weight_as_vote as u128, total_issuance); @@ -223,7 +223,7 @@ benchmarks! { bond { let stash = create_funded_user::("stash", USER_SEED, 100); let reward_destination = RewardDestination::Staked; - let amount = T::Currency::minimum_balance() * 10u32.into(); + let amount = asset::existential_deposit::() * 10u32.into(); whitelist_account!(stash); }: _(RawOrigin::Signed(stash.clone()), amount, reward_destination) verify { @@ -235,7 +235,7 @@ benchmarks! { // clean up any existing state. clear_validators_and_nominators::(); - let origin_weight = MinNominatorBond::::get().max(T::Currency::minimum_balance()); + let origin_weight = MinNominatorBond::::get().max(asset::existential_deposit::()); // setup the worst case list scenario. @@ -249,7 +249,7 @@ benchmarks! { let original_bonded: BalanceOf = Ledger::::get(&controller).map(|l| l.active).ok_or("ledger not created after")?; - let _ = T::Currency::deposit_into_existing(&stash, max_additional).unwrap(); + let _ = asset::mint_existing::(&stash, max_additional).unwrap(); whitelist_account!(stash); }: _(RawOrigin::Signed(stash), max_additional) @@ -264,7 +264,7 @@ benchmarks! { clear_validators_and_nominators::(); // setup the worst case list scenario. - let total_issuance = T::Currency::total_issuance(); + let total_issuance = asset::total_issuance::(); // the weight the nominator will start at. The value used here is expected to be // significantly higher than the first position in a list (e.g. the first bag threshold). let origin_weight = BalanceOf::::try_from(952_994_955_240_703u128) @@ -292,7 +292,7 @@ benchmarks! { let s in 0 .. MAX_SPANS; let (stash, controller) = create_stash_controller::(0, 100, RewardDestination::Staked)?; add_slashing_spans::(&stash, s); - let amount = T::Currency::minimum_balance() * 5u32.into(); // Half of total + let amount = asset::existential_deposit::() * 5u32.into(); // Half of total Staking::::unbond(RawOrigin::Signed(controller.clone()).into(), amount)?; CurrentEra::::put(EraIndex::max_value()); let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; @@ -312,7 +312,7 @@ benchmarks! { // clean up any existing state. clear_validators_and_nominators::(); - let origin_weight = MinNominatorBond::::get().max(T::Currency::minimum_balance()); + let origin_weight = MinNominatorBond::::get().max(asset::existential_deposit::()); // setup a worst case list scenario. Note that we don't care about the setup of the // destination position because we are doing a removal from the list but no insert. @@ -322,7 +322,7 @@ benchmarks! { add_slashing_spans::(&stash, s); assert!(T::VoterList::contains(&stash)); - let ed = T::Currency::minimum_balance(); + let ed = asset::existential_deposit::(); let mut ledger = Ledger::::get(&controller).unwrap(); ledger.active = ed - One::one(); Ledger::::insert(&controller, ledger); @@ -422,7 +422,7 @@ benchmarks! { // clean up any existing state. clear_validators_and_nominators::(); - let origin_weight = MinNominatorBond::::get().max(T::Currency::minimum_balance()); + let origin_weight = MinNominatorBond::::get().max(asset::existential_deposit::()); // setup a worst case list scenario. Note we don't care about the destination position, because // we are just doing an insert into the origin position. @@ -448,7 +448,7 @@ benchmarks! { // clean up any existing state. clear_validators_and_nominators::(); - let origin_weight = MinNominatorBond::::get().max(T::Currency::minimum_balance()); + let origin_weight = MinNominatorBond::::get().max(asset::existential_deposit::()); // setup a worst case list scenario. Note that we don't care about the setup of the // destination position because we are doing a removal from the list but no insert. @@ -564,7 +564,7 @@ benchmarks! { // Clean up any existing state. clear_validators_and_nominators::(); - let origin_weight = MinNominatorBond::::get().max(T::Currency::minimum_balance()); + let origin_weight = MinNominatorBond::::get().max(asset::existential_deposit::()); // setup a worst case list scenario. Note that we don't care about the setup of the // destination position because we are doing a removal from the list but no insert. @@ -611,21 +611,21 @@ benchmarks! { >::insert(current_era, validator.clone(), >::validators(&validator)); let caller = whitelisted_caller(); - let balance_before = T::Currency::free_balance(&validator); + let balance_before = asset::stakeable_balance::(&validator); let mut nominator_balances_before = Vec::new(); for (stash, _) in &nominators { - let balance = T::Currency::free_balance(stash); + let balance = asset::stakeable_balance::(stash); nominator_balances_before.push(balance); } }: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era) verify { - let balance_after = T::Currency::free_balance(&validator); + let balance_after = asset::stakeable_balance::(&validator); ensure!( balance_before < balance_after, "Balance of validator stash should have increased after payout.", ); for ((stash, _), balance_before) in nominators.iter().zip(nominator_balances_before.iter()) { - let balance_after = T::Currency::free_balance(stash); + let balance_after = asset::stakeable_balance::(stash); ensure!( balance_before < &balance_after, "Balance of nominator stash should have increased after payout.", @@ -640,7 +640,7 @@ benchmarks! { clear_validators_and_nominators::(); let origin_weight = MinNominatorBond::::get() - .max(T::Currency::minimum_balance()) + .max(asset::existential_deposit::()) // we use 100 to play friendly with the list threshold values in the mock .max(100u32.into()); @@ -686,7 +686,7 @@ benchmarks! { // clean up any existing state. clear_validators_and_nominators::(); - let origin_weight = MinNominatorBond::::get().max(T::Currency::minimum_balance()); + let origin_weight = MinNominatorBond::::get().max(asset::existential_deposit::()); // setup a worst case list scenario. Note that we don't care about the setup of the // destination position because we are doing a removal from the list but no insert. @@ -697,7 +697,7 @@ benchmarks! { add_slashing_spans::(&stash, s); let l = StakingLedger::::new( stash.clone(), - T::Currency::minimum_balance() - One::one(), + asset::existential_deposit::() - One::one(), ); Ledger::::insert(&controller, l); @@ -764,7 +764,7 @@ benchmarks! { ErasRewardPoints::::insert(current_era, reward); // Create reward pool - let total_payout = T::Currency::minimum_balance() * 1000u32.into(); + let total_payout = asset::existential_deposit::() * 1000u32.into(); >::insert(current_era, total_payout); let caller: T::AccountId = whitelisted_caller(); @@ -793,8 +793,8 @@ benchmarks! { staking_ledger.unlocking.try_push(unlock_chunk.clone()).unwrap(); } Ledger::::insert(controller, staking_ledger); - let slash_amount = T::Currency::minimum_balance() * 10u32.into(); - let balance_before = T::Currency::free_balance(&stash); + let slash_amount = asset::existential_deposit::() * 10u32.into(); + let balance_before = asset::stakeable_balance::(&stash); }: { crate::slashing::do_slash::( &stash, @@ -804,7 +804,7 @@ benchmarks! { EraIndex::zero() ); } verify { - let balance_after = T::Currency::free_balance(&stash); + let balance_after = asset::stakeable_balance::(&stash); assert!(balance_before > balance_after); } @@ -890,7 +890,7 @@ benchmarks! { // clean up any existing state. clear_validators_and_nominators::(); - let origin_weight = MinNominatorBond::::get().max(T::Currency::minimum_balance()); + let origin_weight = MinNominatorBond::::get().max(asset::existential_deposit::()); // setup a worst case list scenario. Note that we don't care about the setup of the // destination position because we are doing a removal from the list but no insert. @@ -972,7 +972,7 @@ benchmarks! { #[cfg(test)] mod tests { use super::*; - use crate::mock::{Balances, ExtBuilder, RuntimeOrigin, Staking, Test}; + use crate::mock::{ExtBuilder, RuntimeOrigin, Staking, Test}; use frame_support::assert_ok; #[test] @@ -1019,16 +1019,17 @@ mod tests { let current_era = CurrentEra::::get().unwrap(); - let original_free_balance = Balances::free_balance(&validator_stash); + let original_stakeable_balance = asset::stakeable_balance::(&validator_stash); assert_ok!(Staking::payout_stakers_by_page( RuntimeOrigin::signed(1337), validator_stash, current_era, 0 )); - let new_free_balance = Balances::free_balance(&validator_stash); + let new_stakeable_balance = asset::stakeable_balance::(&validator_stash); - assert!(original_free_balance < new_free_balance); + // reward increases stakeable balance + assert!(original_stakeable_balance < new_stakeable_balance); }); } diff --git a/substrate/frame/staking/src/ledger.rs b/substrate/frame/staking/src/ledger.rs index dc4b4fc326b8..ac3be04cf607 100644 --- a/substrate/frame/staking/src/ledger.rs +++ b/substrate/frame/staking/src/ledger.rs @@ -31,15 +31,12 @@ //! performed through the methods exposed by the [`StakingLedger`] implementation in order to ensure //! state consistency. -use frame_support::{ - defensive, ensure, - traits::{Defensive, LockableCurrency}, -}; +use frame_support::{defensive, ensure, traits::Defensive}; use sp_staking::{StakingAccount, StakingInterface}; use crate::{ - BalanceOf, Bonded, Config, Error, Ledger, Pallet, Payee, RewardDestination, StakingLedger, - VirtualStakers, STAKING_ID, + asset, BalanceOf, Bonded, Config, Error, Ledger, Pallet, Payee, RewardDestination, + StakingLedger, VirtualStakers, }; #[cfg(any(feature = "runtime-benchmarks", test))] @@ -190,12 +187,7 @@ impl StakingLedger { // We skip locking virtual stakers. if !Pallet::::is_virtual_staker(&self.stash) { // for direct stakers, update lock on stash based on ledger. - T::Currency::set_lock( - STAKING_ID, - &self.stash, - self.total, - frame_support::traits::WithdrawReasons::all(), - ); + asset::update_stake::(&self.stash, self.total); } Ledger::::insert( @@ -269,7 +261,7 @@ impl StakingLedger { // kill virtual staker if it exists. if >::take(&stash).is_none() { // if not virtual staker, clear locks. - T::Currency::remove_lock(STAKING_ID, &ledger.stash); + asset::kill_stake::(&ledger.stash); } Ok(()) diff --git a/substrate/frame/staking/src/lib.rs b/substrate/frame/staking/src/lib.rs index 9e59cbd3d0cb..19d999109d8d 100644 --- a/substrate/frame/staking/src/lib.rs +++ b/substrate/frame/staking/src/lib.rs @@ -295,6 +295,7 @@ pub(crate) mod mock; #[cfg(test)] mod tests; +pub mod asset; pub mod election_size_tracker; pub mod inflation; pub mod ledger; diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 2df3bc084eb0..6c4fe8140e8e 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -27,8 +27,8 @@ use frame_support::{ dispatch::WithPostDispatchInfo, pallet_prelude::*, traits::{ - Currency, Defensive, DefensiveSaturating, EstimateNextNewSession, Get, Imbalance, - InspectLockableCurrency, Len, LockableCurrency, OnUnbalanced, TryCollect, UnixTime, + Defensive, DefensiveSaturating, EstimateNextNewSession, Get, Imbalance, Len, OnUnbalanced, + TryCollect, UnixTime, }, weights::Weight, }; @@ -50,7 +50,7 @@ use sp_staking::{ }; use crate::{ - election_size_tracker::StaticTracker, log, slashing, weights::WeightInfo, ActiveEraInfo, + asset, election_size_tracker::StaticTracker, log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraInfo, EraPayout, Exposure, ExposureOf, Forcing, IndividualExposure, LedgerIntegrityState, MaxNominationsOf, MaxWinnersOf, Nominations, NominationsQuota, PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, ValidatorPrefs, @@ -96,7 +96,7 @@ impl Pallet { pub(crate) fn inspect_bond_state( stash: &T::AccountId, ) -> Result> { - let lock = T::Currency::balance_locked(crate::STAKING_ID, &stash); + let lock = asset::staked::(&stash); let controller = >::get(stash).ok_or_else(|| { if lock == Zero::zero() { @@ -142,7 +142,7 @@ impl Pallet { pub fn weight_of_fn() -> Box VoteWeight> { // NOTE: changing this to unboxed `impl Fn(..)` return type and the pallet will still // compile, while some types in mock fail to resolve. - let issuance = T::Currency::total_issuance(); + let issuance = asset::total_issuance::(); Box::new(move |who: &T::AccountId| -> VoteWeight { Self::slashable_balance_of_vote_weight(who, issuance) }) @@ -150,7 +150,7 @@ impl Pallet { /// Same as `weight_of_fn`, but made for one time use. pub fn weight_of(who: &T::AccountId) -> VoteWeight { - let issuance = T::Currency::total_issuance(); + let issuance = asset::total_issuance::(); Self::slashable_balance_of_vote_weight(who, issuance) } @@ -164,7 +164,7 @@ impl Pallet { } else { // additional amount or actual balance of stash whichever is lower. additional.min( - T::Currency::free_balance(stash) + asset::stakeable_balance::(stash) .checked_sub(&ledger.total) .ok_or(ArithmeticError::Overflow)?, ) @@ -173,7 +173,7 @@ impl Pallet { ledger.total = ledger.total.checked_add(&extra).ok_or(ArithmeticError::Overflow)?; ledger.active = ledger.active.checked_add(&extra).ok_or(ArithmeticError::Overflow)?; // last check: the new active amount of ledger must be more than ED. - ensure!(ledger.active >= T::Currency::minimum_balance(), Error::::InsufficientBond); + ensure!(ledger.active >= asset::existential_deposit::(), Error::::InsufficientBond); // NOTE: ledger must be updated prior to calling `Self::weight_of`. ledger.update()?; @@ -198,7 +198,7 @@ impl Pallet { } let new_total = ledger.total; - let ed = T::Currency::minimum_balance(); + let ed = asset::existential_deposit::(); let used_weight = 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 @@ -414,12 +414,12 @@ impl Pallet { let dest = Self::payee(StakingAccount::Stash(stash.clone()))?; let maybe_imbalance = match dest { - RewardDestination::Stash => T::Currency::deposit_into_existing(stash, amount).ok(), + RewardDestination::Stash => asset::mint_existing::(stash, amount), RewardDestination::Staked => Self::ledger(Stash(stash.clone())) .and_then(|mut ledger| { ledger.active += amount; ledger.total += amount; - let r = T::Currency::deposit_into_existing(stash, amount).ok(); + let r = asset::mint_existing::(stash, amount); let _ = ledger .update() @@ -429,7 +429,7 @@ impl Pallet { }) .unwrap_or_default(), RewardDestination::Account(ref dest_account) => - Some(T::Currency::deposit_creating(&dest_account, amount)), + Some(asset::mint_creating::(&dest_account, amount)), RewardDestination::None => None, #[allow(deprecated)] RewardDestination::Controller => Self::bonded(stash) @@ -437,7 +437,7 @@ impl Pallet { defensive!("Paying out controller as reward destination which is deprecated and should be migrated."); // This should never happen once payees with a `Controller` variant have been migrated. // But if it does, just pay the controller account. - T::Currency::deposit_creating(&controller, amount) + asset::mint_creating::(&controller, amount) }), }; maybe_imbalance.map(|imbalance| (imbalance, dest)) @@ -576,7 +576,7 @@ impl Pallet { let era_duration = (now_as_millis_u64.defensive_saturating_sub(active_era_start)) .saturated_into::(); let staked = Self::eras_total_stake(&active_era.index); - let issuance = T::Currency::total_issuance(); + let issuance = asset::total_issuance::(); let (validator_payout, remainder) = T::EraPayout::era_payout(staked, issuance, era_duration); @@ -597,7 +597,7 @@ impl Pallet { // Set ending era reward. >::insert(&active_era.index, validator_payout); - T::RewardRemainder::on_unbalanced(T::Currency::issue(remainder)); + T::RewardRemainder::on_unbalanced(asset::issue::(remainder)); // Clear disabled validators. >::kill(); @@ -748,7 +748,7 @@ impl Pallet { fn collect_exposures( supports: BoundedSupportsOf, ) -> BoundedVec<(T::AccountId, Exposure>), MaxWinnersOf> { - let total_issuance = T::Currency::total_issuance(); + let total_issuance = asset::total_issuance::(); let to_currency = |e: frame_election_provider_support::ExtendedBalance| { T::CurrencyToVote::to_currency(e, total_issuance) }; @@ -1581,7 +1581,7 @@ impl ScoreProvider for Pallet { // also, we play a trick to make sure that a issuance based-`CurrencyToVote` behaves well: // This will make sure that total issuance is zero, thus the currency to vote will be a 1-1 // conversion. - let imbalance = T::Currency::burn(T::Currency::total_issuance()); + let imbalance = asset::burn::(asset::total_issuance::()); // kinda ugly, but gets the job done. The fact that this works here is a HUGE exception. // Don't try this pattern in other places. core::mem::forget(imbalance); @@ -1919,7 +1919,7 @@ impl StakingInterface for Pallet { impl sp_staking::StakingUnchecked for Pallet { fn migrate_to_virtual_staker(who: &Self::AccountId) { - T::Currency::remove_lock(crate::STAKING_ID, who); + asset::kill_stake::(who); VirtualStakers::::insert(who, ()); } @@ -1956,12 +1956,7 @@ impl sp_staking::StakingUnchecked for Pallet { fn migrate_to_direct_staker(who: &Self::AccountId) { assert!(VirtualStakers::::contains_key(who)); let ledger = StakingLedger::::get(Stash(who.clone())).unwrap(); - T::Currency::set_lock( - crate::STAKING_ID, - who, - ledger.total, - frame_support::traits::WithdrawReasons::all(), - ); + asset::update_stake::(who, ledger.total); VirtualStakers::::remove(who); } } @@ -2097,7 +2092,7 @@ impl Pallet { // ensure locks consistency. if VirtualStakers::::contains_key(stash.clone()) { ensure!( - T::Currency::balance_locked(crate::STAKING_ID, &stash) == Zero::zero(), + asset::staked::(&stash) == Zero::zero(), "virtual stakers should not have any locked balance" ); ensure!( diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 8a4482f52ad5..28aa4f89b622 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -25,8 +25,8 @@ use frame_election_provider_support::{ use frame_support::{ pallet_prelude::*, traits::{ - Currency, Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get, - InspectLockableCurrency, LockableCurrency, OnUnbalanced, UnixTime, WithdrawReasons, + Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get, + InspectLockableCurrency, LockableCurrency, OnUnbalanced, UnixTime, }, weights::Weight, BoundedVec, @@ -48,11 +48,11 @@ mod impls; pub use impls::*; use crate::{ - slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf, DisablingStrategy, - EraPayout, EraRewardPoints, Exposure, ExposurePage, Forcing, LedgerIntegrityState, - MaxNominationsOf, NegativeImbalanceOf, Nominations, NominationsQuota, PositiveImbalanceOf, - RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, - ValidatorPrefs, + asset, slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf, + DisablingStrategy, EraPayout, EraRewardPoints, Exposure, ExposurePage, Forcing, + LedgerIntegrityState, MaxNominationsOf, NegativeImbalanceOf, Nominations, NominationsQuota, + PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, + UnlockChunk, ValidatorPrefs, }; // The speculative number of spans are used as an input of the weight annotation of @@ -779,7 +779,7 @@ pub mod pallet { status ); assert!( - T::Currency::free_balance(stash) >= balance, + asset::stakeable_balance::(stash) >= balance, "Stash does not have enough balance to bond." ); frame_support::assert_ok!(>::bond( @@ -1023,14 +1023,14 @@ pub mod pallet { } // Reject a bond which is considered to be _dust_. - if value < T::Currency::minimum_balance() { + if value < asset::existential_deposit::() { return Err(Error::::InsufficientBond.into()) } // Would fail if account has no provider. frame_system::Pallet::::inc_consumers(&stash)?; - let stash_balance = T::Currency::free_balance(&stash); + let stash_balance = asset::stakeable_balance::(&stash); let value = value.min(stash_balance); Self::deposit_event(Event::::Bonded { stash: stash.clone(), amount: value }); let ledger = StakingLedger::::new(stash.clone(), value); @@ -1068,7 +1068,7 @@ pub mod pallet { /// Schedule a portion of the stash to be unlocked ready for transfer out after the bond /// period ends. If this leaves an amount actively bonded less than - /// T::Currency::minimum_balance(), then it is increased to the full amount. + /// [`asset::existential_deposit`], then it is increased to the full amount. /// /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. /// @@ -1124,7 +1124,7 @@ pub mod pallet { ledger.active -= value; // Avoid there being a dust balance left in the staking system. - if ledger.active < T::Currency::minimum_balance() { + if ledger.active < asset::existential_deposit::() { value += ledger.active; ledger.active = Zero::zero(); } @@ -1654,7 +1654,10 @@ pub mod pallet { let initial_unlocking = ledger.unlocking.len() as u32; let (ledger, rebonded_value) = ledger.rebond(value); // Last check: the new active amount of ledger must be more than ED. - ensure!(ledger.active >= T::Currency::minimum_balance(), Error::::InsufficientBond); + ensure!( + ledger.active >= asset::existential_deposit::(), + Error::::InsufficientBond + ); Self::deposit_event(Event::::Bonded { stash: ledger.stash.clone(), @@ -1706,8 +1709,8 @@ pub mod pallet { // virtual stakers should not be allowed to be reaped. ensure!(!Self::is_virtual_staker(&stash), Error::::VirtualStakerNotAllowed); - let ed = T::Currency::minimum_balance(); - let origin_balance = T::Currency::total_balance(&stash); + let ed = asset::existential_deposit::(); + let origin_balance = asset::total_balance::(&stash); let ledger_total = Self::ledger(Stash(stash.clone())).map(|l| l.total).unwrap_or_default(); let reapable = origin_balance < ed || @@ -2074,8 +2077,8 @@ pub mod pallet { // cannot restore ledger for virtual stakers. ensure!(!Self::is_virtual_staker(&stash), Error::::VirtualStakerNotAllowed); - let current_lock = T::Currency::balance_locked(crate::STAKING_ID, &stash); - let stash_balance = T::Currency::free_balance(&stash); + let current_lock = asset::staked::(&stash); + let stash_balance = asset::stakeable_balance::(&stash); let (new_controller, new_total) = match Self::inspect_bond_state(&stash) { Ok(LedgerIntegrityState::Corrupted) => { @@ -2084,12 +2087,7 @@ pub mod pallet { let new_total = if let Some(total) = maybe_total { let new_total = total.min(stash_balance); // enforce lock == ledger.amount. - T::Currency::set_lock( - crate::STAKING_ID, - &stash, - new_total, - WithdrawReasons::all(), - ); + asset::update_stake::(&stash, new_total); new_total } else { current_lock @@ -2116,18 +2114,13 @@ pub mod pallet { // to enforce a new ledger.total and staking lock for this stash. let new_total = maybe_total.ok_or(Error::::CannotRestoreLedger)?.min(stash_balance); - T::Currency::set_lock( - crate::STAKING_ID, - &stash, - new_total, - WithdrawReasons::all(), - ); + asset::update_stake::(&stash, new_total); Ok((stash.clone(), new_total)) }, Err(Error::::BadState) => { // the stash and ledger do not exist but lock is lingering. - T::Currency::remove_lock(crate::STAKING_ID, &stash); + asset::kill_stake::(&stash); ensure!( Self::inspect_bond_state(&stash) == Err(Error::::NotStash), Error::::BadState diff --git a/substrate/frame/staking/src/slashing.rs b/substrate/frame/staking/src/slashing.rs index 9bc8197c50b3..9fb782265b8b 100644 --- a/substrate/frame/staking/src/slashing.rs +++ b/substrate/frame/staking/src/slashing.rs @@ -50,15 +50,15 @@ //! Based on research at use crate::{ - BalanceOf, Config, DisabledValidators, DisablingStrategy, Error, Exposure, NegativeImbalanceOf, - NominatorSlashInEra, Pallet, Perbill, SessionInterface, SpanSlash, UnappliedSlash, - ValidatorSlashInEra, + asset, BalanceOf, Config, DisabledValidators, DisablingStrategy, Error, Exposure, + NegativeImbalanceOf, NominatorSlashInEra, Pallet, Perbill, SessionInterface, SpanSlash, + UnappliedSlash, ValidatorSlashInEra, }; use alloc::vec::Vec; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ ensure, - traits::{Currency, Defensive, DefensiveSaturating, Imbalance, OnUnbalanced}, + traits::{Defensive, DefensiveSaturating, Imbalance, OnUnbalanced}, }; use scale_info::TypeInfo; use sp_runtime::{ @@ -578,7 +578,7 @@ pub fn do_slash( Err(_) => return, // nothing to do. }; - let value = ledger.slash(value, T::Currency::minimum_balance(), slash_era); + let value = ledger.slash(value, asset::existential_deposit::(), slash_era); if value.is_zero() { // nothing to do return @@ -586,7 +586,7 @@ pub fn do_slash( // Skip slashing for virtual stakers. The pallets managing them should handle the slashing. if !Pallet::::is_virtual_staker(stash) { - let (imbalance, missing) = T::Currency::slash(stash, value); + let (imbalance, missing) = asset::slash::(stash, value); slashed_imbalance.subsume(imbalance); if !missing.is_zero() { @@ -656,7 +656,7 @@ fn pay_reporters( // this cancels out the reporter reward imbalance internally, leading // to no change in total issuance. - T::Currency::resolve_creating(reporter, reporter_reward); + asset::deposit_slashed::(reporter, reporter_reward); } // the rest goes to the on-slash imbalance handler (e.g. treasury) diff --git a/substrate/frame/staking/src/testing_utils.rs b/substrate/frame/staking/src/testing_utils.rs index 65aaa5f09de4..efd4a40f1ab4 100644 --- a/substrate/frame/staking/src/testing_utils.rs +++ b/substrate/frame/staking/src/testing_utils.rs @@ -28,7 +28,7 @@ use rand_chacha::{ use sp_io::hashing::blake2_256; use frame_election_provider_support::SortedListProvider; -use frame_support::{pallet_prelude::*, traits::Currency}; +use frame_support::pallet_prelude::*; use sp_runtime::{traits::StaticLookup, Perbill}; const SEED: u32 = 0; @@ -53,8 +53,8 @@ pub fn create_funded_user( balance_factor: u32, ) -> T::AccountId { let user = account(string, n, SEED); - let balance = T::Currency::minimum_balance() * balance_factor.into(); - let _ = T::Currency::make_free_balance_be(&user, balance); + let balance = asset::existential_deposit::() * balance_factor.into(); + let _ = asset::set_stakeable_balance::(&user, balance); user } @@ -65,7 +65,7 @@ pub fn create_funded_user_with_balance( balance: BalanceOf, ) -> T::AccountId { let user = account(string, n, SEED); - let _ = T::Currency::make_free_balance_be(&user, balance); + let _ = asset::set_stakeable_balance::(&user, balance); user } @@ -77,7 +77,7 @@ pub fn create_stash_controller( ) -> Result<(T::AccountId, T::AccountId), &'static str> { let staker = create_funded_user::("stash", n, balance_factor); let amount = - T::Currency::minimum_balance().max(1u64.into()) * (balance_factor / 10).max(1).into(); + asset::existential_deposit::().max(1u64.into()) * (balance_factor / 10).max(1).into(); Staking::::bond(RawOrigin::Signed(staker.clone()).into(), amount, destination)?; Ok((staker.clone(), staker)) } @@ -96,7 +96,7 @@ pub fn create_unique_stash_controller( } else { create_funded_user::("controller", n, balance_factor) }; - let amount = T::Currency::minimum_balance() * (balance_factor / 10).max(1).into(); + let amount = asset::existential_deposit::() * (balance_factor / 10).max(1).into(); Staking::::bond(RawOrigin::Signed(stash.clone()).into(), amount, destination)?; // update ledger to be a *different* controller to stash @@ -129,7 +129,7 @@ pub fn create_stash_and_dead_payee( let staker = create_funded_user::("stash", n, 0); // payee has no funds let payee = create_funded_user::("payee", n, 0); - let amount = T::Currency::minimum_balance() * (balance_factor / 10).max(1).into(); + let amount = asset::existential_deposit::() * (balance_factor / 10).max(1).into(); Staking::::bond( RawOrigin::Signed(staker.clone()).into(), amount, diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index dd178a95bec5..639f4096456f 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -18,7 +18,7 @@ //! Tests for the module. use super::{ConfigOp, Event, *}; -use crate::ledger::StakingLedgerInspect; +use crate::{asset, ledger::StakingLedgerInspect}; use frame_election_provider_support::{ bounds::{DataProviderBounds, ElectionBoundsBuilder}, ElectionProvider, SortedListProvider, Support, @@ -27,7 +27,7 @@ use frame_support::{ assert_noop, assert_ok, assert_storage_noop, dispatch::{extract_actual_weight, GetDispatchInfo, WithPostDispatchInfo}, pallet_prelude::*, - traits::{Currency, Get, InspectLockableCurrency, ReservableCurrency}, + traits::{Currency, Get, ReservableCurrency}, }; use mock::*; @@ -229,8 +229,8 @@ fn basic_setup_works() { assert_eq!(active_era(), 0); // Account 10 has `balance_factor` free balance - assert_eq!(Balances::free_balance(10), 1); - assert_eq!(Balances::free_balance(10), 1); + assert_eq!(asset::stakeable_balance::(&10), 1); + assert_eq!(asset::stakeable_balance::(&10), 1); // New era is not being forced assert_eq!(Staking::force_era(), Forcing::NotForcing); @@ -311,9 +311,9 @@ fn change_controller_already_paired_once_stash() { #[test] fn rewards_should_work() { ExtBuilder::default().nominate(true).session_per_era(3).build_and_execute(|| { - let init_balance_11 = Balances::total_balance(&11); - let init_balance_21 = Balances::total_balance(&21); - let init_balance_101 = Balances::total_balance(&101); + let init_balance_11 = asset::total_balance::(&11); + let init_balance_21 = asset::total_balance::(&21); + let init_balance_101 = asset::total_balance::(&101); // Set payees Payee::::insert(11, RewardDestination::Account(11)); @@ -332,9 +332,9 @@ fn rewards_should_work() { start_session(1); assert_eq_uvec!(Session::validators(), vec![11, 21]); - assert_eq!(Balances::total_balance(&11), init_balance_11); - assert_eq!(Balances::total_balance(&21), init_balance_21); - assert_eq!(Balances::total_balance(&101), init_balance_101); + assert_eq!(asset::total_balance::(&11), init_balance_11); + assert_eq!(asset::total_balance::(&21), init_balance_21); + assert_eq!(asset::total_balance::(&101), init_balance_101); assert_eq!( Staking::eras_reward_points(active_era()), EraRewardPoints { @@ -363,17 +363,17 @@ fn rewards_should_work() { mock::make_all_reward_payment(0); assert_eq_error_rate!( - Balances::total_balance(&11), + asset::total_balance::(&11), init_balance_11 + part_for_11 * total_payout_0 * 2 / 3, 2, ); assert_eq_error_rate!( - Balances::total_balance(&21), + asset::total_balance::(&21), init_balance_21 + part_for_21 * total_payout_0 * 1 / 3, 2, ); assert_eq_error_rate!( - Balances::total_balance(&101), + asset::total_balance::(&101), init_balance_101 + part_for_101_from_11 * total_payout_0 * 2 / 3 + part_for_101_from_21 * total_payout_0 * 1 / 3, @@ -402,17 +402,17 @@ fn rewards_should_work() { mock::make_all_reward_payment(1); assert_eq_error_rate!( - Balances::total_balance(&11), + asset::total_balance::(&11), init_balance_11 + part_for_11 * (total_payout_0 * 2 / 3 + total_payout_1), 2, ); assert_eq_error_rate!( - Balances::total_balance(&21), + asset::total_balance::(&21), init_balance_21 + part_for_21 * total_payout_0 * 1 / 3, 2, ); assert_eq_error_rate!( - Balances::total_balance(&101), + asset::total_balance::(&101), init_balance_101 + part_for_101_from_11 * (total_payout_0 * 2 / 3 + total_payout_1) + part_for_101_from_21 * total_payout_0 * 1 / 3, @@ -429,7 +429,7 @@ fn staking_should_work() { // put some money in account that we'll use. for i in 1..5 { - let _ = Balances::make_free_balance_be(&i, 2000); + let _ = asset::set_stakeable_balance::(&i, 2000); } // --- Block 2: @@ -611,7 +611,7 @@ fn nominating_and_rewards_should_work() { // give the man some money let initial_balance = 1000; for i in [1, 3, 5, 11, 21].iter() { - let _ = Balances::make_free_balance_be(i, initial_balance); + let _ = asset::set_stakeable_balance::(&i, initial_balance); } // bond two account pairs and state interest in nomination. @@ -636,12 +636,12 @@ fn nominating_and_rewards_should_work() { assert_eq_uvec!(validator_controllers(), vec![21, 11]); // old validators must have already received some rewards. - let initial_balance_41 = Balances::total_balance(&41); - let mut initial_balance_21 = Balances::total_balance(&21); + let initial_balance_41 = asset::total_balance::(&41); + let mut initial_balance_21 = asset::total_balance::(&21); mock::make_all_reward_payment(0); - assert_eq!(Balances::total_balance(&41), initial_balance_41 + total_payout_0 / 2); - assert_eq!(Balances::total_balance(&21), initial_balance_21 + total_payout_0 / 2); - initial_balance_21 = Balances::total_balance(&21); + assert_eq!(asset::total_balance::(&41), initial_balance_41 + total_payout_0 / 2); + assert_eq!(asset::total_balance::(&21), initial_balance_21 + total_payout_0 / 2); + initial_balance_21 = asset::total_balance::(&21); assert_eq!(ErasStakersPaged::::iter_prefix_values((active_era(),)).count(), 2); assert_eq!( @@ -683,30 +683,30 @@ fn nominating_and_rewards_should_work() { // Nominator 2: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 21]'s reward. ==> // 2/9 + 3/11 assert_eq_error_rate!( - Balances::total_balance(&1), + asset::total_balance::(&1), initial_balance + (2 * payout_for_11 / 9 + 3 * payout_for_21 / 11), 2, ); // Nominator 3: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 21]'s reward. ==> // 2/9 + 3/11 - assert_eq!(Balances::total_balance(&3), initial_balance); + assert_eq!(asset::total_balance::(&3), initial_balance); // 333 is the reward destination for 3. assert_eq_error_rate!( - Balances::total_balance(&333), + asset::total_balance::(&333), 2 * payout_for_11 / 9 + 3 * payout_for_21 / 11, 2 ); // Validator 11: got 800 / 1800 external stake => 8/18 =? 4/9 => Validator's share = 5/9 assert_eq_error_rate!( - Balances::total_balance(&11), + asset::total_balance::(&11), initial_balance + 5 * payout_for_11 / 9, 2, ); // Validator 21: got 1200 / 2200 external stake => 12/22 =? 6/11 => Validator's share = // 5/11 assert_eq_error_rate!( - Balances::total_balance(&21), + asset::total_balance::(&21), initial_balance_21 + 5 * payout_for_21 / 11, 2, ); @@ -993,7 +993,7 @@ fn cannot_transfer_staked_balance() { // Confirm account 11 is stashed assert_eq!(Staking::bonded(&11), Some(11)); // Confirm account 11 has some free balance - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); // Confirm account 11 (via controller) is totally staked assert_eq!(Staking::eras_stakers(active_era(), &11).total, 1000); // Confirm account 11 cannot transfer as a result @@ -1003,7 +1003,7 @@ fn cannot_transfer_staked_balance() { ); // Give account 11 extra free balance - let _ = Balances::make_free_balance_be(&11, 10000); + let _ = asset::set_stakeable_balance::(&11, 10000); // Confirm that account 11 can now transfer some balance assert_ok!(Balances::transfer_allow_death(RuntimeOrigin::signed(11), 21, 1)); }); @@ -1018,7 +1018,7 @@ fn cannot_transfer_staked_balance_2() { // Confirm account 21 is stashed assert_eq!(Staking::bonded(&21), Some(21)); // Confirm account 21 has some free balance - assert_eq!(Balances::free_balance(21), 2000); + assert_eq!(asset::stakeable_balance::(&21), 2000); // Confirm account 21 (via controller) is totally staked assert_eq!(Staking::eras_stakers(active_era(), &21).total, 1000); // Confirm account 21 can transfer at most 1000 @@ -1037,14 +1037,14 @@ fn cannot_reserve_staked_balance() { // Confirm account 11 is stashed assert_eq!(Staking::bonded(&11), Some(11)); // Confirm account 11 has some free balance - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); // Confirm account 11 (via controller 10) is totally staked assert_eq!(Staking::eras_stakers(active_era(), &11).own, 1000); // Confirm account 11 cannot reserve as a result assert_noop!(Balances::reserve(&11, 1), BalancesError::::LiquidityRestrictions); // Give account 11 extra free balance - let _ = Balances::make_free_balance_be(&11, 10000); + let _ = asset::set_stakeable_balance::(&11, 10000); // Confirm account 11 can now reserve balance assert_ok!(Balances::reserve(&11, 1)); }); @@ -1057,9 +1057,9 @@ fn reward_destination_works() { // Check that account 11 is a validator assert!(Session::validators().contains(&11)); // Check the balance of the validator account - assert_eq!(Balances::free_balance(10), 1); + assert_eq!(asset::stakeable_balance::(&10), 1); // Check the balance of the stash account - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); // Check how much is at stake assert_eq!( Staking::ledger(11.into()).unwrap(), @@ -1082,7 +1082,7 @@ fn reward_destination_works() { // Check that RewardDestination is Staked assert_eq!(Staking::payee(11.into()), Some(RewardDestination::Staked)); // Check that reward went to the stash account of validator - assert_eq!(Balances::free_balance(11), 1000 + total_payout_0); + assert_eq!(asset::stakeable_balance::(&11), 1000 + total_payout_0); // Check that amount at stake increased accordingly assert_eq!( Staking::ledger(11.into()).unwrap(), @@ -1111,7 +1111,7 @@ fn reward_destination_works() { // Check that RewardDestination is Stash assert_eq!(Staking::payee(11.into()), Some(RewardDestination::Stash)); // Check that reward went to the stash account - assert_eq!(Balances::free_balance(11), 1000 + total_payout_0 + total_payout_1); + assert_eq!(asset::stakeable_balance::(&11), 1000 + total_payout_0 + total_payout_1); // Record this value let recorded_stash_balance = 1000 + total_payout_0 + total_payout_1; // Check that amount at stake is NOT increased @@ -1133,7 +1133,7 @@ fn reward_destination_works() { >::insert(&11, RewardDestination::Account(11)); // Check controller balance - assert_eq!(Balances::free_balance(11), 23150); + assert_eq!(asset::stakeable_balance::(&11), 23150); // Compute total payout now for whole duration as other parameter won't change let total_payout_2 = current_total_payout_for_duration(reward_time_per_era()); @@ -1145,7 +1145,7 @@ fn reward_destination_works() { // Check that RewardDestination is Account(11) assert_eq!(Staking::payee(11.into()), Some(RewardDestination::Account(11))); // Check that reward went to the controller account - assert_eq!(Balances::free_balance(11), recorded_stash_balance + total_payout_2); + assert_eq!(asset::stakeable_balance::(&11), recorded_stash_balance + total_payout_2); // Check that amount at stake is NOT increased assert_eq!( Staking::ledger(11.into()).unwrap(), @@ -1179,8 +1179,8 @@ fn validator_payment_prefs_work() { mock::start_active_era(1); mock::make_all_reward_payment(0); - let balance_era_1_11 = Balances::total_balance(&11); - let balance_era_1_101 = Balances::total_balance(&101); + let balance_era_1_11 = asset::total_balance::(&11); + let balance_era_1_101 = asset::total_balance::(&101); // Compute total payout now for whole duration as other parameter won't change let total_payout_1 = current_total_payout_for_duration(reward_time_per_era()); @@ -1194,8 +1194,16 @@ fn validator_payment_prefs_work() { let shared_cut = total_payout_1 - taken_cut; let reward_of_10 = shared_cut * exposure_1.own / exposure_1.total + taken_cut; let reward_of_100 = shared_cut * exposure_1.others[0].value / exposure_1.total; - assert_eq_error_rate!(Balances::total_balance(&11), balance_era_1_11 + reward_of_10, 2); - assert_eq_error_rate!(Balances::total_balance(&101), balance_era_1_101 + reward_of_100, 2); + assert_eq_error_rate!( + asset::total_balance::(&11), + balance_era_1_11 + reward_of_10, + 2 + ); + assert_eq_error_rate!( + asset::total_balance::(&101), + balance_era_1_101 + reward_of_100, + 2 + ); }); } @@ -1222,7 +1230,7 @@ fn bond_extra_works() { ); // Give account 11 some large free balance greater than total - let _ = Balances::make_free_balance_be(&11, 1000000); + let _ = asset::set_stakeable_balance::(&11, 1000000); // Call the bond_extra function from controller, add only 100 assert_ok!(Staking::bond_extra(RuntimeOrigin::signed(11), 100)); @@ -1284,13 +1292,13 @@ fn bond_extra_and_withdraw_unbonded_works() { assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash)); // Give account 11 some large free balance greater than total - let _ = Balances::make_free_balance_be(&11, 1000000); + let _ = asset::set_stakeable_balance::(&11, 1000000); // Initial config should be correct assert_eq!(active_era(), 0); // check the balance of a validator accounts. - assert_eq!(Balances::total_balance(&11), 1000000); + assert_eq!(asset::total_balance::(&11), 1000000); // confirm that 10 is a normal validator and gets paid at the end of the era. mock::start_active_era(1); @@ -1495,7 +1503,7 @@ fn rebond_works() { assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash)); // Give account 11 some large free balance greater than total - let _ = Balances::make_free_balance_be(&11, 1000000); + let _ = asset::set_stakeable_balance::(&11, 1000000); // confirm that 10 is a normal validator and gets paid at the end of the era. mock::start_active_era(1); @@ -1621,7 +1629,7 @@ fn rebond_is_fifo() { assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash)); // Give account 11 some large free balance greater than total - let _ = Balances::make_free_balance_be(&11, 1000000); + let _ = asset::set_stakeable_balance::(&11, 1000000); // confirm that 10 is a normal validator and gets paid at the end of the era. mock::start_active_era(1); @@ -1717,7 +1725,7 @@ fn rebond_emits_right_value_in_event() { assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash)); // Give account 11 some large free balance greater than total - let _ = Balances::make_free_balance_be(&11, 1000000); + let _ = asset::set_stakeable_balance::(&11, 1000000); // confirm that 10 is a normal validator and gets paid at the end of the era. mock::start_active_era(1); @@ -1852,8 +1860,8 @@ fn reward_to_stake_works() { assert_eq!(Staking::eras_stakers(active_era(), &21).total, 2000); // Give the man some money. - let _ = Balances::make_free_balance_be(&10, 1000); - let _ = Balances::make_free_balance_be(&20, 1000); + let _ = asset::set_stakeable_balance::(&10, 1000); + let _ = asset::set_stakeable_balance::(&20, 1000); // Bypass logic and change current exposure EraInfo::::set_exposure(0, &21, Exposure { total: 69, own: 69, others: vec![] }); @@ -1880,7 +1888,7 @@ fn reward_to_stake_works() { assert_eq!(Staking::eras_stakers(active_era(), &11).total, 1000); assert_eq!(Staking::eras_stakers(active_era(), &21).total, 2000); - let _11_balance = Balances::free_balance(&11); + let _11_balance = asset::stakeable_balance::(&11); assert_eq!(_11_balance, 1000 + total_payout_0 / 2); // Trigger another new era as the info are frozen before the era start. @@ -1899,7 +1907,7 @@ fn reap_stash_works() { .balance_factor(10) .build_and_execute(|| { // given - assert_eq!(Balances::balance_locked(STAKING_ID, &11), 10 * 1000); + assert_eq!(asset::staked::(&11), 10 * 1000); assert_eq!(Staking::bonded(&11), Some(11)); assert!(>::contains_key(&11)); @@ -1926,7 +1934,7 @@ fn reap_stash_works() { assert!(!>::contains_key(&11)); assert!(!>::contains_key(&11)); // lock is removed. - assert_eq!(Balances::balance_locked(STAKING_ID, &11), 0); + assert_eq!(asset::staked::(&11), 0); }); } @@ -1937,7 +1945,7 @@ fn reap_stash_works_with_existential_deposit_zero() { .balance_factor(10) .build_and_execute(|| { // given - assert_eq!(Balances::balance_locked(STAKING_ID, &11), 10 * 1000); + assert_eq!(asset::staked::(&11), 10 * 1000); assert_eq!(Staking::bonded(&11), Some(11)); assert!(>::contains_key(&11)); @@ -1964,7 +1972,7 @@ fn reap_stash_works_with_existential_deposit_zero() { assert!(!>::contains_key(&11)); assert!(!>::contains_key(&11)); // lock is removed. - assert_eq!(Balances::balance_locked(STAKING_ID, &11), 0); + assert_eq!(asset::staked::(&11), 0); }); } @@ -2111,8 +2119,8 @@ fn bond_with_little_staked_value_bounded() { // setup assert_ok!(Staking::chill(RuntimeOrigin::signed(31))); assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash)); - let init_balance_1 = Balances::free_balance(&1); - let init_balance_11 = Balances::free_balance(&11); + let init_balance_1 = asset::stakeable_balance::(&1); + let init_balance_11 = asset::stakeable_balance::(&11); // Stingy validator. assert_ok!(Staking::bond(RuntimeOrigin::signed(1), 1, RewardDestination::Account(1))); @@ -2137,12 +2145,12 @@ fn bond_with_little_staked_value_bounded() { // Old ones are rewarded. assert_eq_error_rate!( - Balances::free_balance(11), + asset::stakeable_balance::(&11), init_balance_11 + total_payout_0 / 3, 1 ); // no rewards paid to 2. This was initial election. - assert_eq!(Balances::free_balance(1), init_balance_1); + assert_eq!(asset::stakeable_balance::(&1), init_balance_1); // reward era 2 let total_payout_1 = current_total_payout_for_duration(reward_time_per_era()); @@ -2155,12 +2163,12 @@ fn bond_with_little_staked_value_bounded() { // 2 is now rewarded. assert_eq_error_rate!( - Balances::free_balance(1), + asset::stakeable_balance::(&1), init_balance_1 + total_payout_1 / 3, 1 ); assert_eq_error_rate!( - Balances::free_balance(&11), + asset::stakeable_balance::(&11), init_balance_11 + total_payout_0 / 3 + total_payout_1 / 3, 2, ); @@ -2188,7 +2196,7 @@ fn bond_with_duplicate_vote_should_be_ignored_by_election_provider() { // give the man some money. let initial_balance = 1000; for i in [1, 2, 3, 4].iter() { - let _ = Balances::make_free_balance_be(i, initial_balance); + let _ = asset::set_stakeable_balance::(&i, initial_balance); } assert_ok!(Staking::bond( @@ -2241,7 +2249,7 @@ fn bond_with_duplicate_vote_should_be_ignored_by_election_provider_elected() { // give the man some money. let initial_balance = 1000; for i in [1, 2, 3, 4].iter() { - let _ = Balances::make_free_balance_be(i, initial_balance); + let _ = asset::set_stakeable_balance::(&i, initial_balance); } assert_ok!(Staking::bond( @@ -2317,7 +2325,7 @@ fn reward_validator_slashing_validator_does_not_overflow() { assert!(stake.checked_mul(reward_slash).is_none()); // Set staker - let _ = Balances::make_free_balance_be(&11, stake); + let _ = asset::set_stakeable_balance::(&11, stake); let exposure = Exposure:: { total: stake, own: stake, others: vec![] }; let reward = EraRewardPoints:: { @@ -2330,11 +2338,11 @@ fn reward_validator_slashing_validator_does_not_overflow() { EraInfo::::set_exposure(0, &11, exposure); ErasValidatorReward::::insert(0, stake); assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 0, 0)); - assert_eq!(Balances::total_balance(&11), stake * 2); + assert_eq!(asset::total_balance::(&11), stake * 2); // Set staker - let _ = Balances::make_free_balance_be(&11, stake); - let _ = Balances::make_free_balance_be(&2, stake); + let _ = asset::set_stakeable_balance::(&11, stake); + let _ = asset::set_stakeable_balance::(&2, stake); // only slashes out of bonded stake are applied. without this line, it is 0. Staking::bond(RuntimeOrigin::signed(2), stake - 1, RewardDestination::Staked).unwrap(); @@ -2358,8 +2366,8 @@ fn reward_validator_slashing_validator_does_not_overflow() { &[Perbill::from_percent(100)], ); - assert_eq!(Balances::total_balance(&11), stake - 1); - assert_eq!(Balances::total_balance(&2), 1); + assert_eq!(asset::total_balance::(&11), stake - 1); + assert_eq!(asset::total_balance::(&2), 1); }) } @@ -2526,7 +2534,7 @@ fn slashing_performed_according_exposure() { ); // The stash account should be slashed for 250 (50% of 500). - assert_eq!(Balances::free_balance(11), 1000 - 250); + assert_eq!(asset::stakeable_balance::(&11), 1000 - 250); }); } @@ -2619,8 +2627,8 @@ fn reporters_receive_their_slice() { // 50% * (10% * initial_balance / 2) let reward = (initial_balance / 20) / 2; let reward_each = reward / 2; // split into two pieces. - assert_eq!(Balances::free_balance(1), 10 + reward_each); - assert_eq!(Balances::free_balance(2), 20 + reward_each); + assert_eq!(asset::stakeable_balance::(&1), 10 + reward_each); + assert_eq!(asset::stakeable_balance::(&2), 20 + reward_each); }); } @@ -2645,7 +2653,7 @@ fn subsequent_reports_in_same_span_pay_out_less() { // F1 * (reward_proportion * slash - 0) // 50% * (10% * initial_balance * 20%) let reward = (initial_balance / 5) / 20; - assert_eq!(Balances::free_balance(1), 10 + reward); + assert_eq!(asset::stakeable_balance::(&1), 10 + reward); on_offence_now( &[OffenceDetails { @@ -2660,7 +2668,7 @@ fn subsequent_reports_in_same_span_pay_out_less() { // F1 * (reward_proportion * slash - prior_payout) // 50% * (10% * (initial_balance / 2) - prior_payout) let reward = ((initial_balance / 20) - prior_payout) / 2; - assert_eq!(Balances::free_balance(1), 10 + prior_payout + reward); + assert_eq!(asset::stakeable_balance::(&1), 10 + prior_payout + reward); }); } @@ -2668,14 +2676,17 @@ fn subsequent_reports_in_same_span_pay_out_less() { fn invulnerables_are_not_slashed() { // For invulnerable validators no slashing is performed. ExtBuilder::default().invulnerables(vec![11]).build_and_execute(|| { - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(21), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&21), 2000); let exposure = Staking::eras_stakers(active_era(), &21); let initial_balance = Staking::slashable_balance_of(&21); - let nominator_balances: Vec<_> = - exposure.others.iter().map(|o| Balances::free_balance(&o.who)).collect(); + let nominator_balances: Vec<_> = exposure + .others + .iter() + .map(|o| asset::stakeable_balance::(&o.who)) + .collect(); on_offence_now( &[ @@ -2692,14 +2703,14 @@ fn invulnerables_are_not_slashed() { ); // The validator 11 hasn't been slashed, but 21 has been. - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); // 2000 - (0.2 * initial_balance) - assert_eq!(Balances::free_balance(21), 2000 - (2 * initial_balance / 10)); + assert_eq!(asset::stakeable_balance::(&21), 2000 - (2 * initial_balance / 10)); // ensure that nominators were slashed as well. for (initial_balance, other) in nominator_balances.into_iter().zip(exposure.others) { assert_eq!( - Balances::free_balance(&other.who), + asset::stakeable_balance::(&other.who), initial_balance - (2 * other.value / 10), ); } @@ -2710,7 +2721,7 @@ fn invulnerables_are_not_slashed() { fn dont_slash_if_fraction_is_zero() { // Don't slash if the fraction is zero. ExtBuilder::default().build_and_execute(|| { - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); on_offence_now( &[OffenceDetails { @@ -2721,7 +2732,7 @@ fn dont_slash_if_fraction_is_zero() { ); // The validator hasn't been slashed. The new era is not forced. - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); assert_eq!(Staking::force_era(), Forcing::NotForcing); }); } @@ -2731,7 +2742,7 @@ fn only_slash_for_max_in_era() { // multiple slashes within one era are only applied if it is more than any previous slash in the // same era. ExtBuilder::default().build_and_execute(|| { - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); on_offence_now( &[OffenceDetails { @@ -2742,7 +2753,7 @@ fn only_slash_for_max_in_era() { ); // The validator has been slashed and has been force-chilled. - assert_eq!(Balances::free_balance(11), 500); + assert_eq!(asset::stakeable_balance::(&11), 500); assert_eq!(Staking::force_era(), Forcing::NotForcing); on_offence_now( @@ -2754,7 +2765,7 @@ fn only_slash_for_max_in_era() { ); // The validator has not been slashed additionally. - assert_eq!(Balances::free_balance(11), 500); + assert_eq!(asset::stakeable_balance::(&11), 500); on_offence_now( &[OffenceDetails { @@ -2765,7 +2776,7 @@ fn only_slash_for_max_in_era() { ); // The validator got slashed 10% more. - assert_eq!(Balances::free_balance(11), 400); + assert_eq!(asset::stakeable_balance::(&11), 400); }) } @@ -2776,7 +2787,7 @@ fn garbage_collection_after_slashing() { .existential_deposit(2) .balance_factor(2) .build_and_execute(|| { - assert_eq!(Balances::free_balance(11), 2000); + assert_eq!(asset::stakeable_balance::(&11), 2000); on_offence_now( &[OffenceDetails { @@ -2786,7 +2797,7 @@ fn garbage_collection_after_slashing() { &[Perbill::from_percent(10)], ); - assert_eq!(Balances::free_balance(11), 2000 - 200); + assert_eq!(asset::stakeable_balance::(&11), 2000 - 200); assert!(SlashingSpans::::get(&11).is_some()); assert_eq!(SpanSlash::::get(&(11, 0)).amount(), &200); @@ -2801,8 +2812,8 @@ fn garbage_collection_after_slashing() { // validator and nominator slash in era are garbage-collected by era change, // so we don't test those here. - assert_eq!(Balances::free_balance(11), 2); - assert_eq!(Balances::total_balance(&11), 2); + assert_eq!(asset::stakeable_balance::(&11), 2); + assert_eq!(asset::total_balance::(&11), 2); let slashing_spans = SlashingSpans::::get(&11).unwrap(); assert_eq!(slashing_spans.iter().count(), 2); @@ -2826,11 +2837,11 @@ fn garbage_collection_on_window_pruning() { ExtBuilder::default().build_and_execute(|| { mock::start_active_era(1); - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); let now = active_era(); let exposure = Staking::eras_stakers(now, &11); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( @@ -2841,8 +2852,8 @@ fn garbage_collection_on_window_pruning() { &[Perbill::from_percent(10)], ); - assert_eq!(Balances::free_balance(11), 900); - assert_eq!(Balances::free_balance(101), 2000 - (nominated_value / 10)); + assert_eq!(asset::stakeable_balance::(&11), 900); + assert_eq!(asset::stakeable_balance::(&101), 2000 - (nominated_value / 10)); assert!(ValidatorSlashInEra::::get(&now, &11).is_some()); assert!(NominatorSlashInEra::::get(&now, &101).is_some()); @@ -2867,9 +2878,9 @@ fn slashing_nominators_by_span_max() { mock::start_active_era(2); mock::start_active_era(3); - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(21), 2000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&21), 2000); + assert_eq!(asset::stakeable_balance::(&101), 2000); assert_eq!(Staking::slashable_balance_of(&21), 1000); let exposure_11 = Staking::eras_stakers(active_era(), &11); @@ -2886,10 +2897,10 @@ fn slashing_nominators_by_span_max() { 2, ); - assert_eq!(Balances::free_balance(11), 900); + assert_eq!(asset::stakeable_balance::(&11), 900); let slash_1_amount = Perbill::from_percent(10) * nominated_value_11; - assert_eq!(Balances::free_balance(101), 2000 - slash_1_amount); + assert_eq!(asset::stakeable_balance::(&101), 2000 - slash_1_amount); let expected_spans = vec![ slashing::SlashingSpan { index: 1, start: 4, length: None }, @@ -2913,14 +2924,14 @@ fn slashing_nominators_by_span_max() { ); // 11 was not further slashed, but 21 and 101 were. - assert_eq!(Balances::free_balance(11), 900); - assert_eq!(Balances::free_balance(21), 1700); + assert_eq!(asset::stakeable_balance::(&11), 900); + assert_eq!(asset::stakeable_balance::(&21), 1700); let slash_2_amount = Perbill::from_percent(30) * nominated_value_21; assert!(slash_2_amount > slash_1_amount); // only the maximum slash in a single span is taken. - assert_eq!(Balances::free_balance(101), 2000 - slash_2_amount); + assert_eq!(asset::stakeable_balance::(&101), 2000 - slash_2_amount); // third slash: in same era and on same validator as first, higher // in-era value, but lower slash value than slash 2. @@ -2934,15 +2945,15 @@ fn slashing_nominators_by_span_max() { ); // 11 was further slashed, but 21 and 101 were not. - assert_eq!(Balances::free_balance(11), 800); - assert_eq!(Balances::free_balance(21), 1700); + assert_eq!(asset::stakeable_balance::(&11), 800); + assert_eq!(asset::stakeable_balance::(&21), 1700); let slash_3_amount = Perbill::from_percent(20) * nominated_value_21; assert!(slash_3_amount < slash_2_amount); assert!(slash_3_amount > slash_1_amount); // only the maximum slash in a single span is taken. - assert_eq!(Balances::free_balance(101), 2000 - slash_2_amount); + assert_eq!(asset::stakeable_balance::(&101), 2000 - slash_2_amount); }); } @@ -2953,7 +2964,7 @@ fn slashes_are_summed_across_spans() { mock::start_active_era(2); mock::start_active_era(3); - assert_eq!(Balances::free_balance(21), 2000); + assert_eq!(asset::stakeable_balance::(&21), 2000); assert_eq!(Staking::slashable_balance_of(&21), 1000); let get_span = |account| SlashingSpans::::get(&account).unwrap(); @@ -2972,7 +2983,7 @@ fn slashes_are_summed_across_spans() { ]; assert_eq!(get_span(21).iter().collect::>(), expected_spans); - assert_eq!(Balances::free_balance(21), 1900); + assert_eq!(asset::stakeable_balance::(&21), 1900); // 21 has been force-chilled. re-signal intent to validate. Staking::validate(RuntimeOrigin::signed(21), Default::default()).unwrap(); @@ -2996,7 +3007,7 @@ fn slashes_are_summed_across_spans() { ]; assert_eq!(get_span(21).iter().collect::>(), expected_spans); - assert_eq!(Balances::free_balance(21), 1810); + assert_eq!(asset::stakeable_balance::(&21), 1810); }); } @@ -3005,10 +3016,10 @@ fn deferred_slashes_are_deferred() { ExtBuilder::default().slash_defer_duration(2).build_and_execute(|| { mock::start_active_era(1); - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); let exposure = Staking::eras_stakers(active_era(), &11); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; System::reset_events(); @@ -3024,25 +3035,25 @@ fn deferred_slashes_are_deferred() { // nominations are not removed regardless of the deferring. assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); mock::start_active_era(2); - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); mock::start_active_era(3); - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); // at the start of era 4, slashes from era 1 are processed, // after being deferred for at least 2 full eras. mock::start_active_era(4); - assert_eq!(Balances::free_balance(11), 900); - assert_eq!(Balances::free_balance(101), 2000 - (nominated_value / 10)); + assert_eq!(asset::stakeable_balance::(&11), 900); + assert_eq!(asset::stakeable_balance::(&101), 2000 - (nominated_value / 10)); assert!(matches!( staking_events_since_last_call().as_slice(), @@ -3140,8 +3151,8 @@ fn staker_cannot_bail_deferred_slash() { ExtBuilder::default().slash_defer_duration(2).build_and_execute(|| { mock::start_active_era(1); - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); let exposure = Staking::eras_stakers(active_era(), &11); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; @@ -3173,20 +3184,20 @@ fn staker_cannot_bail_deferred_slash() { ); // no slash yet. - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); // no slash yet. mock::start_active_era(2); - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); assert_eq!(Staking::current_era().unwrap(), 2); assert_eq!(active_era(), 2); // no slash yet. mock::start_active_era(3); - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); assert_eq!(Staking::current_era().unwrap(), 3); assert_eq!(active_era(), 3); @@ -3203,8 +3214,8 @@ fn staker_cannot_bail_deferred_slash() { // after being deferred for at least 2 full eras. mock::start_active_era(4); - assert_eq!(Balances::free_balance(11), 900); - assert_eq!(Balances::free_balance(101), 2000 - (nominated_value / 10)); + assert_eq!(asset::stakeable_balance::(&11), 900); + assert_eq!(asset::stakeable_balance::(&101), 2000 - (nominated_value / 10)); // and the leftover of the funds can now be unbonded. }) @@ -3215,10 +3226,10 @@ fn remove_deferred() { ExtBuilder::default().slash_defer_duration(2).build_and_execute(|| { mock::start_active_era(1); - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); let exposure = Staking::eras_stakers(active_era(), &11); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; // deferred to start of era 4. @@ -3227,8 +3238,8 @@ fn remove_deferred() { &[Perbill::from_percent(10)], ); - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); mock::start_active_era(2); @@ -3249,13 +3260,13 @@ fn remove_deferred() { // cancel one of them. assert_ok!(Staking::cancel_deferred_slash(RuntimeOrigin::root(), 4, vec![0])); - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); mock::start_active_era(3); - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); // at the start of era 4, slashes from era 1 are processed, // after being deferred for at least 2 full eras. @@ -3280,8 +3291,8 @@ fn remove_deferred() { let actual_slash = total_slash - initial_slash; // 5% slash (15 - 10) processed now. - assert_eq!(Balances::free_balance(11), 950); - assert_eq!(Balances::free_balance(101), 2000 - actual_slash); + assert_eq!(asset::stakeable_balance::(&11), 950); + assert_eq!(asset::stakeable_balance::(&101), 2000 - actual_slash); }) } @@ -3290,10 +3301,10 @@ fn remove_multi_deferred() { ExtBuilder::default().slash_defer_duration(2).build_and_execute(|| { mock::start_active_era(1); - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); let exposure = Staking::eras_stakers(active_era(), &11); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&101), 2000); on_offence_now( &[OffenceDetails { offender: (11, exposure.clone()), reporters: vec![] }], @@ -3363,8 +3374,8 @@ fn slash_kicks_validators_not_nominators_and_disables_nominator_for_kicked_valid assert_eq_uvec!(Session::validators(), vec![11, 21, 31, 41, 51, 201, 202]); // pre-slash balance - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); // 100 has approval for 11 as of now assert!(Staking::nominators(101).unwrap().targets.contains(&11)); @@ -3398,8 +3409,8 @@ fn slash_kicks_validators_not_nominators_and_disables_nominator_for_kicked_valid // post-slash balance let nominator_slash_amount_11 = 125 / 10; - assert_eq!(Balances::free_balance(11), 900); - assert_eq!(Balances::free_balance(101), 2000 - nominator_slash_amount_11); + assert_eq!(asset::stakeable_balance::(&11), 900); + assert_eq!(asset::stakeable_balance::(&101), 2000 - nominator_slash_amount_11); // check that validator was disabled. assert!(is_disabled(11)); @@ -3663,8 +3674,8 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { // Consumed weight for all payout_stakers dispatches that fail let err_weight = ::WeightInfo::payout_stakers_alive_staked(0); - let init_balance_11 = Balances::total_balance(&11); - let init_balance_101 = Balances::total_balance(&101); + let init_balance_11 = asset::total_balance::(&11); + let init_balance_101 = asset::total_balance::(&101); let part_for_11 = Perbill::from_rational::(1000, 1125); let part_for_101 = Perbill::from_rational::(125, 1125); @@ -3728,11 +3739,11 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { // only era 1 and 2 can be rewarded. assert_eq!( - Balances::total_balance(&11), + asset::total_balance::(&11), init_balance_11 + part_for_11 * (total_payout_1 + total_payout_2), ); assert_eq!( - Balances::total_balance(&101), + asset::total_balance::(&101), init_balance_101 + part_for_101 * (total_payout_1 + total_payout_2), ); }); @@ -3749,18 +3760,18 @@ fn zero_slash_keeps_nominators() { .build_and_execute(|| { mock::start_active_era(1); - assert_eq!(Balances::free_balance(11), 1000); + assert_eq!(asset::stakeable_balance::(&11), 1000); let exposure = Staking::eras_stakers(active_era(), &11); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&101), 2000); on_offence_now( &[OffenceDetails { offender: (11, exposure.clone()), reporters: vec![] }], &[Perbill::from_percent(0)], ); - assert_eq!(Balances::free_balance(11), 1000); - assert_eq!(Balances::free_balance(101), 2000); + assert_eq!(asset::stakeable_balance::(&11), 1000); + assert_eq!(asset::stakeable_balance::(&101), 2000); // 11 is not removed but disabled assert!(Validators::::iter().any(|(stash, _)| stash == 11)); @@ -3837,7 +3848,7 @@ fn test_nominators_over_max_exposure_page_size_are_rewarded() { for i in 0..=MaxExposurePageSize::get() { let stash = 10_000 + i as AccountId; let balance = 10_000 + i as Balance; - Balances::make_free_balance_be(&stash, balance); + asset::set_stakeable_balance::(&stash, balance); assert_ok!(Staking::bond( RuntimeOrigin::signed(stash), balance, @@ -3859,13 +3870,13 @@ fn test_nominators_over_max_exposure_page_size_are_rewarded() { while i < MaxExposurePageSize::get() { let stash = 10_000 + i as AccountId; let balance = 10_000 + i as Balance; - assert!(Balances::free_balance(&stash) > balance); + assert!(asset::stakeable_balance::(&stash) > balance); i += 1; } // Assert overflowing nominators from page 1 are also rewarded let stash = 10_000 + i as AccountId; - assert!(Balances::free_balance(&stash) > (10_000 + i) as Balance); + assert!(asset::stakeable_balance::(&stash) > (10_000 + i) as Balance); }); } @@ -3878,7 +3889,7 @@ fn test_nominators_are_rewarded_for_all_exposure_page() { for i in 0..nominator_count { let stash = 10_000 + i as AccountId; let balance = 10_000 + i as Balance; - Balances::make_free_balance_be(&stash, balance); + asset::set_stakeable_balance::(&stash, balance); assert_ok!(Staking::bond( RuntimeOrigin::signed(stash), balance, @@ -3900,9 +3911,10 @@ fn test_nominators_are_rewarded_for_all_exposure_page() { // Assert all nominators are rewarded according to their stake for i in 0..nominator_count { // balance of the nominator after the reward payout. - let current_balance = Balances::free_balance(&((10000 + i) as AccountId)); + let current_balance = asset::stakeable_balance::(&((10000 + i) as AccountId)); // balance of the nominator in the previous iteration. - let previous_balance = Balances::free_balance(&((10000 + i - 1) as AccountId)); + let previous_balance = + asset::stakeable_balance::(&((10000 + i - 1) as AccountId)); // balance before the reward. let original_balance = 10_000 + i as Balance; @@ -3958,7 +3970,7 @@ fn test_multi_page_payout_stakers_by_page() { RewardOnUnbalanceWasCalled::set(false); System::reset_events(); - let controller_balance_before_p0_payout = Balances::free_balance(&11); + let controller_balance_before_p0_payout = asset::stakeable_balance::(&11); // Payout rewards for first exposure page assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0)); @@ -3972,7 +3984,7 @@ fn test_multi_page_payout_stakers_by_page() { ] )); - let controller_balance_after_p0_payout = Balances::free_balance(&11); + let controller_balance_after_p0_payout = asset::stakeable_balance::(&11); // verify rewards have been paid out but still some left assert!(pallet_balances::TotalIssuance::::get() > pre_payout_total_issuance); @@ -3996,7 +4008,7 @@ fn test_multi_page_payout_stakers_by_page() { ] )); // verify the validator was not rewarded the second time - assert_eq!(Balances::free_balance(&11), controller_balance_after_p0_payout); + assert_eq!(asset::stakeable_balance::(&11), controller_balance_after_p0_payout); // verify all rewards have been paid out assert_eq_error_rate!( @@ -4007,9 +4019,9 @@ fn test_multi_page_payout_stakers_by_page() { assert!(RewardOnUnbalanceWasCalled::get()); // Top 64 nominators of validator 11 automatically paid out, including the validator - assert!(Balances::free_balance(&11) > balance); + assert!(asset::stakeable_balance::(&11) > balance); for i in 0..100 { - assert!(Balances::free_balance(&(1000 + i)) > balance + i as Balance); + assert!(asset::stakeable_balance::(&(1000 + i)) > balance + i as Balance); } // verify we no longer track rewards in `legacy_claimed_rewards` vec @@ -4178,7 +4190,7 @@ fn test_multi_page_payout_stakers_backward_compatible() { let pre_payout_total_issuance = pallet_balances::TotalIssuance::::get(); RewardOnUnbalanceWasCalled::set(false); - let controller_balance_before_p0_payout = Balances::free_balance(&11); + let controller_balance_before_p0_payout = asset::stakeable_balance::(&11); // Payout rewards for first exposure page assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1)); // page 0 is claimed @@ -4187,7 +4199,7 @@ fn test_multi_page_payout_stakers_backward_compatible() { Error::::AlreadyClaimed.with_weight(err_weight) ); - let controller_balance_after_p0_payout = Balances::free_balance(&11); + let controller_balance_after_p0_payout = asset::stakeable_balance::(&11); // verify rewards have been paid out but still some left assert!(pallet_balances::TotalIssuance::::get() > pre_payout_total_issuance); @@ -4206,7 +4218,7 @@ fn test_multi_page_payout_stakers_backward_compatible() { ); // verify the validator was not rewarded the second time - assert_eq!(Balances::free_balance(&11), controller_balance_after_p0_payout); + assert_eq!(asset::stakeable_balance::(&11), controller_balance_after_p0_payout); // verify all rewards have been paid out assert_eq_error_rate!( @@ -4218,9 +4230,9 @@ fn test_multi_page_payout_stakers_backward_compatible() { // verify all nominators of validator 11 are paid out, including the validator // Validator payout goes to controller. - assert!(Balances::free_balance(&11) > balance); + assert!(asset::stakeable_balance::(&11) > balance); for i in 0..100 { - assert!(Balances::free_balance(&(1000 + i)) > balance + i as Balance); + assert!(asset::stakeable_balance::(&(1000 + i)) > balance + i as Balance); } // verify we no longer track rewards in `legacy_claimed_rewards` vec @@ -4578,25 +4590,29 @@ fn test_commission_paid_across_pages() { let payout = current_total_payout_for_duration(reward_time_per_era()); mock::start_active_era(2); - let initial_balance = Balances::free_balance(&11); + let initial_balance = asset::stakeable_balance::(&11); // Payout rewards for first exposure page assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0)); - let controller_balance_after_p0_payout = Balances::free_balance(&11); + let controller_balance_after_p0_payout = asset::stakeable_balance::(&11); // some commission is paid assert!(initial_balance < controller_balance_after_p0_payout); // payout all pages for i in 1..4 { - let before_balance = Balances::free_balance(&11); + let before_balance = asset::stakeable_balance::(&11); assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, i)); - let after_balance = Balances::free_balance(&11); + let after_balance = asset::stakeable_balance::(&11); // some commission is paid for every page assert!(before_balance < after_balance); } - assert_eq_error_rate!(Balances::free_balance(&11), initial_balance + payout / 2, 1,); + assert_eq_error_rate!( + asset::stakeable_balance::(&11), + initial_balance + payout / 2, + 1, + ); }); } @@ -4852,7 +4868,7 @@ fn payout_to_any_account_works() { assert_ok!(Staking::set_payee(RuntimeOrigin::signed(1234), RewardDestination::Account(42))); // Reward Destination account doesn't exist - assert_eq!(Balances::free_balance(42), 0); + assert_eq!(asset::stakeable_balance::(&42), 0); mock::start_active_era(1); Staking::reward_by_ids(vec![(11, 1)]); @@ -4862,7 +4878,7 @@ fn payout_to_any_account_works() { assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0)); // Payment is successful - assert!(Balances::free_balance(42) > 0); + assert!(asset::stakeable_balance::(&42) > 0); }) } @@ -5661,9 +5677,9 @@ fn chill_other_works() { let a = 4 * i; let b = 4 * i + 2; let c = 4 * i + 3; - Balances::make_free_balance_be(&a, 100_000); - Balances::make_free_balance_be(&b, 100_000); - Balances::make_free_balance_be(&c, 100_000); + asset::set_stakeable_balance::(&a, 100_000); + asset::set_stakeable_balance::(&b, 100_000); + asset::set_stakeable_balance::(&c, 100_000); // Nominator assert_ok!(Staking::bond(RuntimeOrigin::signed(a), 1000, RewardDestination::Stash)); @@ -6859,7 +6875,7 @@ fn test_runtime_api_pending_rewards() { // Set staker for v in validator_one..=validator_three { - let _ = Balances::make_free_balance_be(&v, stake); + let _ = asset::set_stakeable_balance::(&v, stake); assert_ok!(Staking::bond(RuntimeOrigin::signed(v), stake, RewardDestination::Staked)); } @@ -7049,7 +7065,7 @@ mod staking_interface { assert!(!>::contains_key(&11)); assert!(!>::contains_key(&11)); // lock is removed. - assert_eq!(Balances::balance_locked(STAKING_ID, &11), 0); + assert_eq!(asset::staked::(&11), 0); }); } @@ -7086,12 +7102,12 @@ mod staking_unchecked { fn virtual_bond_does_not_lock() { ExtBuilder::default().build_and_execute(|| { mock::start_active_era(1); - assert_eq!(Balances::free_balance(10), 1); + assert_eq!(asset::stakeable_balance::(&10), 1); // 10 can bond more than its balance amount since we do not require lock for virtual // bonding. assert_ok!(::virtual_bond(&10, 100, &15)); // nothing is locked on 10. - assert_eq!(Balances::balance_locked(STAKING_ID, &10), 0); + assert_eq!(asset::staked::(&10), 0); // adding more balance does not lock anything as well. assert_ok!(::bond_extra(&10, 1000)); // but ledger is updated correctly. @@ -7118,7 +7134,7 @@ mod staking_unchecked { Ok(Stake { total: 1100, active: 900 }) ); // still no locks. - assert_eq!(Balances::balance_locked(STAKING_ID, &10), 0); + assert_eq!(asset::staked::(&10), 0); mock::start_active_era(2); // cannot withdraw without waiting for unbonding period. @@ -7218,11 +7234,11 @@ mod staking_unchecked { fn migrate_virtual_staker() { ExtBuilder::default().build_and_execute(|| { // give some balance to 200 - Balances::make_free_balance_be(&200, 2000); + asset::set_stakeable_balance::(&200, 2000); // stake assert_ok!(Staking::bond(RuntimeOrigin::signed(200), 1000, RewardDestination::Staked)); - assert_eq!(Balances::balance_locked(crate::STAKING_ID, &200), 1000); + assert_eq!(asset::staked::(&200), 1000); // migrate them to virtual staker ::migrate_to_virtual_staker(&200); @@ -7230,7 +7246,7 @@ mod staking_unchecked { assert_ok!(::set_payee(&200, &201)); // ensure the balance is not locked anymore - assert_eq!(Balances::balance_locked(crate::STAKING_ID, &200), 0); + assert_eq!(asset::staked::(&200), 0); // and they are marked as virtual stakers assert_eq!(Pallet::::is_virtual_staker(&200), true); @@ -7300,7 +7316,7 @@ mod staking_unchecked { assert!(is_disabled(11)); // but virtual nominator's balance is not slashed. - assert_eq!(Balances::free_balance(&101), nominator_balance); + assert_eq!(asset::stakeable_balance::(&101), nominator_balance); // but slash is broadcasted to slash observers. assert_eq!(SlashObserver::get().get(&101).unwrap(), &nominator_share); }) @@ -7332,9 +7348,9 @@ mod staking_unchecked { assert_ok!(::set_payee(&101, &102)); // cache values - let validator_balance = Balances::free_balance(&11); + let validator_balance = asset::stakeable_balance::(&11); let validator_stake = Staking::ledger(11.into()).unwrap().total; - let nominator_balance = Balances::free_balance(&101); + let nominator_balance = asset::stakeable_balance::(&101); let nominator_stake = Staking::ledger(101.into()).unwrap().total; // 11 goes offline @@ -7353,14 +7369,14 @@ mod staking_unchecked { // all validator stake is slashed assert_eq_error_rate!( validator_balance - validator_stake, - Balances::free_balance(&11), + asset::stakeable_balance::(&11), 1 ); // Because slashing happened. assert!(is_disabled(11)); // Virtual nominator's balance is not slashed. - assert_eq!(Balances::free_balance(&101), nominator_balance); + assert_eq!(asset::stakeable_balance::(&101), nominator_balance); // Slash is broadcasted to slash observers. assert_eq!(SlashObserver::get().get(&101).unwrap(), &nominator_stake); @@ -7900,7 +7916,7 @@ mod ledger_recovery { ExtBuilder::default().has_stakers(true).try_state(false).build_and_execute(|| { setup_double_bonded_ledgers(); - let lock_333_before = Balances::balance_locked(crate::STAKING_ID, &333); + let lock_333_before = asset::staked::(&333); // get into corrupted and killed ledger state by killing a corrupted ledger: // init state: @@ -7936,14 +7952,14 @@ mod ledger_recovery { // side effects on 333 - ledger, bonded, payee, lock should be completely empty. // however, 333 lock remains. - assert_eq!(Balances::balance_locked(crate::STAKING_ID, &333), lock_333_before); // NOK + assert_eq!(asset::staked::(&333), lock_333_before); // NOK assert!(Bonded::::get(&333).is_none()); // OK assert!(Payee::::get(&333).is_none()); // OK assert!(Ledger::::get(&444).is_none()); // OK // side effects on 444 - ledger, bonded, payee, lock should remain be intact. // however, 444 lock was removed. - assert_eq!(Balances::balance_locked(crate::STAKING_ID, &444), 0); // NOK + assert_eq!(asset::staked::(&444), 0); // NOK assert!(Bonded::::get(&444).is_some()); // OK assert!(Payee::::get(&444).is_some()); // OK assert!(Ledger::::get(&555).is_none()); // NOK @@ -7957,7 +7973,7 @@ mod ledger_recovery { ExtBuilder::default().has_stakers(true).try_state(false).build_and_execute(|| { setup_double_bonded_ledgers(); - let lock_333_before = Balances::balance_locked(crate::STAKING_ID, &333); + let lock_333_before = asset::staked::(&333); // get into corrupted and killed ledger state by killing a corrupted ledger: // init state: @@ -7992,14 +8008,14 @@ mod ledger_recovery { assert_eq!(Staking::inspect_bond_state(&444), Err(Error::::NotStash)); // side effects on 333 - ledger, bonded, payee, lock should be intact. - assert_eq!(Balances::balance_locked(crate::STAKING_ID, &333), lock_333_before); // OK + assert_eq!(asset::staked::(&333), lock_333_before); // OK assert_eq!(Bonded::::get(&333), Some(444)); // OK assert!(Payee::::get(&333).is_some()); // OK // however, ledger associated with its controller was killed. assert!(Ledger::::get(&444).is_none()); // NOK // side effects on 444 - ledger, bonded, payee, lock should be completely removed. - assert_eq!(Balances::balance_locked(crate::STAKING_ID, &444), 0); // OK + assert_eq!(asset::staked::(&444), 0); // OK assert!(Bonded::::get(&444).is_none()); // OK assert!(Payee::::get(&444).is_none()); // OK assert!(Ledger::::get(&555).is_none()); // OK @@ -8080,7 +8096,7 @@ mod ledger_recovery { setup_double_bonded_ledgers(); // ledger.total == lock - let total_444_before_corruption = Balances::balance_locked(crate::STAKING_ID, &444); + let total_444_before_corruption = asset::staked::(&444); // get into corrupted and killed ledger state by killing a corrupted ledger: // init state: @@ -8182,8 +8198,8 @@ mod ledger_recovery { ExtBuilder::default().has_stakers(true).build_and_execute(|| { setup_double_bonded_ledgers(); - let lock_333_before = Balances::balance_locked(crate::STAKING_ID, &333); - let lock_444_before = Balances::balance_locked(crate::STAKING_ID, &444); + let lock_333_before = asset::staked::(&333); + let lock_444_before = asset::staked::(&444); // get into corrupted and killed ledger state by killing a corrupted ledger: // init state: @@ -8203,16 +8219,13 @@ mod ledger_recovery { // if 444 bonds extra, the locks remain in sync. bond_extra_no_checks(&444, 40); - assert_eq!(Balances::balance_locked(crate::STAKING_ID, &333), lock_333_before); - assert_eq!(Balances::balance_locked(crate::STAKING_ID, &444), lock_444_before + 40); + assert_eq!(asset::staked::(&333), lock_333_before); + assert_eq!(asset::staked::(&444), lock_444_before + 40); // however if 333 bonds extra, the wrong lock is updated. bond_extra_no_checks(&333, 30); - assert_eq!( - Balances::balance_locked(crate::STAKING_ID, &333), - lock_444_before + 40 + 30 - ); //not OK - assert_eq!(Balances::balance_locked(crate::STAKING_ID, &444), lock_444_before + 40); // OK + assert_eq!(asset::staked::(&333), lock_444_before + 40 + 30); //not OK + assert_eq!(asset::staked::(&444), lock_444_before + 40); // OK // recover the ledger bonded by 333 stash. Note that the total/lock needs to be // re-written since on-chain data lock has become out of sync. @@ -8247,9 +8260,9 @@ mod ledger_recovery { let ledger_444 = Bonded::::get(&444).and_then(Ledger::::get).unwrap(); assert_eq!(ledger_333.total, lock_333_before + 30); - assert_eq!(Balances::balance_locked(crate::STAKING_ID, &333), ledger_333.total); + assert_eq!(asset::staked::(&333), ledger_333.total); assert_eq!(ledger_444.total, lock_444_before + 40); - assert_eq!(Balances::balance_locked(crate::STAKING_ID, &444), ledger_444.total); + assert_eq!(asset::staked::(&444), ledger_444.total); // try-state checks are ok now. assert_ok!(Staking::do_try_state(System::block_number())); diff --git a/substrate/frame/support/src/traits.rs b/substrate/frame/support/src/traits.rs index 6e59ff9d030b..631225b9a327 100644 --- a/substrate/frame/support/src/traits.rs +++ b/substrate/frame/support/src/traits.rs @@ -23,7 +23,8 @@ pub mod tokens; pub use tokens::{ currency::{ ActiveIssuanceOf, Currency, InspectLockableCurrency, LockIdentifier, LockableCurrency, - NamedReservableCurrency, ReservableCurrency, TotalIssuanceOf, VestingSchedule, + NamedReservableCurrency, ReservableCurrency, TotalIssuanceOf, VestedTransfer, + VestingSchedule, }, fungible, fungibles, imbalance::{Imbalance, OnUnbalanced, SignedImbalance}, diff --git a/substrate/frame/support/src/traits/tokens/currency.rs b/substrate/frame/support/src/traits/tokens/currency.rs index b3db4c98001d..ea2c66a32cb0 100644 --- a/substrate/frame/support/src/traits/tokens/currency.rs +++ b/substrate/frame/support/src/traits/tokens/currency.rs @@ -30,7 +30,9 @@ use sp_runtime::{traits::MaybeSerializeDeserialize, DispatchError}; mod reservable; pub use reservable::{NamedReservableCurrency, ReservableCurrency}; mod lockable; -pub use lockable::{InspectLockableCurrency, LockIdentifier, LockableCurrency, VestingSchedule}; +pub use lockable::{ + InspectLockableCurrency, LockIdentifier, LockableCurrency, VestedTransfer, VestingSchedule, +}; /// Abstraction over a fungible assets system. pub trait Currency { diff --git a/substrate/frame/support/src/traits/tokens/currency/lockable.rs b/substrate/frame/support/src/traits/tokens/currency/lockable.rs index 51a48dd15ce8..4ec45c908e68 100644 --- a/substrate/frame/support/src/traits/tokens/currency/lockable.rs +++ b/substrate/frame/support/src/traits/tokens/currency/lockable.rs @@ -112,3 +112,56 @@ pub trait VestingSchedule { /// NOTE: This doesn't alter the free balance of the account. fn remove_vesting_schedule(who: &AccountId, schedule_index: u32) -> DispatchResult; } + +/// A vested transfer over a currency. This allows a transferred amount to vest over time. +pub trait VestedTransfer { + /// The quantity used to denote time; usually just a `BlockNumber`. + type Moment; + + /// The currency that this schedule applies to. + type Currency: Currency; + + /// Execute a vested transfer from `source` to `target` with the given schedule: + /// - `locked`: The amount to be transferred and for the vesting schedule to apply to. + /// - `per_block`: The amount to be unlocked each block. (linear vesting) + /// - `starting_block`: The block where the vesting should start. This block can be in the past + /// or future, and should adjust when the tokens become available to the user. + /// + /// Example: Assume we are on block 100. If `locked` amount is 100, and `per_block` is 1: + /// - If `starting_block` is 0, then the whole 100 tokens will be available right away as the + /// vesting schedule started in the past and has fully completed. + /// - If `starting_block` is 50, then 50 tokens are made available right away, and 50 more + /// tokens will unlock one token at a time until block 150. + /// - If `starting_block` is 100, then each block, 1 token will be unlocked until the whole + /// balance is unlocked at block 200. + /// - If `starting_block` is 200, then the 100 token balance will be completely locked until + /// block 200, and then start to unlock one token at a time until block 300. + fn vested_transfer( + source: &AccountId, + target: &AccountId, + locked: >::Balance, + per_block: >::Balance, + starting_block: Self::Moment, + ) -> DispatchResult; +} + +// An no-op implementation of `VestedTransfer` for pallets that require this trait, but users may +// not want to implement this functionality +pub struct NoVestedTransfers { + phantom: core::marker::PhantomData, +} + +impl> VestedTransfer for NoVestedTransfers { + type Moment = (); + type Currency = C; + + fn vested_transfer( + _source: &AccountId, + _target: &AccountId, + _locked: >::Balance, + _per_block: >::Balance, + _starting_block: Self::Moment, + ) -> DispatchResult { + Err(sp_runtime::DispatchError::Unavailable.into()) + } +} diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 8ac32b777d80..536d68b84f79 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -365,7 +365,7 @@ pub mod pallet { type MaxConsumers = frame_support::traits::ConstU32<128>; /// The default data to be stored in an account. - type AccountData = crate::AccountInfo; + type AccountData = (); /// What to do if a new account is created. type OnNewAccount = (); diff --git a/substrate/frame/treasury/Cargo.toml b/substrate/frame/treasury/Cargo.toml index 55bdd4f7a498..93a3d9bea93d 100644 --- a/substrate/frame/treasury/Cargo.toml +++ b/substrate/frame/treasury/Cargo.toml @@ -30,6 +30,7 @@ frame-system = { workspace = true } pallet-balances = { workspace = true } sp-runtime = { workspace = true } sp-core = { optional = true, workspace = true } +log = { workspace = true } [dev-dependencies] sp-io = { workspace = true, default-features = true } @@ -43,6 +44,7 @@ std = [ "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "log/std", "pallet-balances/std", "pallet-utility/std", "scale-info/std", diff --git a/substrate/frame/treasury/src/lib.rs b/substrate/frame/treasury/src/lib.rs index edb39f230642..ad74495ce090 100644 --- a/substrate/frame/treasury/src/lib.rs +++ b/substrate/frame/treasury/src/lib.rs @@ -73,6 +73,7 @@ #![cfg_attr(not(feature = "std"), no_std)] mod benchmarking; +pub mod migration; #[cfg(test)] mod tests; pub mod weights; diff --git a/substrate/frame/treasury/src/migration.rs b/substrate/frame/treasury/src/migration.rs new file mode 100644 index 000000000000..c0de4ce43108 --- /dev/null +++ b/substrate/frame/treasury/src/migration.rs @@ -0,0 +1,133 @@ +// 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. + +//! Treasury pallet migrations. + +use super::*; +use alloc::collections::BTreeSet; +#[cfg(feature = "try-runtime")] +use alloc::vec::Vec; +use core::marker::PhantomData; +use frame_support::{defensive, traits::OnRuntimeUpgrade}; + +/// The log target for this pallet. +const LOG_TARGET: &str = "runtime::treasury"; + +pub mod cleanup_proposals { + use super::*; + + /// Migration to cleanup unapproved proposals to return the bonds back to the proposers. + /// Proposals can no longer be created and the `Proposal` storage item will be removed in the + /// future. + /// + /// `UnreserveWeight` returns `Weight` of `unreserve_balance` operation which is perfomed during + /// this migration. + pub struct Migration(PhantomData<(T, I, UnreserveWeight)>); + + impl, I: 'static, UnreserveWeight: Get> OnRuntimeUpgrade + for Migration + { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + let mut approval_index = BTreeSet::new(); + for approval in Approvals::::get().iter() { + approval_index.insert(*approval); + } + + let mut proposals_processed = 0; + for (proposal_index, p) in Proposals::::iter() { + if !approval_index.contains(&proposal_index) { + let err_amount = T::Currency::unreserve(&p.proposer, p.bond); + if err_amount.is_zero() { + Proposals::::remove(proposal_index); + log::info!( + target: LOG_TARGET, + "Released bond amount of {:?} to proposer {:?}", + p.bond, + p.proposer, + ); + } else { + defensive!( + "err_amount is non zero for proposal {:?}", + (proposal_index, err_amount) + ); + Proposals::::mutate_extant(proposal_index, |proposal| { + proposal.value = err_amount; + }); + log::info!( + target: LOG_TARGET, + "Released partial bond amount of {:?} to proposer {:?}", + p.bond - err_amount, + p.proposer, + ); + } + proposals_processed += 1; + } + } + + log::info!( + target: LOG_TARGET, + "Migration for pallet-treasury finished, released {} proposal bonds.", + proposals_processed, + ); + + // calculate and return migration weights + let approvals_read = 1; + T::DbWeight::get().reads_writes( + proposals_processed as u64 + approvals_read, + proposals_processed as u64, + ) + UnreserveWeight::get() * proposals_processed + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + let value = ( + Proposals::::iter_values().count() as u32, + Approvals::::get().len() as u32, + ); + log::info!( + target: LOG_TARGET, + "Proposals and Approvals count {:?}", + value, + ); + Ok(value.encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { + let (old_proposals_count, old_approvals_count) = + <(u32, u32)>::decode(&mut &state[..]).expect("Known good"); + let new_proposals_count = Proposals::::iter_values().count() as u32; + let new_approvals_count = Approvals::::get().len() as u32; + + log::info!( + target: LOG_TARGET, + "Proposals and Approvals count {:?}", + (new_proposals_count, new_approvals_count), + ); + + ensure!( + new_proposals_count <= old_proposals_count, + "Proposals after migration should be less or equal to old proposals" + ); + ensure!( + new_approvals_count == old_approvals_count, + "Approvals after migration should remain the same" + ); + Ok(()) + } + } +} diff --git a/substrate/frame/vesting/src/benchmarking.rs b/substrate/frame/vesting/src/benchmarking.rs index 68214c4f47cc..736dd6eac1a8 100644 --- a/substrate/frame/vesting/src/benchmarking.rs +++ b/substrate/frame/vesting/src/benchmarking.rs @@ -42,7 +42,7 @@ fn add_locks(who: &T::AccountId, n: u8) { } fn add_vesting_schedules( - target: AccountIdLookupOf, + target: &T::AccountId, n: u32, ) -> Result, &'static str> { let min_transfer = T::MinVestedTransfer::get(); @@ -52,7 +52,6 @@ fn add_vesting_schedules( let starting_block = 1u32; let source: T::AccountId = account("source", 0, SEED); - let source_lookup = T::Lookup::unlookup(source.clone()); T::Currency::make_free_balance_be(&source, BalanceOf::::max_value()); T::BlockNumberProvider::set_block_number(BlockNumberFor::::zero()); @@ -62,11 +61,7 @@ fn add_vesting_schedules( total_locked += locked; let schedule = VestingInfo::new(locked, per_block, starting_block.into()); - assert_ok!(Vesting::::do_vested_transfer( - source_lookup.clone(), - target.clone(), - schedule - )); + assert_ok!(Vesting::::do_vested_transfer(&source, target, schedule)); // Top up to guarantee we can always transfer another schedule. T::Currency::make_free_balance_be(&source, BalanceOf::::max_value()); @@ -81,11 +76,10 @@ benchmarks! { let s in 1 .. T::MAX_VESTING_SCHEDULES; let caller: T::AccountId = whitelisted_caller(); - let caller_lookup = T::Lookup::unlookup(caller.clone()); T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance()); add_locks::(&caller, l as u8); - let expected_balance = add_vesting_schedules::(caller_lookup, s)?; + let expected_balance = add_vesting_schedules::(&caller, s)?; // At block zero, everything is vested. assert_eq!(System::::block_number(), BlockNumberFor::::zero()); @@ -109,11 +103,10 @@ benchmarks! { let s in 1 .. T::MAX_VESTING_SCHEDULES; let caller: T::AccountId = whitelisted_caller(); - let caller_lookup = T::Lookup::unlookup(caller.clone()); T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance()); add_locks::(&caller, l as u8); - add_vesting_schedules::(caller_lookup, s)?; + add_vesting_schedules::(&caller, s)?; // At block 21, everything is unlocked. T::BlockNumberProvider::set_block_number(21u32.into()); @@ -141,7 +134,7 @@ benchmarks! { T::Currency::make_free_balance_be(&other, T::Currency::minimum_balance()); add_locks::(&other, l as u8); - let expected_balance = add_vesting_schedules::(other_lookup.clone(), s)?; + let expected_balance = add_vesting_schedules::(&other, s)?; // At block zero, everything is vested. assert_eq!(System::::block_number(), BlockNumberFor::::zero()); @@ -171,7 +164,7 @@ benchmarks! { T::Currency::make_free_balance_be(&other, T::Currency::minimum_balance()); add_locks::(&other, l as u8); - add_vesting_schedules::(other_lookup.clone(), s)?; + add_vesting_schedules::(&other, s)?; // At block 21 everything is unlocked. T::BlockNumberProvider::set_block_number(21u32.into()); @@ -206,7 +199,7 @@ benchmarks! { add_locks::(&target, l as u8); // Add one vesting schedules. let orig_balance = T::Currency::free_balance(&target); - let mut expected_balance = add_vesting_schedules::(target_lookup.clone(), s)?; + let mut expected_balance = add_vesting_schedules::(&target, s)?; let transfer_amount = T::MinVestedTransfer::get(); let per_block = transfer_amount.checked_div(&20u32.into()).unwrap(); @@ -246,7 +239,7 @@ benchmarks! { add_locks::(&target, l as u8); // Add one less than max vesting schedules let orig_balance = T::Currency::free_balance(&target); - let mut expected_balance = add_vesting_schedules::(target_lookup.clone(), s)?; + let mut expected_balance = add_vesting_schedules::(&target, s)?; let transfer_amount = T::MinVestedTransfer::get(); let per_block = transfer_amount.checked_div(&20u32.into()).unwrap(); @@ -281,7 +274,7 @@ benchmarks! { T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance()); add_locks::(&caller, l as u8); // Add max vesting schedules. - let expected_balance = add_vesting_schedules::(caller_lookup, s)?; + let expected_balance = add_vesting_schedules::(&caller, s)?; // Schedules are not vesting at block 0. assert_eq!(System::::block_number(), BlockNumberFor::::zero()); @@ -332,7 +325,7 @@ benchmarks! { T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance()); add_locks::(&caller, l as u8); // Add max vesting schedules. - let total_transferred = add_vesting_schedules::(caller_lookup, s)?; + let total_transferred = add_vesting_schedules::(&caller, s)?; // Go to about half way through all the schedules duration. (They all start at 1, and have a duration of 20 or 21). T::BlockNumberProvider::set_block_number(11u32.into()); @@ -397,7 +390,7 @@ force_remove_vesting_schedule { // Give target existing locks. add_locks::(&target, l as u8); - let _ = add_vesting_schedules::(target_lookup.clone(), s)?; + add_vesting_schedules::(&target, s)?; // The last vesting schedule. let schedule_index = s - 1; diff --git a/substrate/frame/vesting/src/lib.rs b/substrate/frame/vesting/src/lib.rs index bfc10efeed79..15f8d397f81c 100644 --- a/substrate/frame/vesting/src/lib.rs +++ b/substrate/frame/vesting/src/lib.rs @@ -66,8 +66,8 @@ use frame_support::{ ensure, storage::bounded_vec::BoundedVec, traits::{ - Currency, ExistenceRequirement, Get, LockIdentifier, LockableCurrency, VestingSchedule, - WithdrawReasons, + Currency, ExistenceRequirement, Get, LockIdentifier, LockableCurrency, VestedTransfer, + VestingSchedule, WithdrawReasons, }, weights::Weight, }; @@ -351,8 +351,8 @@ pub mod pallet { schedule: VestingInfo, BlockNumberFor>, ) -> DispatchResult { let transactor = ensure_signed(origin)?; - let transactor = ::unlookup(transactor); - Self::do_vested_transfer(transactor, target, schedule) + let target = T::Lookup::lookup(target)?; + Self::do_vested_transfer(&transactor, &target, schedule) } /// Force a vested transfer. @@ -380,7 +380,9 @@ pub mod pallet { schedule: VestingInfo, BlockNumberFor>, ) -> DispatchResult { ensure_root(origin)?; - Self::do_vested_transfer(source, target, schedule) + let target = T::Lookup::lookup(target)?; + let source = T::Lookup::lookup(source)?; + Self::do_vested_transfer(&source, &target, schedule) } /// Merge two vesting schedules together, creating a new vesting schedule that unlocks over @@ -525,8 +527,8 @@ impl Pallet { // Execute a vested transfer from `source` to `target` with the given `schedule`. fn do_vested_transfer( - source: AccountIdLookupOf, - target: AccountIdLookupOf, + source: &T::AccountId, + target: &T::AccountId, schedule: VestingInfo, BlockNumberFor>, ) -> DispatchResult { // Validate user inputs. @@ -534,27 +536,22 @@ impl Pallet { if !schedule.is_valid() { return Err(Error::::InvalidScheduleParams.into()) }; - let target = T::Lookup::lookup(target)?; - let source = T::Lookup::lookup(source)?; // Check we can add to this account prior to any storage writes. Self::can_add_vesting_schedule( - &target, + target, schedule.locked(), schedule.per_block(), schedule.starting_block(), )?; - T::Currency::transfer( - &source, - &target, - schedule.locked(), - ExistenceRequirement::AllowDeath, - )?; + T::Currency::transfer(source, target, schedule.locked(), ExistenceRequirement::AllowDeath)?; // We can't let this fail because the currency transfer has already happened. + // Must be successful as it has been checked before. + // Better to return error on failure anyway. let res = Self::add_vesting_schedule( - &target, + target, schedule.locked(), schedule.per_block(), schedule.starting_block(), @@ -751,8 +748,8 @@ where Ok(()) } - // Ensure we can call `add_vesting_schedule` without error. This should always - // be called prior to `add_vesting_schedule`. + /// Ensure we can call `add_vesting_schedule` without error. This should always + /// be called prior to `add_vesting_schedule`. fn can_add_vesting_schedule( who: &T::AccountId, locked: BalanceOf, @@ -784,3 +781,32 @@ where Ok(()) } } + +/// An implementation that allows the Vesting Pallet to handle a vested transfer +/// on behalf of another Pallet. +impl VestedTransfer for Pallet +where + BalanceOf: MaybeSerializeDeserialize + Debug, +{ + type Currency = T::Currency; + type Moment = BlockNumberFor; + + fn vested_transfer( + source: &T::AccountId, + target: &T::AccountId, + locked: BalanceOf, + per_block: BalanceOf, + starting_block: BlockNumberFor, + ) -> DispatchResult { + use frame_support::storage::{with_transaction, TransactionOutcome}; + let schedule = VestingInfo::new(locked, per_block, starting_block); + with_transaction(|| -> TransactionOutcome { + let result = Self::do_vested_transfer(source, target, schedule); + + match &result { + Ok(()) => TransactionOutcome::Commit(result), + _ => TransactionOutcome::Rollback(result), + } + }) + } +} diff --git a/substrate/frame/vesting/src/tests.rs b/substrate/frame/vesting/src/tests.rs index 57cb59f27a4d..0dd7133d930a 100644 --- a/substrate/frame/vesting/src/tests.rs +++ b/substrate/frame/vesting/src/tests.rs @@ -280,13 +280,14 @@ fn extra_balance_should_transfer() { // Account 1 has only 5 units vested at block 1 (plus 150 unvested) assert_eq!(Vesting::vesting_balance(&1), Some(45)); assert_ok!(Vesting::vest(Some(1).into())); - assert_ok!(Balances::transfer_allow_death(Some(1).into(), 3, 155)); // Account 1 can send extra units gained + // Account 1 can send extra units gained + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 3, 155)); // Account 2 has no units vested at block 1, but gained 100 assert_eq!(Vesting::vesting_balance(&2), Some(200)); assert_ok!(Vesting::vest(Some(2).into())); - assert_ok!(Balances::transfer_allow_death(Some(2).into(), 3, 100)); // Account 2 can send extra - // units gained + // Account 2 can send extra units gained + assert_ok!(Balances::transfer_allow_death(Some(2).into(), 3, 100)); }); } @@ -295,14 +296,16 @@ fn liquid_funds_should_transfer_with_delayed_vesting() { ExtBuilder::default().existential_deposit(256).build().execute_with(|| { let user12_free_balance = Balances::free_balance(&12); - assert_eq!(user12_free_balance, 2560); // Account 12 has free balance - // Account 12 has liquid funds + // Account 12 has free balance + assert_eq!(user12_free_balance, 2560); + // Account 12 has liquid funds assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance - 256 * 5)); // Account 12 has delayed vesting let user12_vesting_schedule = VestingInfo::new( 256 * 5, - 64, // Vesting over 20 blocks + // Vesting over 20 blocks + 64, 10, ); assert_eq!(VestingStorage::::get(&12).unwrap(), vec![user12_vesting_schedule]); @@ -630,8 +633,10 @@ fn merge_ongoing_schedules() { let sched1 = VestingInfo::new( ED * 10, - ED, // Vest over 10 blocks. - sched0.starting_block() + 5, // Start at block 15. + // Vest over 10 blocks. + ED, + // Start at block 15. + sched0.starting_block() + 5, ); assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); assert_eq!(VestingStorage::::get(&2).unwrap(), vec![sched0, sched1]); @@ -1191,3 +1196,43 @@ fn remove_vesting_schedule() { ); }); } + +#[test] +fn vested_transfer_impl_works() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert_eq!(Balances::free_balance(&3), 256 * 30); + assert_eq!(Balances::free_balance(&4), 256 * 40); + // Account 4 should not have any vesting yet. + assert_eq!(VestingStorage::::get(&4), None); + + // Basic working scenario + assert_ok!(>::vested_transfer( + &3, + &4, + ED * 5, + ED * 5 / 20, + 10 + )); + // Now account 4 should have vesting. + let new_vesting_schedule = VestingInfo::new( + ED * 5, + (ED * 5) / 20, // Vesting over 20 blocks + 10, + ); + assert_eq!(VestingStorage::::get(&4).unwrap(), vec![new_vesting_schedule]); + // Account 4 has 5 * 256 locked. + assert_eq!(Vesting::vesting_balance(&4), Some(256 * 5)); + + // If the transfer fails (because they don't have enough balance), no storage is changed. + assert_noop!( + >::vested_transfer(&3, &4, ED * 9999, ED * 5 / 20, 10), + TokenError::FundsUnavailable + ); + + // If applying the vesting schedule fails (per block is 0), no storage is changed. + assert_noop!( + >::vested_transfer(&3, &4, ED * 5, 0, 10), + Error::::InvalidScheduleParams + ); + }); +} diff --git a/substrate/primitives/runtime/src/testing.rs b/substrate/primitives/runtime/src/testing.rs index b4aeda5a0e7a..a4ce4b5fc1a0 100644 --- a/substrate/primitives/runtime/src/testing.rs +++ b/substrate/primitives/runtime/src/testing.rs @@ -29,10 +29,7 @@ use crate::{ ApplyExtrinsicResultWithInfo, KeyTypeId, }; use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize, Serializer}; -use sp_core::{ - crypto::{key_types, ByteArray, CryptoType, Dummy}, - U256, -}; +use sp_core::crypto::{key_types, ByteArray, CryptoType, Dummy}; pub use sp_core::{sr25519, H256}; use std::{ cell::RefCell, @@ -79,7 +76,8 @@ impl From for u64 { impl UintAuthorityId { /// Convert this authority ID into a public key. pub fn to_public_key(&self) -> T { - let bytes: [u8; 32] = U256::from(self.0).into(); + let mut bytes = [0u8; 32]; + bytes[0..8].copy_from_slice(&self.0.to_le_bytes()); T::from_slice(&bytes).unwrap() } } diff --git a/substrate/primitives/staking/src/lib.rs b/substrate/primitives/staking/src/lib.rs index 5e94524816a0..17010a8907fc 100644 --- a/substrate/primitives/staking/src/lib.rs +++ b/substrate/primitives/staking/src/lib.rs @@ -619,7 +619,7 @@ pub trait DelegationMigrator { /// /// Also removed from [`StakingUnchecked`] as a Virtual Staker. Useful for testing. #[cfg(feature = "runtime-benchmarks")] - fn migrate_to_direct_staker(agent: Agent); + fn force_kill_agent(agent: Agent); } sp_core::generate_feature_enabled_macro!(runtime_benchmarks_enabled, feature = "runtime-benchmarks", $); diff --git a/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs b/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs index 520e4cfda7bb..b5d7016f1ca4 100644 --- a/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs +++ b/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs @@ -36,7 +36,7 @@ use sp_core::{ testing::{TestOffchainExt, TestTransactionPoolExt}, OffchainDbExt, OffchainWorkerExt, TransactionPoolExt, }, - traits::{CallContext, CodeExecutor, ReadRuntimeVersionExt}, + traits::{CallContext, CodeExecutor, ReadRuntimeVersionExt, WrappedRuntimeCode}, Hasher, }; use sp_externalities::Extensions; @@ -47,6 +47,7 @@ use sp_storage::{well_known_keys::CODE, Storage}; use sp_trie::{proof_size_extension::ProofSizeExt, recorder::Recorder}; use sp_wasm_interface::HostFunctions; use std::{ + borrow::Cow, collections::{BTreeMap, BTreeSet, HashMap}, fmt::Debug, fs, @@ -368,12 +369,12 @@ impl PalletCmd { "dispatch a benchmark", ) { Err(e) => { - log::error!("Error executing and verifying runtime benchmark: {}", e); + log::error!(target: LOG_TARGET, "Error executing and verifying runtime benchmark: {}", e); failed.push((pallet.clone(), extrinsic.clone())); continue 'outer }, Ok(Err(e)) => { - log::error!("Error executing and verifying runtime benchmark: {}", e); + log::error!(target: LOG_TARGET, "Error executing and verifying runtime benchmark: {}", e); failed.push((pallet.clone(), extrinsic.clone())); continue 'outer }, @@ -408,12 +409,12 @@ impl PalletCmd { "dispatch a benchmark", ) { Err(e) => { - log::error!("Error executing runtime benchmark: {}", e); + log::error!(target: LOG_TARGET, "Error executing runtime benchmark: {}", e); failed.push((pallet.clone(), extrinsic.clone())); continue 'outer }, Ok(Err(e)) => { - log::error!("Benchmark {pallet}::{extrinsic} failed: {e}",); + log::error!(target: LOG_TARGET, "Benchmark {pallet}::{extrinsic} failed: {e}",); failed.push((pallet.clone(), extrinsic.clone())); continue 'outer }, @@ -502,33 +503,28 @@ impl PalletCmd { } fn select_benchmarks_to_run(&self, list: Vec) -> Result> { - let pallet = self.pallet.clone().unwrap_or_default(); - let pallet = pallet.as_bytes(); - let extrinsic = self.extrinsic.clone().unwrap_or_default(); let extrinsic_split: Vec<&str> = extrinsic.split(',').collect(); let extrinsics: Vec<_> = extrinsic_split.iter().map(|x| x.trim().as_bytes()).collect(); // Use the benchmark list and the user input to determine the set of benchmarks to run. let mut benchmarks_to_run = Vec::new(); - list.iter() - .filter(|item| pallet.is_empty() || pallet == &b"*"[..] || pallet == &item.pallet[..]) - .for_each(|item| { - for benchmark in &item.benchmarks { - let benchmark_name = &benchmark.name; - if extrinsic.is_empty() || - extrinsic.as_bytes() == &b"*"[..] || - extrinsics.contains(&&benchmark_name[..]) - { - benchmarks_to_run.push(( - item.pallet.clone(), - benchmark.name.clone(), - benchmark.components.clone(), - benchmark.pov_modes.clone(), - )) - } + list.iter().filter(|item| self.pallet_selected(&item.pallet)).for_each(|item| { + for benchmark in &item.benchmarks { + let benchmark_name = &benchmark.name; + if extrinsic.is_empty() || + extrinsic.as_bytes() == &b"*"[..] || + extrinsics.contains(&&benchmark_name[..]) + { + benchmarks_to_run.push(( + item.pallet.clone(), + benchmark.name.clone(), + benchmark.components.clone(), + benchmark.pov_modes.clone(), + )) } - }); + } + }); // Convert `Vec` to `String` for better readability. let benchmarks_to_run: Vec<_> = benchmarks_to_run .into_iter() @@ -558,6 +554,16 @@ impl PalletCmd { Ok(benchmarks_to_run) } + /// Whether this pallet should be run. + fn pallet_selected(&self, pallet: &Vec) -> bool { + let include = self.pallet.clone().unwrap_or_default(); + + let included = include.is_empty() || include == "*" || include.as_bytes() == pallet; + let excluded = self.exclude_pallets.iter().any(|p| p.as_bytes() == pallet); + + included && !excluded + } + /// Build the genesis storage by either the Genesis Builder API, chain spec or nothing. /// /// Behaviour can be controlled by the `--genesis-builder` flag. @@ -566,12 +572,11 @@ impl PalletCmd { chain_spec: &Option>, ) -> Result { Ok(match (self.genesis_builder, self.runtime.as_ref()) { - (Some(GenesisBuilderPolicy::None), Some(_)) => return Err("Cannot use `--genesis-builder=none` with `--runtime` since the runtime would be ignored.".into()), - (Some(GenesisBuilderPolicy::None), None) => Storage::default(), + (Some(GenesisBuilderPolicy::None), _) => Storage::default(), (Some(GenesisBuilderPolicy::SpecGenesis | GenesisBuilderPolicy::Spec), Some(_)) => return Err("Cannot use `--genesis-builder=spec-genesis` with `--runtime` since the runtime would be ignored.".into()), (Some(GenesisBuilderPolicy::SpecGenesis | GenesisBuilderPolicy::Spec), None) | (None, None) => { - log::warn!("{WARN_SPEC_GENESIS_CTOR}"); + log::warn!(target: LOG_TARGET, "{WARN_SPEC_GENESIS_CTOR}"); let Some(chain_spec) = chain_spec else { return Err("No chain spec specified to generate the genesis state".into()); }; @@ -593,7 +598,7 @@ impl PalletCmd { }, (Some(GenesisBuilderPolicy::Runtime), None) => return Err("Cannot use `--genesis-builder=runtime` without `--runtime`".into()), (Some(GenesisBuilderPolicy::Runtime), Some(runtime)) | (None, Some(runtime)) => { - log::info!("Loading WASM from {}", runtime.display()); + log::info!(target: LOG_TARGET, "Loading WASM from {}", runtime.display()); let code = fs::read(&runtime).map_err(|e| { format!( @@ -613,7 +618,7 @@ impl PalletCmd { &self, chain_spec: &dyn ChainSpec, ) -> Result { - log::info!("Building genesis state from chain spec runtime"); + log::info!(target: LOG_TARGET, "Building genesis state from chain spec runtime"); let storage = chain_spec .build_storage() .map_err(|e| format!("{ERROR_CANNOT_BUILD_GENESIS}\nError: {e}"))?; @@ -636,8 +641,9 @@ impl PalletCmd { genesis_config_caller.get_storage_for_named_preset(preset).inspect_err(|e| { let presets = genesis_config_caller.preset_names().unwrap_or_default(); log::error!( + target: LOG_TARGET, "Please pick one of the available presets with \ - `--genesis-builder-preset=`. Available presets ({}): {:?}. Error: {:?}", + `--genesis-builder-preset=` or use a different `--genesis-builder-policy`. Available presets ({}): {:?}. Error: {:?}", presets.len(), presets, e @@ -690,11 +696,25 @@ impl PalletCmd { &self, state: &'a BenchmarkingState, ) -> Result, H>> { - log::info!("Loading WASM from state"); - let state = - sp_state_machine::backend::BackendRuntimeCode::new(state, IgnorePendingCode::Yes); + if let Some(runtime) = self.runtime.as_ref() { + log::info!(target: LOG_TARGET, "Loading WASM from file"); + let code = fs::read(runtime).map_err(|e| { + format!( + "Could not load runtime file from path: {}, error: {}", + runtime.display(), + e + ) + })?; + let hash = sp_core::blake2_256(&code).to_vec(); + let wrapped_code = WrappedRuntimeCode(Cow::Owned(code)); + + Ok(FetchedCode::FromFile { wrapped_code, heap_pages: self.heap_pages, hash }) + } else { + log::info!(target: LOG_TARGET, "Loading WASM from state"); + let state = sp_state_machine::backend::BackendRuntimeCode::new(state, IgnorePendingCode::Yes); - Ok(FetchedCode { state }) + Ok(FetchedCode::FromGenesis { state }) + } } /// Allocation strategy for pallet benchmarking. diff --git a/substrate/utils/frame/benchmarking-cli/src/pallet/mod.rs b/substrate/utils/frame/benchmarking-cli/src/pallet/mod.rs index a507c1d1f548..412a1a86cb8e 100644 --- a/substrate/utils/frame/benchmarking-cli/src/pallet/mod.rs +++ b/substrate/utils/frame/benchmarking-cli/src/pallet/mod.rs @@ -53,6 +53,10 @@ pub struct PalletCmd { #[arg(short, long, required_unless_present_any = ["list", "json_input", "all"], default_value_if("all", "true", Some("*".into())))] pub extrinsic: Option, + /// Comma separated list of pallets that should be excluded from the benchmark. + #[arg(long, value_parser, num_args = 1.., value_delimiter = ',')] + pub exclude_pallets: Vec, + /// Run benchmarks for all pallets and extrinsics. /// /// This is equivalent to running `--pallet * --extrinsic *`. diff --git a/substrate/utils/frame/benchmarking-cli/src/pallet/types.rs b/substrate/utils/frame/benchmarking-cli/src/pallet/types.rs index ce37be455e8a..a4799dc92369 100644 --- a/substrate/utils/frame/benchmarking-cli/src/pallet/types.rs +++ b/substrate/utils/frame/benchmarking-cli/src/pallet/types.rs @@ -18,7 +18,7 @@ //! Various types used by this crate. use sc_cli::Result; -use sp_core::traits::RuntimeCode; +use sp_core::traits::{RuntimeCode, WrappedRuntimeCode}; use sp_runtime::traits::Hash; /// How the genesis state for benchmarking should be build. @@ -43,8 +43,9 @@ pub enum GenesisBuilderPolicy { /// A runtime blob that was either fetched from genesis storage or loaded from a file. // NOTE: This enum is only needed for the annoying lifetime bounds on `RuntimeCode`. Otherwise we // could just directly return the blob. -pub struct FetchedCode<'a, B, H> { - pub state: sp_state_machine::backend::BackendRuntimeCode<'a, B, H>, +pub enum FetchedCode<'a, B, H> { + FromGenesis { state: sp_state_machine::backend::BackendRuntimeCode<'a, B, H> }, + FromFile { wrapped_code: WrappedRuntimeCode<'a>, heap_pages: Option, hash: Vec }, } impl<'a, B, H> FetchedCode<'a, B, H> @@ -54,7 +55,14 @@ where { /// The runtime blob. pub fn code(&'a self) -> Result> { - self.state.runtime_code().map_err(Into::into) + match self { + Self::FromGenesis { state } => state.runtime_code().map_err(Into::into), + Self::FromFile { wrapped_code, heap_pages, hash } => Ok(RuntimeCode { + code_fetcher: wrapped_code, + heap_pages: *heap_pages, + hash: hash.clone(), + }), + } } } diff --git a/substrate/utils/frame/benchmarking-cli/src/pallet/writer.rs b/substrate/utils/frame/benchmarking-cli/src/pallet/writer.rs index 34f31734da67..28918dd4e6a3 100644 --- a/substrate/utils/frame/benchmarking-cli/src/pallet/writer.rs +++ b/substrate/utils/frame/benchmarking-cli/src/pallet/writer.rs @@ -484,9 +484,6 @@ pub(crate) fn write_results( benchmarks: results.clone(), }; - let file_path = fs::canonicalize(&file_path).map_err(|e| { - format!("Could not get absolute path for: {:?}. Error: {:?}", &file_path, e) - })?; let mut output_file = fs::File::create(&file_path).map_err(|e| { format!("Could not write weight file to: {:?}. Error: {:?}", &file_path, e) })?; diff --git a/umbrella/Cargo.toml b/umbrella/Cargo.toml index 3e7edc739821..e05bf129bbd5 100644 --- a/umbrella/Cargo.toml +++ b/umbrella/Cargo.toml @@ -335,7 +335,7 @@ runtime-benchmarks = [ "parachains-common?/runtime-benchmarks", "polkadot-cli?/runtime-benchmarks", "polkadot-node-metrics?/runtime-benchmarks", - "polkadot-parachain-lib?/runtime-benchmarks", + "polkadot-omni-node-lib?/runtime-benchmarks", "polkadot-parachain-primitives?/runtime-benchmarks", "polkadot-primitives?/runtime-benchmarks", "polkadot-runtime-common?/runtime-benchmarks", @@ -466,7 +466,7 @@ try-runtime = [ "pallet-xcm-bridge-hub?/try-runtime", "pallet-xcm?/try-runtime", "polkadot-cli?/try-runtime", - "polkadot-parachain-lib?/try-runtime", + "polkadot-omni-node-lib?/try-runtime", "polkadot-runtime-common?/try-runtime", "polkadot-runtime-parachains?/try-runtime", "polkadot-sdk-frame?/try-runtime", @@ -600,7 +600,7 @@ runtime = [ "sp-wasm-interface", "sp-weights", ] -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-revive-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-approval-voting-parallel", "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-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-types", "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-parachain-lib", "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-chain-spec-builder", "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"] +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-revive-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-approval-voting-parallel", "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-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-types", "polkadot-node-subsystem-util", "polkadot-omni-node-lib", "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-chain-spec-builder", "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", @@ -2082,13 +2082,13 @@ path = "../polkadot/node/subsystem-util" default-features = false optional = true -[dependencies.polkadot-overseer] -path = "../polkadot/node/overseer" +[dependencies.polkadot-omni-node-lib] +path = "../cumulus/polkadot-omni-node/lib" default-features = false optional = true -[dependencies.polkadot-parachain-lib] -path = "../cumulus/polkadot-parachain/polkadot-parachain-lib" +[dependencies.polkadot-overseer] +path = "../polkadot/node/overseer" default-features = false optional = true diff --git a/umbrella/src/lib.rs b/umbrella/src/lib.rs index 656273029fe8..7778706d515d 100644 --- a/umbrella/src/lib.rs +++ b/umbrella/src/lib.rs @@ -898,14 +898,14 @@ pub use polkadot_node_subsystem_types; #[cfg(feature = "polkadot-node-subsystem-util")] pub use polkadot_node_subsystem_util; +/// Helper library that can be used to build a parachain node. +#[cfg(feature = "polkadot-omni-node-lib")] +pub use polkadot_omni_node_lib; + /// System overseer of the Polkadot node. #[cfg(feature = "polkadot-overseer")] pub use polkadot_overseer; -/// Helper library that can be used to build a parachain node. -#[cfg(feature = "polkadot-parachain-lib")] -pub use polkadot_parachain_lib; - /// Types and utilities for creating and working with parachains. #[cfg(feature = "polkadot-parachain-primitives")] pub use polkadot_parachain_primitives;