├── .devcontainer ├── devcontainer.json └── updateContentCommand.sh ├── .editorconfig ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .rustfmt.toml ├── CODEOWNERS ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── node ├── Cargo.toml ├── build.rs └── src │ ├── chain_spec.rs │ ├── chain_spec │ └── dev.rs │ ├── cli.rs │ ├── command.rs │ ├── main.rs │ ├── rpc.rs │ ├── service.rs │ └── service │ └── dev.rs ├── parachain-runtime ├── Cargo.toml ├── build.rs └── src │ ├── assets_config.rs │ ├── contracts_config.rs │ ├── lib.rs │ ├── revive_config.rs │ ├── weights │ ├── block_weights.rs │ ├── extrinsic_weights.rs │ ├── mod.rs │ ├── paritydb_weights.rs │ └── rocksdb_weights.rs │ └── xcm_config.rs ├── runtime ├── Cargo.toml ├── build.rs └── src │ ├── assets_config.rs │ ├── contracts_config.rs │ ├── lib.rs │ └── revive_config.rs ├── scripts └── ci │ └── pre_cache.sh └── zombienet.toml /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": "mcr.microsoft.com/devcontainers/universal:2", 3 | "features": { 4 | "ghcr.io/devcontainers/features/rust:1": {}, 5 | "devwasm.azurecr.io/dev-wasm/dev-wasm-feature/rust-wasi:0": {} 6 | }, 7 | "updateContentCommand": "./.devcontainer/updateContentCommand.sh" 8 | } 9 | -------------------------------------------------------------------------------- /.devcontainer/updateContentCommand.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Installing protoc..." 4 | sudo apt update 5 | sudo apt install -y unzip 6 | PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') 7 | curl -Lo protoc.zip "https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-${PROTOC_VERSION}-linux-x86_64.zip" 8 | sudo unzip -q protoc.zip bin/protoc -d /usr/local 9 | sudo chmod a+x /usr/local/bin/protoc 10 | rm -rf protoc.zip 11 | 12 | echo "Installing Substrate Contracts Node..." 13 | SUBSTRATE_VERSION=$(curl -s "https://api.github.com/repos/paritytech/substrate-contracts-node/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') 14 | curl -Lo substrate.tar.gz "https://github.com/paritytech/substrate-contracts-node/releases/download/v${SUBSTRATE_VERSION}/substrate-contracts-node-linux.tar.gz" 15 | mkdir substrate-temp 16 | tar -xzf substrate.tar.gz -C substrate-temp 17 | sudo mv substrate-temp/artifacts/substrate-contracts-node-linux/substrate-contracts-node /usr/local/bin/ 18 | sudo chmod a+x /usr/local/bin/substrate-contracts-node 19 | rm -rf substrate.tar.gz substrate-temp 20 | 21 | echo "Installing cargo-contract CLI tool..." 22 | cargo install --force --locked cargo-contract --version 2.0.0-rc 23 | 24 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style=space 5 | indent_size=2 6 | tab_width=2 7 | end_of_line=lf 8 | charset=utf-8 9 | trim_trailing_whitespace=true 10 | insert_final_newline=true 11 | 12 | [*.{rs,toml}] 13 | indent_style=tab 14 | indent_size=tab 15 | tab_width=4 16 | max_line_length=100 17 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | tags: 8 | - v* 9 | pull_request: 10 | types: [opened, synchronize, reopened, ready_for_review] 11 | 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 14 | cancel-in-progress: true 15 | 16 | # common variable is defined in the workflow 17 | # repo env variable doesn't work for PR from forks 18 | env: 19 | CI_IMAGE: "paritytech/ci-unified:bullseye-1.81.0" 20 | 21 | jobs: 22 | set-image: 23 | # This workaround sets the container image for each job using 'set-image' job output. 24 | # env variables don't work for PR from forks, so we need to use outputs. 25 | runs-on: ubuntu-latest 26 | outputs: 27 | CI_IMAGE: ${{ steps.set_image.outputs.CI_IMAGE }} 28 | steps: 29 | - id: set_image 30 | run: echo "CI_IMAGE=${{ env.CI_IMAGE }}" >> $GITHUB_OUTPUT 31 | 32 | fmt: 33 | name: Cargo fmt 34 | runs-on: ubuntu-latest 35 | timeout-minutes: 5 36 | needs: [set-image] 37 | container: 38 | image: ${{ needs.set-image.outputs.CI_IMAGE }} 39 | steps: 40 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 41 | - name: Rust Cache 42 | uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 43 | with: 44 | cache-on-failure: true 45 | cache-all-crates: true 46 | - name: cargo info 47 | run: | 48 | echo "######## rustup show ########" 49 | rustup show 50 | echo "######## cargo --version ########" 51 | cargo --version 52 | - name: Cargo fmt 53 | run: cargo +nightly fmt --all -- --check 54 | 55 | build-test-linux: 56 | name: Build Linux 57 | runs-on: parity-large 58 | timeout-minutes: 50 59 | needs: [set-image, fmt] 60 | container: 61 | image: ${{ needs.set-image.outputs.CI_IMAGE }} 62 | steps: 63 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 64 | - name: Rust Cache 65 | uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 66 | with: 67 | cache-on-failure: true 68 | cache-all-crates: true 69 | - name: cargo info 70 | run: | 71 | echo "######## rustup show ########" 72 | rustup show 73 | echo "######## cargo --version ########" 74 | cargo --version 75 | - name: Build and Test Linux 76 | run: | 77 | echo "######## cargo build ########" 78 | cargo build --release 79 | echo "######## cargo test ########" 80 | cargo test --release --all 81 | echo "######## Packing artifacts ########" 82 | mkdir -p ./artifacts/substrate-contracts-node-linux/ 83 | cp target/release/substrate-contracts-node ./artifacts/substrate-contracts-node-linux/substrate-contracts-node 84 | ls -la ./artifacts/substrate-contracts-node-linux/ 85 | - name: Upload artifacts 86 | uses: actions/upload-artifact@v4.3.6 87 | with: 88 | name: build-linux 89 | path: ./artifacts 90 | build-macos: 91 | timeout-minutes: 50 92 | runs-on: parity-macos 93 | needs: [fmt] 94 | steps: 95 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 96 | - name: Set rust version from env file 97 | run: | 98 | echo $CI_IMAGE 99 | RUST_VERSION=$(echo $CI_IMAGE | sed -E 's/.*ci-unified:([^-]+)-([^-]+).*/\2/') 100 | echo $RUST_VERSION 101 | echo "RUST_VERSION=${RUST_VERSION}" >> $GITHUB_ENV 102 | - name: Set up Homebrew 103 | uses: Homebrew/actions/setup-homebrew@1ccc07ccd54b6048295516a3eb89b192c35057dc # master from 12.09.2024 104 | - name: Install protobuf 105 | run: brew install protobuf 106 | - name: Install rust ${{ env.RUST_VERSION }} 107 | uses: actions-rust-lang/setup-rust-toolchain@1fbea72663f6d4c03efaab13560c8a24cfd2a7cc # v1.9.0 108 | with: 109 | cache: false 110 | toolchain: ${{ env.RUST_VERSION }} 111 | target: wasm32-unknown-unknown, aarch64-apple-darwin, x86_64-apple-darwin 112 | components: cargo, clippy, rust-docs, rust-src, rustfmt, rustc, rust-std 113 | - name: cargo info 114 | run: | 115 | echo "######## rustup show ########" 116 | rustup show 117 | echo "######## cargo --version ########" 118 | cargo --version 119 | - name: Rust Cache 120 | uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 121 | with: 122 | cache-on-failure: true 123 | cache-all-crates: true 124 | - name: Run cargo build 125 | run: | 126 | echo "######## cargo build aarch64-apple-darwin ########" 127 | cargo build --release --target aarch64-apple-darwin 128 | echo "######## cargo build x86_64-apple-darwin ########" 129 | cargo build --release --target x86_64-apple-darwin 130 | echo "######## Packing artifacts ########" 131 | mkdir -p ./artifacts/substrate-contracts-node-mac/ 132 | lipo ./target/x86_64-apple-darwin/release/substrate-contracts-node \ 133 | ./target/aarch64-apple-darwin/release/substrate-contracts-node \ 134 | -create -output ./artifacts/substrate-contracts-node-mac/substrate-contracts-node 135 | ls -la ./artifacts/substrate-contracts-node-mac/ 136 | - name: Upload artifacts 137 | uses: actions/upload-artifact@v4.3.6 138 | with: 139 | name: build-macos 140 | path: ./artifacts 141 | publish: 142 | name: Publish release 143 | runs-on: ubuntu-latest 144 | needs: [build-test-linux, build-macos] 145 | permissions: 146 | contents: write 147 | steps: 148 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 149 | - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 150 | with: 151 | name: build-linux 152 | - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 153 | with: 154 | name: build-macos 155 | - name: Pack artifacts 156 | run: | 157 | tar -czvf ./substrate-contracts-node-linux.tar.gz ./substrate-contracts-node-linux 158 | tar -czvf ./substrate-contracts-node-mac-universal.tar.gz ./substrate-contracts-node-mac 159 | ls -la 160 | - name: Publish release 161 | uses: ghalactic/github-release-from-tag@cebdacac0ccd08933b8e7f278f4123723ad978eb # v5.4.0 162 | if: github.ref_type == 'tag' 163 | with: 164 | prerelease: false 165 | draft: true 166 | assets: | 167 | - path: substrate-contracts-node-linux.tar.gz 168 | - path: substrate-contracts-node-mac-universal.tar.gz 169 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/target/ 2 | **/*.rs.bk 3 | *.swp 4 | .wasm-binaries 5 | .vscode 6 | .DS_Store 7 | .idea/ 8 | rls*.log 9 | runtime/Cargo.lock -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | # Basic 2 | hard_tabs = true 3 | max_width = 100 4 | use_small_heuristics = "Max" 5 | # Imports 6 | imports_granularity = "Crate" 7 | reorder_imports = true 8 | # Consistency 9 | newline_style = "Unix" 10 | # Format comments 11 | comment_width = 100 12 | wrap_comments = true 13 | # Misc 14 | chain_width = 80 15 | spaces_around_ranges = false 16 | binop_separator = "Back" 17 | reorder_impl_items = false 18 | match_arm_leading_pipes = "Preserve" 19 | match_arm_blocks = false 20 | match_block_trailing_comma = true 21 | trailing_comma = "Vertical" 22 | trailing_semicolon = false 23 | use_field_init_shorthand = true 24 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lists some code owners. 2 | # 3 | # A codeowner just oversees some part of the codebase. If an owned file is changed then the 4 | # corresponding codeowner receives a review request. An approval of the codeowner might be 5 | # required for merging a PR (depends on repository settings). 6 | # 7 | # For details about syntax, see: 8 | # https://help.github.com/en/articles/about-code-owners 9 | # But here are some important notes: 10 | # 11 | # - Glob syntax is git-like, e.g. `/core` means the core directory in the root, unlike `core` 12 | # which can be everywhere. 13 | # - Multiple owners are supported. 14 | # - Either handle (e.g, @github_user or @github_org/team) or email can be used. Keep in mind, 15 | # that handles might work better because they are more recognizable on GitHub, 16 | # eyou can use them for mentioning unlike an email. 17 | # - The latest matching rule, if multiple, takes precedence. 18 | 19 | # Global code owners 20 | * @cmichi @athei @ascjones @agryaznov @SkymanOne 21 | 22 | # CI 23 | /.github/ @paritytech/ci @cmichi @ascjones @athei @agryaznov @SkymanOne 24 | /scripts/ci/ @paritytech/ci @cmichi @ascjones @athei @agryaznov @SkymanOne 25 | /.gitlab-ci.yml @paritytech/ci @cmichi @ascjones @athei @agryaznov @SkymanOne 26 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace.package] 2 | authors = ["anonymous"] 3 | edition = "2021" 4 | version = "0.42.0" 5 | license = "Unlicense" 6 | homepage = "https://github.com/paritytech/substrate-contracts-node" 7 | repository = "https://github.com/paritytech/substrate-contracts-node" 8 | 9 | [workspace] 10 | resolver = "2" 11 | members = ["node", "runtime", "parachain-runtime"] 12 | 13 | [profile.release] 14 | panic = 'unwind' 15 | 16 | [workspace.dependencies] 17 | clap = { version = "4.5.10", features = ["derive"] } 18 | codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ 19 | "derive", 20 | ] } 21 | futures = "0.3.30" 22 | hex-literal = { version = "0.4.1" } 23 | jsonrpsee = { version = "0.24.3", features = ["server"] } 24 | log = { version = "0.4.22", default-features = false } 25 | serde = { version = "1.0.209", features = ["derive"] } 26 | serde_json = "1.0.127" 27 | scale-info = { version = "2.11.1", default-features = false, features = [ 28 | "derive", 29 | ] } 30 | smallvec = "1.11.0" 31 | color-print = "0.3.4" 32 | wasmtime = "8.0.1" 33 | 34 | # Substrate 35 | frame-benchmarking = { version = "38.0.0", default-features = false } 36 | frame-benchmarking-cli = { version = "43.0.0" } 37 | frame-executive = { version = "38.0.0", default-features = false } 38 | frame-support = { version = "38.0.0", default-features = false } 39 | frame-support-procedural = { version = "30.0.3", default-features = false } 40 | frame-system = { version = "38.0.0", default-features = false } 41 | frame-system-benchmarking = { version = "38.0.0", default-features = false } 42 | frame-system-rpc-runtime-api = { version = "34.0.0", default-features = false } 43 | frame-try-runtime = { version = "0.44.0", default-features = false } 44 | pallet-aura = { version = "37.0.0", default-features = false } 45 | pallet-authorship = { version = "38.0.0", default-features = false } 46 | pallet-balances = { version = "39.0.0", default-features = false } 47 | pallet-contracts = { version = "38.0.0", default-features = false } 48 | pallet-session = { version = "38.0.0", default-features = false } 49 | pallet-sudo = { version = "38.0.0", default-features = false } 50 | pallet-timestamp = { version = "37.0.0", default-features = false } 51 | pallet-transaction-payment = { version = "38.0.0", default-features = false } 52 | pallet-message-queue = { version = "41.0.2", default-features = false } 53 | pallet-transaction-payment-rpc = { version = "41.0.0" } 54 | pallet-transaction-payment-rpc-runtime-api = { version = "38.0.0", default-features = false } 55 | sc-basic-authorship = { version = "0.45.0" } 56 | sc-chain-spec = { version = "38.0.0" } 57 | sc-cli = { version = "0.47.0" } 58 | sc-client-api = { version = "37.0.0" } 59 | sc-consensus = { version = "0.44.0" } 60 | sc-executor = { version = "0.40.1" } 61 | sc-network = { version = "0.45.1" } 62 | sc-network-sync = { version = "0.44.1" } 63 | sc-offchain = { version = "40.0.0" } 64 | sc-rpc = { version = "40.0.0" } 65 | sc-service = { version = "0.46.0" } 66 | sc-sysinfo = { version = "38.0.0" } 67 | sc-telemetry = { version = "25.0.0" } 68 | sc-tracing = { version = "37.0.1" } 69 | sc-transaction-pool = { version = "37.0.0" } 70 | sc-transaction-pool-api = { version = "37.0.0" } 71 | sp-api = { version = "34.0.0", default-features = false } 72 | sp-keyring = { version = "39.0.0", default-features = false } 73 | sp-block-builder = { version = "34.0.0", default-features = false } 74 | sp-blockchain = { version = "37.0.1" } 75 | sp-consensus-aura = { version = "0.40.0", default-features = false } 76 | sp-core = { version = "34.0.0", default-features = false } 77 | sp-inherents = { version = "34.0.0", default-features = false } 78 | sp-io = { version = "38.0.0", default-features = false } 79 | sp-keystore = { version = "0.40.0" } 80 | sp-offchain = { version = "34.0.0", default-features = false } 81 | sp-runtime = { version = "39.0.1", default-features = false } 82 | sp-session = { version = "36.0.0", default-features = false } 83 | sp-std = { version = "14.0.0", default-features = false } 84 | sp-timestamp = { version = "34.0.0" } 85 | sp-transaction-pool = { version = "34.0.0", default-features = false } 86 | sp-version = { version = "37.0.0", default-features = false } 87 | substrate-frame-rpc-system = { version = "39.0.0" } 88 | prometheus-endpoint = { version = "0.17.0", default-features = false, package = "substrate-prometheus-endpoint" } 89 | substrate-wasm-builder = { version = "24.0.1" } 90 | substrate-build-script-utils = { version = "11.0.0" } 91 | try-runtime-cli = { version = "0.42.0" } 92 | 93 | # extra deps for running a solo node on top of a parachain 94 | pallet-grandpa = { version = "38.0.0", default-features = false } 95 | sc-consensus-grandpa = { version = "0.30.0", default-features = false } 96 | sp-consensus-grandpa = { version = "21.0.0", default-features = false } 97 | sp-genesis-builder = { version = "0.15.1", default-features = false } 98 | sp-storage = { version = "21.0.0", default-features = false } 99 | sc-consensus-aura = { version = "0.45.0", default-features = false } 100 | sc-consensus-manual-seal = { version = "0.46.0", default-features = false } 101 | 102 | # extra deps for setting up pallet-revive 103 | pallet-assets = { version = "40.0.0", default-features = false } 104 | pallet-insecure-randomness-collective-flip = { version = "26.0.0", default-features = false } 105 | pallet-revive = { version = "0.2.0", default-features = false } 106 | pallet-utility = { version = "38.0.0", default-features = false } 107 | 108 | # Polkadot 109 | pallet-xcm = { version = "17.0.1", default-features = false } 110 | polkadot-cli = { version = "19.0.0", default-features = false } 111 | polkadot-parachain-primitives = { version = "14.0.0", default-features = false } 112 | polkadot-primitives = { version = "16.0.0" } 113 | polkadot-runtime-common = { version = "17.0.0", default-features = false } 114 | xcm = { version = "14.2.0", package = "staging-xcm", default-features = false } 115 | xcm-builder = { version = "17.0.1", package = "staging-xcm-builder", default-features = false } 116 | xcm-executor = { version = "17.0.0", package = "staging-xcm-executor", default-features = false } 117 | 118 | # Cumulus 119 | cumulus-client-cli = { version = "0.18.0" } 120 | cumulus-client-collator = { version = "0.18.0" } 121 | cumulus-client-consensus-proposer = { version = "0.16.0" } 122 | cumulus-client-consensus-aura = { version = "0.18.0" } 123 | cumulus-client-consensus-common = { version = "0.18.0" } 124 | cumulus-client-service = { version = "0.19.0" } 125 | cumulus-pallet-aura-ext = { version = "0.17.0", default-features = false } 126 | cumulus-pallet-dmp-queue = { version = "0.17.0", default-features = false } 127 | cumulus-pallet-parachain-system = { version = "0.17.1", default-features = false } 128 | cumulus-pallet-session-benchmarking = { version = "19.0.0", default-features = false } 129 | cumulus-pallet-xcm = { version = "0.17.0", default-features = false } 130 | cumulus-pallet-xcmp-queue = { version = "0.17.0", default-features = false } 131 | cumulus-primitives-aura = { version = "0.15.0", default-features = false } 132 | cumulus-primitives-core = { version = "0.16.0", default-features = false } 133 | cumulus-primitives-parachain-inherent = { version = "0.16.0" } 134 | cumulus-primitives-timestamp = { version = "0.16.0", default-features = false } 135 | cumulus-primitives-utility = { version = "0.17.0", default-features = false } 136 | cumulus-relay-chain-interface = { version = "0.18.0" } 137 | pallet-collator-selection = { version = "19.0.0", default-features = false } 138 | parachain-info = { version = "0.17.0", package = "staging-parachain-info", default-features = false } 139 | parachains-common = { version = "18.0.0", default-features = false } 140 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # substrate-contracts-node 2 | 3 | [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/paritytech/substrate-contracts-node) 4 | 5 | This repository contains Substrate's [`node-template`](https://github.com/paritytech/substrate/tree/master/bin/node-template) 6 | configured to include Substrate's [`pallet-contracts`](https://github.com/paritytech/substrate/tree/master/frame/contracts) 7 | ‒ a smart contract module. 8 | 9 | _This repository contains a couple of modifications that make it unsuitable 10 | for a production deployment, but a great fit for development and testing:_ 11 | 12 | * The unstable features of the [`pallet-contracts`](https://github.com/paritytech/substrate/tree/master/frame/contracts) 13 | are enabled by default (see the [`runtime/Cargo.toml`](https://github.com/paritytech/substrate-contracts-node/blob/main/runtime/Cargo.toml)). 14 | * The consensus algorithm has been switched to `manual-seal` in 15 | [#42](https://github.com/paritytech/substrate-contracts-node/pull/42). 16 | Hereby blocks are authored immediately at every transaction, so there 17 | is none of the typical six seconds block time associated with `grandpa` or `aura`. 18 | * By default, either manual or instant seal does not result in block finalization unless the `engine_finalizeBlock` 19 | RPC is executed. However, it is possible to configure the finalization of sealed blocks to occur after a certain 20 | amount of time by setting the `--finalize-delay-sec` option to a specific value, which specifies the number of seconds 21 | to delay before finalizing the blocks. The default value is 1 second. 22 | ```shell 23 | ./target/release/substrate-contracts-node --finalize-delay-sec 5 24 | ``` 25 | * _If no CLI arguments are passed the node is started in development mode 26 | by default._ 27 | * A custom logging filter is applied by default that hides block production noise 28 | and prints the contracts debug buffer to the console. 29 | * _With each start of the node process the chain starts from genesis ‒ so no 30 | chain state is retained, all contracts will be lost! If you want to retain 31 | chain state you have to supply a `--base-path`._ 32 | * For `pallet_contracts::Config` we increased the allowed contract sizes. This 33 | avoids running into `CodeTooLarge` when uploading contracts during development. 34 | See the comment in [`runtime/src/lib.rs`](https://github.com/paritytech/substrate-contracts-node/blob/main/runtime/src/lib.rs) 35 | for more details. 36 | 37 | If you are looking for a node suitable for production see these configurations: 38 | 39 | * [Substrate Node Template](https://github.com/paritytech/substrate/tree/master/bin/node-template) 40 | * [Substrate Cumulus Parachain Template](https://github.com/paritytech/cumulus/tree/master/parachain-template) 41 | * [Contracts Parachain Configuration for Rococo](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/contracts/contracts-rococo) 42 | 43 | ## Installation 44 | 45 | ### Download Binary 46 | 47 | The easiest way is to download a binary release from [our releases page](https://github.com/paritytech/substrate-contracts-node/releases) 48 | and just execute `./substrate-contracts-node`. 49 | 50 | ### Build Locally 51 | 52 | Follow the [official installation steps](https://docs.substrate.io/install/) to set up all Substrate prerequisites. 53 | 54 | Afterwards you can install this node via 55 | 56 | ```bash 57 | cargo install contracts-node 58 | ``` 59 | 60 | ## Usage 61 | 62 | To run a local dev node execute 63 | 64 | ```bash 65 | substrate-contracts-node 66 | ``` 67 | 68 | A new chain in temporary directory will be created each time the command is executed. This is the 69 | default for this node. If you want to persist chain state across runs you need to 70 | specify a directory with `--base-path`. 71 | 72 | See our FAQ for more details: 73 | [How do I print something to the console from the runtime?](https://paritytech.github.io/ink-docs/faq/#how-do-i-print-something-to-the-console-from-the-runtime). 74 | 75 | ## Connect with frontend 76 | 77 | Once the node template is running locally, you can connect to it with frontends like [Contracts UI](https://contracts-ui.substrate.io/#/?rpc=ws://127.0.0.1:9944) or [Polkadot-JS Apps](https://polkadot.js.org/apps/#/explorer?rpc=ws://localhost:9944) and interact with your chain. 78 | 79 | ## How to upgrade to new Polkadot release 80 | 81 | We can have two types of releases: 82 | 83 | * Internal release: This type of release does not involve releasing the crates on crates.io. It involves using Git 84 | references in the Cargo.toml dependencies. We utilize this type of release for faster iteration when we don't want 85 | to wait for the substrate crates to be released. 86 | 87 | * Crate release: This is the preferable type of release, which involves specifying crate versions in the Cargo.toml 88 | dependencies and releasing the crates on crates.io.. 89 | 90 | - [ ] Check Substrate's [`solochain-template`](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain), 91 | for new commits between the new polkadot release branch and the one this repository is currently synced with. 92 | The current branch is mentioned in the last release. 93 | - [ ] Apply each commit that happened in this `solochain-template` folder since the last sync. 94 | - [ ] Check [`parachain-template`](https://github.com/paritytech/polkadot-sdk/tree/master/templates/parachain) 95 | and apply each commit that has occurred in its folder since the last sync. 96 | - [ ] Check commits for [`pallet-contracts`](https://github.com/paritytech/polkadot-sdk/tree/master/substrate/frame/contracts) 97 | since the last time someone synchronized this repository with Substrate 98 | in order to not miss any important changes. 99 | - [ ] (Crate release only) Execute `psvm -p ./Cargo.toml -v X.X.X`, to update the dependencies to the required versions. 100 | Replace `X.X.X` with the requested Polkadot release version. 101 | - [ ] (Internal release only) Manually update the dependencies in Cargo.toml to the required Git SHA versions. 102 | - [ ] Increment the minor version number in `Cargo.toml` and `node/Cargo.toml`. 103 | - [ ] Execute `cargo run --release`. If successful, it should produce blocks 104 | and a new, up to date, `Cargo.lock` will be created. 105 | - [ ] Create a PR with the changes, have it reviewed. 106 | - [ ] (Crate release only) Upload crates to `crates.io` using the commands below, replacing `XX` with your incremented 107 | version number: 108 | `cargo release 0.XX.0 -v --no-tag --no-push -p contracts-node-runtime -p contracts-parachain-runtime --execute` 109 | `cargo release 0.XX.0 -v --no-tag --no-push -p contracts-node --execute` 110 | Note: Before uploading, perform a dry run to ensure that it will be successful. 111 | - [ ] Merge the release PR branch. 112 | - [ ] Set the tag and run the following commands to push the tag. The tag must contain a message, otherwise the github action won't be able to create a release: 113 | 114 | ```bash 115 | TAG="v0.XX.0" 116 | git checkout main 117 | git pull 118 | git tag -a ${TAG} -m "${TAG}" 119 | git push origin ${TAG} 120 | ``` 121 | 122 | 123 | - [ ] After tag is pushed CI creates a GitHub draft release. 124 | This draft release will contain a binary for Linux and Mac and appear 125 | under [Releases](https://github.com/paritytech/substrate-contracts-node/releases). 126 | Add a description in the style of "Synchronized with [`polkadot-v1.8.0`](https://github.com/paritytech/polkadot-sdk/tree/release-polkadot-v1.8.0) branch." 127 | and publish it. 128 | -------------------------------------------------------------------------------- /node/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "contracts-node" 3 | version.workspace = true 4 | authors.workspace = true 5 | description = "Substrate node configured for smart contracts via `pallet-contracts` and `pallet-revive`." 6 | edition.workspace = true 7 | license.workspace = true 8 | build = "build.rs" 9 | homepage.workspace = true 10 | repository.workspace = true 11 | 12 | [package.metadata.docs.rs] 13 | targets = ["x86_64-unknown-linux-gnu"] 14 | 15 | [[bin]] 16 | name = "substrate-contracts-node" 17 | path = "src/main.rs" 18 | 19 | [dependencies] 20 | clap = { workspace = true } 21 | log = { workspace = true } 22 | codec = { workspace = true } 23 | serde = { workspace = true } 24 | jsonrpsee = { workspace = true } 25 | futures = { workspace = true } 26 | serde_json = { workspace = true } 27 | wasmtime = { workspace = true } 28 | 29 | # Local 30 | contracts-parachain-runtime = { path = "../parachain-runtime", features = [ 31 | "parachain", 32 | ], version = "0.42.0" } 33 | contracts-node-runtime = { path = "../runtime", version = "0.42.0" } 34 | 35 | # Substrate 36 | frame-benchmarking = { workspace = true } 37 | frame-benchmarking-cli = { workspace = true } 38 | pallet-transaction-payment-rpc = { workspace = true } 39 | sc-basic-authorship = { workspace = true } 40 | sc-chain-spec = { workspace = true } 41 | sc-cli = { workspace = true } 42 | sc-client-api = { workspace = true } 43 | sc-offchain = { workspace = true } 44 | sc-consensus = { workspace = true } 45 | sc-executor = { workspace = true } 46 | sc-network = { workspace = true } 47 | sc-network-sync = { workspace = true } 48 | sp-keyring = { workspace = true } 49 | sc-rpc = { workspace = true } 50 | sc-service = { workspace = true } 51 | sc-sysinfo = { workspace = true } 52 | sc-telemetry = { workspace = true } 53 | sc-tracing = { workspace = true } 54 | sc-transaction-pool = { workspace = true } 55 | sc-transaction-pool-api = { workspace = true } 56 | sp-api = { workspace = true } 57 | sp-block-builder = { workspace = true } 58 | sp-blockchain = { workspace = true } 59 | sp-consensus-aura = { workspace = true } 60 | sp-core = { workspace = true } 61 | sp-keystore = { workspace = true } 62 | sp-io = { workspace = true } 63 | sp-runtime = { workspace = true } 64 | sp-timestamp = { workspace = true } 65 | substrate-frame-rpc-system = { workspace = true } 66 | prometheus-endpoint = { workspace = true } 67 | try-runtime-cli = { workspace = true, optional = true } 68 | 69 | # extra for running solo-chain 70 | sp-consensus-grandpa = { workspace = true } 71 | sc-consensus-grandpa = { workspace = true } 72 | sc-consensus-aura = { workspace = true } 73 | sc-consensus-manual-seal = { workspace = true } 74 | 75 | # Polkadot 76 | polkadot-cli = { features = ["rococo-native"], workspace = true } 77 | polkadot-primitives = { workspace = true } 78 | xcm = { workspace = true } 79 | 80 | # Cumulus 81 | cumulus-client-cli = { workspace = true } 82 | cumulus-client-collator = { workspace = true } 83 | cumulus-client-consensus-aura = { workspace = true } 84 | cumulus-client-consensus-common = { workspace = true } 85 | cumulus-client-consensus-proposer = { workspace = true } 86 | cumulus-client-service = { workspace = true } 87 | cumulus-primitives-core = { workspace = true } 88 | cumulus-primitives-parachain-inherent = { workspace = true } 89 | cumulus-relay-chain-interface = { workspace = true } 90 | color-print = { workspace = true } 91 | 92 | [build-dependencies] 93 | substrate-build-script-utils = { workspace = true } 94 | 95 | [features] 96 | default = [] 97 | runtime-benchmarks = [ 98 | "contracts-parachain-runtime/runtime-benchmarks", 99 | "polkadot-cli/runtime-benchmarks", 100 | ] 101 | try-runtime = [ 102 | "try-runtime-cli/try-runtime", 103 | "contracts-parachain-runtime/try-runtime", 104 | ] 105 | -------------------------------------------------------------------------------- /node/build.rs: -------------------------------------------------------------------------------- 1 | use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; 2 | 3 | fn main() { 4 | generate_cargo_keys(); 5 | 6 | rerun_if_git_head_changed(); 7 | } 8 | -------------------------------------------------------------------------------- /node/src/chain_spec.rs: -------------------------------------------------------------------------------- 1 | pub mod dev; 2 | 3 | use contracts_parachain_runtime::{AccountId, AuraId, Signature, EXISTENTIAL_DEPOSIT}; 4 | use cumulus_primitives_core::ParaId; 5 | use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; 6 | use sc_service::ChainType; 7 | use serde::{Deserialize, Serialize}; 8 | use sp_core::{sr25519, Pair, Public}; 9 | use sp_runtime::traits::{IdentifyAccount, Verify}; 10 | 11 | /// Specialized `ChainSpec` for the normal parachain runtime. 12 | pub type ChainSpec = sc_service::GenericChainSpec; 13 | 14 | /// The default XCM version to set in genesis config. 15 | const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; 16 | 17 | /// Helper function to generate a crypto pair from seed 18 | pub fn get_from_seed(seed: &str) -> ::Public { 19 | TPublic::Pair::from_string(&format!("//{}", seed), None) 20 | .expect("static values are valid; qed") 21 | .public() 22 | } 23 | 24 | /// The extensions for the [`ChainSpec`]. 25 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] 26 | #[serde(deny_unknown_fields)] 27 | pub struct Extensions { 28 | /// The relay chain of the Parachain. 29 | #[serde(alias = "relayChain", alias = "RelayChain")] 30 | pub relay_chain: String, 31 | /// The id of the Parachain. 32 | #[serde(alias = "paraId", alias = "ParaId")] 33 | pub para_id: u32, 34 | } 35 | 36 | impl Extensions { 37 | /// Try to get the extension from the given `ChainSpec`. 38 | pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> { 39 | sc_chain_spec::get_extension(chain_spec.extensions()) 40 | } 41 | } 42 | 43 | type AccountPublic = ::Signer; 44 | 45 | /// Generate collator keys from seed. 46 | /// 47 | /// This function's return type must always match the session keys of the chain in tuple format. 48 | pub fn get_collator_keys_from_seed(seed: &str) -> AuraId { 49 | get_from_seed::(seed) 50 | } 51 | 52 | /// Helper function to generate an account ID from seed 53 | pub fn get_account_id_from_seed(seed: &str) -> AccountId 54 | where 55 | AccountPublic: From<::Public>, 56 | { 57 | AccountPublic::from(get_from_seed::(seed)).into_account() 58 | } 59 | 60 | /// Generate the session keys from individual elements. 61 | /// 62 | /// The input must be a tuple of individual keys (a single arg for now since we have just one key). 63 | pub fn template_session_keys(keys: AuraId) -> contracts_parachain_runtime::SessionKeys { 64 | contracts_parachain_runtime::SessionKeys { aura: keys } 65 | } 66 | 67 | pub fn local_testnet_config() -> ChainSpec { 68 | // Give your base currency a unit name and decimal places 69 | let mut properties = sc_chain_spec::Properties::new(); 70 | properties.insert("tokenSymbol".into(), "UNIT".into()); 71 | properties.insert("tokenDecimals".into(), 12.into()); 72 | properties.insert("ss58Format".into(), 42.into()); 73 | 74 | #[allow(deprecated)] 75 | ChainSpec::builder( 76 | contracts_parachain_runtime::WASM_BINARY 77 | .expect("WASM binary was not built, please build it!"), 78 | Extensions { 79 | relay_chain: "rococo-local".into(), 80 | // You MUST set this to the correct network! 81 | para_id: 1000, 82 | }, 83 | ) 84 | .with_name("Local Testnet") 85 | .with_id("local_testnet") 86 | .with_chain_type(ChainType::Local) 87 | .with_genesis_config_patch(testnet_genesis( 88 | // initial collators. 89 | vec![ 90 | ( 91 | get_account_id_from_seed::("Alice"), 92 | get_collator_keys_from_seed("Alice"), 93 | ), 94 | ( 95 | get_account_id_from_seed::("Bob"), 96 | get_collator_keys_from_seed("Bob"), 97 | ), 98 | ], 99 | vec![ 100 | get_account_id_from_seed::("Alice"), 101 | get_account_id_from_seed::("Bob"), 102 | get_account_id_from_seed::("Charlie"), 103 | get_account_id_from_seed::("Dave"), 104 | get_account_id_from_seed::("Eve"), 105 | get_account_id_from_seed::("Ferdie"), 106 | get_account_id_from_seed::("Alice//stash"), 107 | get_account_id_from_seed::("Bob//stash"), 108 | get_account_id_from_seed::("Charlie//stash"), 109 | get_account_id_from_seed::("Dave//stash"), 110 | get_account_id_from_seed::("Eve//stash"), 111 | get_account_id_from_seed::("Ferdie//stash"), 112 | ], 113 | get_account_id_from_seed::("Alice"), 114 | 1000.into(), 115 | )) 116 | .with_protocol_id("contracts-local") 117 | .with_properties(properties) 118 | .build() 119 | } 120 | 121 | fn testnet_genesis( 122 | invulnerables: Vec<(AccountId, AuraId)>, 123 | endowed_accounts: Vec, 124 | root: AccountId, 125 | id: ParaId, 126 | ) -> serde_json::Value { 127 | serde_json::json!({ 128 | "balances": { 129 | "balances": endowed_accounts.iter().cloned().map(|k| (k, 1u64 << 60)).collect::>(), 130 | }, 131 | "parachainInfo": { 132 | "parachainId": id, 133 | }, 134 | "collatorSelection": { 135 | "invulnerables": invulnerables.iter().cloned().map(|(acc, _)| acc).collect::>(), 136 | "candidacyBond": EXISTENTIAL_DEPOSIT * 16, 137 | }, 138 | "session": { 139 | "keys": invulnerables 140 | .into_iter() 141 | .map(|(acc, aura)| { 142 | ( 143 | acc.clone(), // account id 144 | acc, // validator id 145 | template_session_keys(aura), // session keys 146 | ) 147 | }) 148 | .collect::>(), 149 | }, 150 | "polkadotXcm": { 151 | "safeXcmVersion": Some(SAFE_XCM_VERSION), 152 | }, 153 | "sudo": { "key": Some(root) } 154 | }) 155 | } 156 | -------------------------------------------------------------------------------- /node/src/chain_spec/dev.rs: -------------------------------------------------------------------------------- 1 | use contracts_node_runtime::{AccountId, Signature, WASM_BINARY}; 2 | use sc_service::ChainType; 3 | use sp_core::{sr25519, Pair, Public}; 4 | use sp_runtime::traits::{IdentifyAccount, Verify}; 5 | 6 | /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. 7 | pub type ChainSpec = sc_service::GenericChainSpec; 8 | 9 | /// Generate a crypto pair from seed. 10 | pub fn get_from_seed(seed: &str) -> ::Public { 11 | TPublic::Pair::from_string(&format!("//{}", seed), None) 12 | .expect("static values are valid; qed") 13 | .public() 14 | } 15 | 16 | type AccountPublic = ::Signer; 17 | 18 | /// Generate an account ID from seed. 19 | pub fn get_account_id_from_seed(seed: &str) -> AccountId 20 | where 21 | AccountPublic: From<::Public>, 22 | { 23 | AccountPublic::from(get_from_seed::(seed)).into_account() 24 | } 25 | 26 | pub fn development_config() -> Result { 27 | Ok(ChainSpec::builder(WASM_BINARY.expect("Development wasm not available"), Default::default()) 28 | .with_name("Development") 29 | .with_id("dev") 30 | .with_chain_type(ChainType::Development) 31 | .with_genesis_config_patch(testnet_genesis( 32 | // Sudo account 33 | get_account_id_from_seed::("Alice"), 34 | // Pre-funded accounts 35 | vec![ 36 | get_account_id_from_seed::("Alice"), 37 | get_account_id_from_seed::("Alice//stash"), 38 | get_account_id_from_seed::("Bob"), 39 | get_account_id_from_seed::("Bob//stash"), 40 | get_account_id_from_seed::("Charlie"), 41 | get_account_id_from_seed::("Charlie//stash"), 42 | get_account_id_from_seed::("Dave"), 43 | get_account_id_from_seed::("Dave//stash"), 44 | get_account_id_from_seed::("Eve"), 45 | get_account_id_from_seed::("Eve//stash"), 46 | get_account_id_from_seed::("Ferdie"), 47 | get_account_id_from_seed::("Ferdie//stash"), 48 | ], 49 | true, 50 | )) 51 | .build()) 52 | } 53 | 54 | /// Configure initial storage state for FRAME modules. 55 | fn testnet_genesis( 56 | root_key: AccountId, 57 | endowed_accounts: Vec, 58 | _enable_println: bool, 59 | ) -> serde_json::Value { 60 | serde_json::json!({ 61 | "balances": { 62 | // Configure endowed accounts with initial balance of 1 << 60. 63 | "balances": endowed_accounts.iter().cloned().map(|k| (k, 1u64 << 60)).collect::>(), 64 | }, 65 | "sudo": { 66 | // Assign network admin rights. 67 | "key": Some(root_key), 68 | }, 69 | }) 70 | } 71 | -------------------------------------------------------------------------------- /node/src/cli.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | /// Sub-commands supported by the collator. 4 | #[derive(Debug, clap::Subcommand)] 5 | pub enum Subcommand { 6 | /// Build a chain specification. 7 | BuildSpec(sc_cli::BuildSpecCmd), 8 | 9 | /// Validate blocks. 10 | CheckBlock(sc_cli::CheckBlockCmd), 11 | 12 | /// Export blocks. 13 | ExportBlocks(sc_cli::ExportBlocksCmd), 14 | 15 | /// Export the state of a given block into a chain spec. 16 | ExportState(sc_cli::ExportStateCmd), 17 | 18 | /// Import blocks. 19 | ImportBlocks(sc_cli::ImportBlocksCmd), 20 | 21 | /// Revert the chain to a previous state. 22 | Revert(sc_cli::RevertCmd), 23 | 24 | /// Remove the whole chain. 25 | PurgeChain(cumulus_client_cli::PurgeChainCmd), 26 | 27 | /// Export the genesis state of the parachain. 28 | #[command(alias = "export-genesis-state")] 29 | ExportGenesisHead(cumulus_client_cli::ExportGenesisHeadCommand), 30 | 31 | /// Export the genesis wasm of the parachain. 32 | ExportGenesisWasm(cumulus_client_cli::ExportGenesisWasmCommand), 33 | 34 | /// Sub-commands concerned with benchmarking. 35 | /// The pallet benchmarking moved to the `pallet` sub-command. 36 | #[command(subcommand)] 37 | Benchmark(frame_benchmarking_cli::BenchmarkCmd), 38 | } 39 | 40 | const AFTER_HELP_EXAMPLE: &str = color_print::cstr!( 41 | r#"Examples: 42 | parachain-contracts-node build-spec --disable-default-bootnode > plain-parachain-chainspec.json 43 | Export a chainspec for a local testnet in json format. 44 | parachain-contracts-node --chain plain-parachain-chainspec.json --tmp -- --chain rococo-local 45 | Launch a full node with chain specification loaded from plain-parachain-chainspec.json. 46 | parachain-contracts-node 47 | Launch a full node with default parachain local-testnet and relay chain rococo-local. 48 | parachain-contracts-node --collator 49 | Launch a collator with default parachain local-testnet and relay chain rococo-local. 50 | "# 51 | ); 52 | #[derive(Debug, clap::Parser)] 53 | #[command( 54 | propagate_version = true, 55 | args_conflicts_with_subcommands = true, 56 | subcommand_negates_reqs = true 57 | )] 58 | #[clap(after_help = AFTER_HELP_EXAMPLE)] 59 | pub struct Cli { 60 | #[command(subcommand)] 61 | pub subcommand: Option, 62 | 63 | #[command(flatten)] 64 | pub run: cumulus_client_cli::RunCmd, 65 | 66 | /// Disable automatic hardware benchmarks. 67 | /// 68 | /// By default these benchmarks are automatically ran at startup and measure 69 | /// the CPU speed, the memory bandwidth and the disk speed. 70 | /// 71 | /// The results are then printed out in the logs, and also sent as part of 72 | /// telemetry, if telemetry is enabled. 73 | #[arg(long)] 74 | pub no_hardware_benchmarks: bool, 75 | 76 | /// Relay chain arguments 77 | #[arg(raw = true)] 78 | pub relay_chain_args: Vec, 79 | 80 | /// The number of seconds to delay before finalizing blocks. 81 | #[arg(long, default_value_t = 1)] 82 | pub finalize_delay_sec: u8, 83 | } 84 | 85 | #[derive(Debug)] 86 | pub struct RelayChainCli { 87 | /// The actual relay chain cli object. 88 | pub base: polkadot_cli::RunCmd, 89 | 90 | /// Optional chain id that should be passed to the relay chain. 91 | pub chain_id: Option, 92 | 93 | /// The base path that should be used by the relay chain. 94 | pub base_path: Option, 95 | } 96 | 97 | impl RelayChainCli { 98 | /// Parse the relay chain CLI parameters using the para chain `Configuration`. 99 | pub fn new<'a>( 100 | para_config: &sc_service::Configuration, 101 | relay_chain_args: impl Iterator, 102 | ) -> Self { 103 | let extension = crate::chain_spec::Extensions::try_get(&*para_config.chain_spec); 104 | let chain_id = extension.map(|e| e.relay_chain.clone()); 105 | let base_path = para_config.base_path.path().join("polkadot"); 106 | Self { 107 | base_path: Some(base_path), 108 | chain_id, 109 | base: clap::Parser::parse_from(relay_chain_args), 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /node/src/command.rs: -------------------------------------------------------------------------------- 1 | use contracts_parachain_runtime::Block; 2 | use cumulus_primitives_core::ParaId; 3 | use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE}; 4 | use log::info; 5 | use sc_cli::{ 6 | ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, 7 | NetworkParams, Result, RpcEndpoint, SharedParams, SubstrateCli, 8 | }; 9 | use sc_service::config::{BasePath, PrometheusConfig}; 10 | 11 | use crate::{ 12 | chain_spec, 13 | cli::{Cli, RelayChainCli, Subcommand}, 14 | service::{dev, new_partial}, 15 | }; 16 | 17 | fn load_spec(id: &str) -> std::result::Result, String> { 18 | Ok(match id { 19 | "" | "dev" => Box::new(chain_spec::dev::development_config()?), 20 | "contracts-parachain-local" => Box::new(chain_spec::local_testnet_config()), 21 | path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), 22 | }) 23 | } 24 | 25 | impl SubstrateCli for Cli { 26 | fn impl_name() -> String { 27 | "Substrate Contracts Node".into() 28 | } 29 | 30 | fn impl_version() -> String { 31 | env!("SUBSTRATE_CLI_IMPL_VERSION").into() 32 | } 33 | 34 | fn description() -> String { 35 | env!("CARGO_PKG_DESCRIPTION").into() 36 | } 37 | 38 | fn author() -> String { 39 | env!("CARGO_PKG_AUTHORS").into() 40 | } 41 | 42 | fn support_url() -> String { 43 | "https://github.com/paritytech/substrate-contracts-node/issues/new".into() 44 | } 45 | 46 | fn copyright_start_year() -> i32 { 47 | 2021 48 | } 49 | 50 | fn load_spec(&self, id: &str) -> std::result::Result, String> { 51 | load_spec(id) 52 | } 53 | } 54 | 55 | impl SubstrateCli for RelayChainCli { 56 | fn impl_name() -> String { 57 | "Substrate Contracts Node".into() 58 | } 59 | 60 | fn impl_version() -> String { 61 | env!("SUBSTRATE_CLI_IMPL_VERSION").into() 62 | } 63 | 64 | fn description() -> String { 65 | env!("CARGO_PKG_DESCRIPTION").into() 66 | } 67 | 68 | fn author() -> String { 69 | env!("CARGO_PKG_AUTHORS").into() 70 | } 71 | 72 | fn support_url() -> String { 73 | "https://github.com/paritytech/substrate-contracts-node/issues/new".into() 74 | } 75 | 76 | fn copyright_start_year() -> i32 { 77 | 2020 78 | } 79 | 80 | fn load_spec(&self, id: &str) -> std::result::Result, String> { 81 | polkadot_cli::Cli::from_iter([RelayChainCli::executable_name()].iter()).load_spec(id) 82 | } 83 | } 84 | 85 | macro_rules! construct_async_run { 86 | (|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{ 87 | let runner = $cli.create_runner($cmd)?; 88 | runner.async_run(|$config| { 89 | let $components = new_partial(&$config)?; 90 | let task_manager = $components.task_manager; 91 | { $( $code )* }.map(|v| (v, task_manager)) 92 | }) 93 | }} 94 | } 95 | 96 | /// Parse command line arguments into service configuration. 97 | pub fn run() -> Result<()> { 98 | let mut cli = Cli::from_args(); 99 | 100 | if cli.run.base.shared_params.chain.is_none() { 101 | log::debug!("forcing dev mode"); 102 | cli.run.base.shared_params.dev = true; 103 | } 104 | 105 | // remove block production noise and output contracts debug buffer by default 106 | if cli.run.base.shared_params.log.is_empty() { 107 | cli.run.base.shared_params.log = vec![ 108 | "runtime::contracts=debug".into(), 109 | "sc_cli=info".into(), 110 | "sc_rpc_server=info".into(), 111 | "warn".into(), 112 | ]; 113 | } 114 | 115 | match &cli.subcommand { 116 | Some(Subcommand::BuildSpec(cmd)) => { 117 | let runner = cli.create_runner(cmd)?; 118 | runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) 119 | }, 120 | Some(Subcommand::CheckBlock(cmd)) => { 121 | construct_async_run!(|components, cli, cmd, config| { 122 | Ok(cmd.run(components.client, components.import_queue)) 123 | }) 124 | }, 125 | Some(Subcommand::ExportBlocks(cmd)) => { 126 | construct_async_run!(|components, cli, cmd, config| { 127 | Ok(cmd.run(components.client, config.database)) 128 | }) 129 | }, 130 | Some(Subcommand::ExportState(cmd)) => { 131 | construct_async_run!(|components, cli, cmd, config| { 132 | Ok(cmd.run(components.client, config.chain_spec)) 133 | }) 134 | }, 135 | Some(Subcommand::ImportBlocks(cmd)) => { 136 | construct_async_run!(|components, cli, cmd, config| { 137 | Ok(cmd.run(components.client, components.import_queue)) 138 | }) 139 | }, 140 | Some(Subcommand::Revert(cmd)) => { 141 | construct_async_run!(|components, cli, cmd, config| { 142 | Ok(cmd.run(components.client, components.backend, None)) 143 | }) 144 | }, 145 | Some(Subcommand::PurgeChain(cmd)) => { 146 | let runner = cli.create_runner(cmd)?; 147 | 148 | runner.sync_run(|config| { 149 | let polkadot_cli = RelayChainCli::new( 150 | &config, 151 | [RelayChainCli::executable_name()].iter().chain(cli.relay_chain_args.iter()), 152 | ); 153 | 154 | let polkadot_config = SubstrateCli::create_configuration( 155 | &polkadot_cli, 156 | &polkadot_cli, 157 | config.tokio_handle.clone(), 158 | ) 159 | .map_err(|err| format!("Relay chain argument error: {}", err))?; 160 | 161 | cmd.run(config, polkadot_config) 162 | }) 163 | }, 164 | Some(Subcommand::ExportGenesisHead(cmd)) => { 165 | let runner = cli.create_runner(cmd)?; 166 | runner.sync_run(|config| { 167 | let partials = new_partial(&config)?; 168 | 169 | cmd.run(partials.client) 170 | }) 171 | }, 172 | Some(Subcommand::ExportGenesisWasm(cmd)) => { 173 | let runner = cli.create_runner(cmd)?; 174 | runner.sync_run(|_config| { 175 | let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; 176 | cmd.run(&*spec) 177 | }) 178 | }, 179 | Some(Subcommand::Benchmark(cmd)) => { 180 | let runner = cli.create_runner(cmd)?; 181 | // Switch on the concrete benchmark sub-command- 182 | match cmd { 183 | BenchmarkCmd::Pallet(cmd) => 184 | if cfg!(feature = "runtime-benchmarks") { 185 | runner.sync_run(|config| { 186 | cmd.run_with_spec::, ()>(Some( 187 | config.chain_spec, 188 | )) 189 | }) 190 | } else { 191 | Err("Benchmarking wasn't enabled when building the node. \ 192 | You can enable it with `--features runtime-benchmarks`." 193 | .into()) 194 | }, 195 | BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { 196 | let partials = new_partial(&config)?; 197 | cmd.run(partials.client) 198 | }), 199 | #[cfg(not(feature = "runtime-benchmarks"))] 200 | BenchmarkCmd::Storage(_) => Err(sc_cli::Error::Input( 201 | "Compile with --features=runtime-benchmarks \ 202 | to enable storage benchmarks." 203 | .into(), 204 | )), 205 | #[cfg(feature = "runtime-benchmarks")] 206 | BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { 207 | let partials = new_partial(&config)?; 208 | let db = partials.backend.expose_db(); 209 | let storage = partials.backend.expose_storage(); 210 | cmd.run(config, partials.client.clone(), db, storage) 211 | }), 212 | BenchmarkCmd::Machine(cmd) => 213 | runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())), 214 | // NOTE: this allows the Client to leniently implement 215 | // new benchmark commands without requiring a companion MR. 216 | #[allow(unreachable_patterns)] 217 | _ => Err("Benchmarking sub-command unsupported".into()), 218 | } 219 | }, 220 | None => { 221 | let runner = cli.create_runner(&cli.run.normalize())?; 222 | let collator_options = cli.run.collator_options(); 223 | 224 | runner.run_node_until_exit(|config| async move { 225 | if config.chain_spec.name() == "Development" { 226 | return dev::new_full::>( 227 | config, 228 | cli.finalize_delay_sec.into(), 229 | ) 230 | .map_err(sc_cli::Error::Service); 231 | } 232 | 233 | let hwbench = (!cli.no_hardware_benchmarks) 234 | .then_some(config.database.path().map(|database_path| { 235 | let _ = std::fs::create_dir_all(database_path); 236 | sc_sysinfo::gather_hwbench( 237 | Some(database_path), 238 | &SUBSTRATE_REFERENCE_HARDWARE, 239 | ) 240 | })) 241 | .flatten(); 242 | 243 | let para_id = chain_spec::Extensions::try_get(&*config.chain_spec) 244 | .map(|e| e.para_id) 245 | .ok_or("Could not find parachain ID in chain-spec.")?; 246 | 247 | let polkadot_cli = RelayChainCli::new( 248 | &config, 249 | [RelayChainCli::executable_name()].iter().chain(cli.relay_chain_args.iter()), 250 | ); 251 | 252 | let id = ParaId::from(para_id); 253 | 254 | let tokio_handle = config.tokio_handle.clone(); 255 | let polkadot_config = 256 | SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, tokio_handle) 257 | .map_err(|err| format!("Relay chain argument error: {}", err))?; 258 | 259 | info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); 260 | 261 | crate::service::start_parachain_node( 262 | config, 263 | polkadot_config, 264 | collator_options, 265 | id, 266 | hwbench, 267 | ) 268 | .await 269 | .map(|r| r.0) 270 | .map_err(Into::into) 271 | }) 272 | }, 273 | } 274 | } 275 | 276 | impl DefaultConfigurationValues for RelayChainCli { 277 | fn p2p_listen_port() -> u16 { 278 | 30334 279 | } 280 | 281 | fn rpc_listen_port() -> u16 { 282 | 9945 283 | } 284 | 285 | fn prometheus_listen_port() -> u16 { 286 | 9616 287 | } 288 | } 289 | 290 | impl CliConfiguration for RelayChainCli { 291 | fn shared_params(&self) -> &SharedParams { 292 | self.base.base.shared_params() 293 | } 294 | 295 | fn import_params(&self) -> Option<&ImportParams> { 296 | self.base.base.import_params() 297 | } 298 | 299 | fn network_params(&self) -> Option<&NetworkParams> { 300 | self.base.base.network_params() 301 | } 302 | 303 | fn keystore_params(&self) -> Option<&KeystoreParams> { 304 | self.base.base.keystore_params() 305 | } 306 | 307 | fn base_path(&self) -> Result> { 308 | Ok(self 309 | .shared_params() 310 | .base_path()? 311 | .or_else(|| self.base_path.clone().map(Into::into))) 312 | } 313 | 314 | fn rpc_addr(&self, default_listen_port: u16) -> Result>> { 315 | self.base.base.rpc_addr(default_listen_port) 316 | } 317 | 318 | fn prometheus_config( 319 | &self, 320 | default_listen_port: u16, 321 | chain_spec: &Box, 322 | ) -> Result> { 323 | self.base.base.prometheus_config(default_listen_port, chain_spec) 324 | } 325 | 326 | fn init(&self, _support_url: &String, _impl_version: &String, _logger_hook: F) -> Result<()> 327 | where 328 | F: FnOnce(&mut sc_cli::LoggerBuilder), 329 | { 330 | unreachable!("PolkadotCli is never initialized; qed"); 331 | } 332 | 333 | fn chain_id(&self, is_dev: bool) -> Result { 334 | let chain_id = self.base.base.chain_id(is_dev)?; 335 | 336 | Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id }) 337 | } 338 | 339 | fn role(&self, is_dev: bool) -> Result { 340 | self.base.base.role(is_dev) 341 | } 342 | 343 | fn transaction_pool(&self, is_dev: bool) -> Result { 344 | self.base.base.transaction_pool(is_dev) 345 | } 346 | 347 | fn trie_cache_maximum_size(&self) -> Result> { 348 | self.base.base.trie_cache_maximum_size() 349 | } 350 | 351 | fn rpc_methods(&self) -> Result { 352 | self.base.base.rpc_methods() 353 | } 354 | 355 | fn rpc_max_connections(&self) -> Result { 356 | self.base.base.rpc_max_connections() 357 | } 358 | 359 | fn rpc_cors(&self, is_dev: bool) -> Result>> { 360 | self.base.base.rpc_cors(is_dev) 361 | } 362 | 363 | fn default_heap_pages(&self) -> Result> { 364 | self.base.base.default_heap_pages() 365 | } 366 | 367 | fn force_authoring(&self) -> Result { 368 | self.base.base.force_authoring() 369 | } 370 | 371 | fn disable_grandpa(&self) -> Result { 372 | self.base.base.disable_grandpa() 373 | } 374 | 375 | fn max_runtime_instances(&self) -> Result> { 376 | self.base.base.max_runtime_instances() 377 | } 378 | 379 | fn announce_block(&self) -> Result { 380 | self.base.base.announce_block() 381 | } 382 | 383 | fn telemetry_endpoints( 384 | &self, 385 | chain_spec: &Box, 386 | ) -> Result> { 387 | self.base.base.telemetry_endpoints(chain_spec) 388 | } 389 | 390 | fn node_name(&self) -> Result { 391 | self.base.base.node_name() 392 | } 393 | } 394 | -------------------------------------------------------------------------------- /node/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Substrate Parachain Node Template CLI 2 | 3 | #![warn(missing_docs)] 4 | 5 | mod chain_spec; 6 | #[macro_use] 7 | mod service; 8 | mod cli; 9 | mod command; 10 | mod rpc; 11 | 12 | fn main() -> sc_cli::Result<()> { 13 | command::run() 14 | } 15 | -------------------------------------------------------------------------------- /node/src/rpc.rs: -------------------------------------------------------------------------------- 1 | //! A collection of node-specific RPC methods. 2 | //! Substrate provides the `sc-rpc` crate, which defines the core RPC layer 3 | //! used by Substrate nodes. This file extends those RPC definitions with 4 | //! capabilities that are specific to this project's runtime configuration. 5 | 6 | #![warn(missing_docs)] 7 | 8 | use std::sync::Arc; 9 | 10 | use contracts_parachain_runtime::{opaque::Block, AccountId, Balance, Nonce}; 11 | 12 | use sc_transaction_pool_api::TransactionPool; 13 | use sp_api::ProvideRuntimeApi; 14 | use sp_block_builder::BlockBuilder; 15 | use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; 16 | 17 | /// A type representing all RPC extensions. 18 | pub type RpcExtension = jsonrpsee::RpcModule<()>; 19 | 20 | /// Full client dependencies 21 | pub struct FullDeps { 22 | /// The client instance to use. 23 | pub client: Arc, 24 | /// Transaction pool instance. 25 | pub pool: Arc

, 26 | } 27 | 28 | /// Instantiate all RPC extensions. 29 | pub fn create_full( 30 | deps: FullDeps, 31 | ) -> Result> 32 | where 33 | C: ProvideRuntimeApi 34 | + HeaderBackend 35 | + HeaderMetadata 36 | + Send 37 | + Sync 38 | + 'static, 39 | C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, 40 | C::Api: substrate_frame_rpc_system::AccountNonceApi, 41 | C::Api: BlockBuilder, 42 | P: TransactionPool + Sync + Send + 'static, 43 | { 44 | use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; 45 | use substrate_frame_rpc_system::{System, SystemApiServer}; 46 | 47 | let mut module = RpcExtension::new(()); 48 | let FullDeps { client, pool } = deps; 49 | 50 | module.merge(System::new(client.clone(), pool).into_rpc())?; 51 | module.merge(TransactionPayment::new(client).into_rpc())?; 52 | Ok(module) 53 | } 54 | -------------------------------------------------------------------------------- /node/src/service.rs: -------------------------------------------------------------------------------- 1 | //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. 2 | 3 | pub mod dev; 4 | 5 | // std 6 | use std::{sync::Arc, time::Duration}; 7 | 8 | use cumulus_client_cli::CollatorOptions; 9 | // Local Runtime Types 10 | use contracts_parachain_runtime::{ 11 | opaque::{Block, Hash}, 12 | RuntimeApi, 13 | }; 14 | // Cumulus Imports 15 | use cumulus_client_collator::service::CollatorService; 16 | use cumulus_client_consensus_aura::collators::lookahead::{self as aura, Params as AuraParams}; 17 | use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImport; 18 | use cumulus_client_consensus_proposer::Proposer; 19 | use cumulus_client_service::{ 20 | build_network, build_relay_chain_interface, prepare_node_config, start_relay_chain_tasks, 21 | BuildNetworkParams, CollatorSybilResistance, DARecoveryProfile, ParachainHostFunctions, 22 | StartRelayChainTasksParams, 23 | }; 24 | use cumulus_primitives_core::{ 25 | relay_chain::{CollatorPair, ValidationCode}, 26 | ParaId, 27 | }; 28 | use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface}; 29 | 30 | // Substrate Imports 31 | use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE; 32 | use prometheus_endpoint::Registry; 33 | use sc_client_api::Backend; 34 | use sc_consensus::ImportQueue; 35 | use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY}; 36 | use sc_network::NetworkBlock; 37 | use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; 38 | use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; 39 | use sc_transaction_pool_api::OffchainTransactionPoolFactory; 40 | use sp_keystore::KeystorePtr; 41 | 42 | type ParachainExecutor = WasmExecutor; 43 | 44 | type ParachainClient = TFullClient; 45 | 46 | type ParachainBackend = TFullBackend; 47 | 48 | type ParachainBlockImport = TParachainBlockImport, ParachainBackend>; 49 | 50 | /// Assembly of PartialComponents (enough to run chain ops subcommands) 51 | pub type Service = PartialComponents< 52 | ParachainClient, 53 | ParachainBackend, 54 | (), 55 | sc_consensus::DefaultImportQueue, 56 | sc_transaction_pool::FullPool, 57 | (ParachainBlockImport, Option, Option), 58 | >; 59 | 60 | /// Starts a `ServiceBuilder` for a full service. 61 | /// 62 | /// Use this macro if you don't actually need the full service, but just the builder in order to 63 | /// be able to perform chain operations. 64 | pub fn new_partial(config: &Configuration) -> Result { 65 | let telemetry = config 66 | .telemetry_endpoints 67 | .clone() 68 | .filter(|x| !x.is_empty()) 69 | .map(|endpoints| -> Result<_, sc_telemetry::Error> { 70 | let worker = TelemetryWorker::new(16)?; 71 | let telemetry = worker.handle().new_telemetry(endpoints); 72 | Ok((worker, telemetry)) 73 | }) 74 | .transpose()?; 75 | 76 | let heap_pages = config 77 | .executor 78 | .default_heap_pages 79 | .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ }); 80 | 81 | let executor = ParachainExecutor::builder() 82 | .with_execution_method(config.executor.wasm_method) 83 | .with_onchain_heap_alloc_strategy(heap_pages) 84 | .with_offchain_heap_alloc_strategy(heap_pages) 85 | .with_max_runtime_instances(config.executor.max_runtime_instances) 86 | .with_runtime_cache_size(config.executor.runtime_cache_size) 87 | .build(); 88 | 89 | let (client, backend, keystore_container, task_manager) = 90 | sc_service::new_full_parts_record_import::( 91 | config, 92 | telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), 93 | executor, 94 | true, 95 | )?; 96 | let client = Arc::new(client); 97 | 98 | let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); 99 | 100 | let telemetry = telemetry.map(|(worker, telemetry)| { 101 | task_manager.spawn_handle().spawn("telemetry", None, worker.run()); 102 | telemetry 103 | }); 104 | 105 | let transaction_pool = sc_transaction_pool::BasicPool::new_full( 106 | config.transaction_pool.clone(), 107 | config.role.is_authority().into(), 108 | config.prometheus_registry(), 109 | task_manager.spawn_essential_handle(), 110 | client.clone(), 111 | ); 112 | 113 | let block_import = ParachainBlockImport::new(client.clone(), backend.clone()); 114 | 115 | let import_queue = build_import_queue( 116 | client.clone(), 117 | block_import.clone(), 118 | config, 119 | telemetry.as_ref().map(|telemetry| telemetry.handle()), 120 | &task_manager, 121 | ); 122 | 123 | Ok(PartialComponents { 124 | backend, 125 | client, 126 | import_queue, 127 | keystore_container, 128 | task_manager, 129 | transaction_pool, 130 | select_chain: (), 131 | other: (block_import, telemetry, telemetry_worker_handle), 132 | }) 133 | } 134 | 135 | /// Build the import queue for the parachain runtime. 136 | fn build_import_queue( 137 | client: Arc, 138 | block_import: ParachainBlockImport, 139 | config: &Configuration, 140 | telemetry: Option, 141 | task_manager: &TaskManager, 142 | ) -> sc_consensus::DefaultImportQueue { 143 | cumulus_client_consensus_aura::equivocation_import_queue::fully_verifying_import_queue::< 144 | sp_consensus_aura::sr25519::AuthorityPair, 145 | _, 146 | _, 147 | _, 148 | _, 149 | >( 150 | client, 151 | block_import, 152 | move |_, _| async move { 153 | let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); 154 | Ok(timestamp) 155 | }, 156 | &task_manager.spawn_essential_handle(), 157 | config.prometheus_registry(), 158 | telemetry, 159 | ) 160 | } 161 | 162 | #[allow(clippy::too_many_arguments)] 163 | fn start_consensus( 164 | client: Arc, 165 | backend: Arc, 166 | block_import: ParachainBlockImport, 167 | prometheus_registry: Option<&Registry>, 168 | telemetry: Option, 169 | task_manager: &TaskManager, 170 | relay_chain_interface: Arc, 171 | transaction_pool: Arc>, 172 | keystore: KeystorePtr, 173 | relay_chain_slot_duration: Duration, 174 | para_id: ParaId, 175 | collator_key: CollatorPair, 176 | overseer_handle: OverseerHandle, 177 | announce_block: Arc>) + Send + Sync>, 178 | ) -> Result<(), sc_service::Error> { 179 | let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( 180 | task_manager.spawn_handle(), 181 | client.clone(), 182 | transaction_pool, 183 | prometheus_registry, 184 | telemetry.clone(), 185 | ); 186 | 187 | let proposer = Proposer::new(proposer_factory); 188 | 189 | let collator_service = CollatorService::new( 190 | client.clone(), 191 | Arc::new(task_manager.spawn_handle()), 192 | announce_block, 193 | client.clone(), 194 | ); 195 | 196 | let params = AuraParams { 197 | create_inherent_data_providers: move |_, ()| async move { Ok(()) }, 198 | block_import, 199 | para_client: client.clone(), 200 | para_backend: backend, 201 | relay_client: relay_chain_interface, 202 | code_hash_provider: move |block_hash| { 203 | client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) 204 | }, 205 | keystore, 206 | collator_key, 207 | para_id, 208 | overseer_handle, 209 | relay_chain_slot_duration, 210 | proposer, 211 | collator_service, 212 | authoring_duration: Duration::from_millis(2000), 213 | reinitialize: false, 214 | }; 215 | 216 | let fut = aura::run::( 217 | params, 218 | ); 219 | task_manager.spawn_essential_handle().spawn("aura", None, fut); 220 | 221 | Ok(()) 222 | } 223 | 224 | /// Start a node with the given parachain `Configuration` and relay chain `Configuration`. 225 | #[sc_tracing::logging::prefix_logs_with("Parachain")] 226 | pub async fn start_parachain_node( 227 | parachain_config: Configuration, 228 | polkadot_config: Configuration, 229 | collator_options: CollatorOptions, 230 | para_id: ParaId, 231 | hwbench: Option, 232 | ) -> sc_service::error::Result<(TaskManager, Arc)> { 233 | let parachain_config = prepare_node_config(parachain_config); 234 | 235 | let params = new_partial(¶chain_config)?; 236 | let (block_import, mut telemetry, telemetry_worker_handle) = params.other; 237 | let prometheus_registry = parachain_config.prometheus_registry().cloned(); 238 | let net_config = sc_network::config::FullNetworkConfiguration::< 239 | _, 240 | _, 241 | sc_network::NetworkWorker, 242 | >::new(¶chain_config.network, prometheus_registry.clone()); 243 | 244 | let client = params.client.clone(); 245 | let backend = params.backend.clone(); 246 | let mut task_manager = params.task_manager; 247 | 248 | let (relay_chain_interface, collator_key) = build_relay_chain_interface( 249 | polkadot_config, 250 | ¶chain_config, 251 | telemetry_worker_handle, 252 | &mut task_manager, 253 | collator_options.clone(), 254 | hwbench.clone(), 255 | ) 256 | .await 257 | .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?; 258 | 259 | let validator = parachain_config.role.is_authority(); 260 | let transaction_pool = params.transaction_pool.clone(); 261 | let import_queue_service = params.import_queue.service(); 262 | 263 | // NOTE: because we use Aura here explicitly, we can use `CollatorSybilResistance::Resistant` 264 | // when starting the network. 265 | let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = 266 | build_network(BuildNetworkParams { 267 | parachain_config: ¶chain_config, 268 | net_config, 269 | client: client.clone(), 270 | transaction_pool: transaction_pool.clone(), 271 | para_id, 272 | spawn_handle: task_manager.spawn_handle(), 273 | relay_chain_interface: relay_chain_interface.clone(), 274 | import_queue: params.import_queue, 275 | sybil_resistance_level: CollatorSybilResistance::Resistant, // because of Aura 276 | }) 277 | .await?; 278 | 279 | if parachain_config.offchain_worker.enabled { 280 | use futures::FutureExt; 281 | 282 | task_manager.spawn_handle().spawn( 283 | "offchain-workers-runner", 284 | "offchain-work", 285 | sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { 286 | runtime_api_provider: client.clone(), 287 | keystore: Some(params.keystore_container.keystore()), 288 | offchain_db: backend.offchain_storage(), 289 | transaction_pool: Some(OffchainTransactionPoolFactory::new( 290 | transaction_pool.clone(), 291 | )), 292 | network_provider: Arc::new(network.clone()), 293 | is_validator: parachain_config.role.is_authority(), 294 | enable_http_requests: false, 295 | custom_extensions: move |_| vec![], 296 | }) 297 | .run(client.clone(), task_manager.spawn_handle()) 298 | .boxed(), 299 | ); 300 | } 301 | 302 | let rpc_builder = { 303 | let client = client.clone(); 304 | let transaction_pool = transaction_pool.clone(); 305 | 306 | Box::new(move |_| { 307 | let deps = 308 | crate::rpc::FullDeps { client: client.clone(), pool: transaction_pool.clone() }; 309 | 310 | crate::rpc::create_full(deps).map_err(Into::into) 311 | }) 312 | }; 313 | 314 | sc_service::spawn_tasks(sc_service::SpawnTasksParams { 315 | rpc_builder, 316 | client: client.clone(), 317 | transaction_pool: transaction_pool.clone(), 318 | task_manager: &mut task_manager, 319 | config: parachain_config, 320 | keystore: params.keystore_container.keystore(), 321 | backend: backend.clone(), 322 | network, 323 | sync_service: sync_service.clone(), 324 | system_rpc_tx, 325 | tx_handler_controller, 326 | telemetry: telemetry.as_mut(), 327 | })?; 328 | 329 | if let Some(hwbench) = hwbench { 330 | sc_sysinfo::print_hwbench(&hwbench); 331 | // Here you can check whether the hardware meets your chains' requirements. Putting a link 332 | // in there and swapping out the requirements for your own are probably a good idea. The 333 | // requirements for a para-chain are dictated by its relay-chain. 334 | match SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench, false) { 335 | Err(err) if validator => { 336 | log::warn!( 337 | "⚠️ The hardware does not meet the minimal requirements {} for role 'Authority'.", 338 | err 339 | ); 340 | }, 341 | _ => {}, 342 | } 343 | 344 | if let Some(ref mut telemetry) = telemetry { 345 | let telemetry_handle = telemetry.handle(); 346 | task_manager.spawn_handle().spawn( 347 | "telemetry_hwbench", 348 | None, 349 | sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench), 350 | ); 351 | } 352 | } 353 | 354 | let announce_block = { 355 | let sync_service = sync_service.clone(); 356 | Arc::new(move |hash, data| sync_service.announce_block(hash, data)) 357 | }; 358 | 359 | let relay_chain_slot_duration = Duration::from_secs(6); 360 | 361 | let overseer_handle = relay_chain_interface 362 | .overseer_handle() 363 | .map_err(|e| sc_service::Error::Application(Box::new(e)))?; 364 | 365 | start_relay_chain_tasks(StartRelayChainTasksParams { 366 | client: client.clone(), 367 | announce_block: announce_block.clone(), 368 | para_id, 369 | relay_chain_interface: relay_chain_interface.clone(), 370 | task_manager: &mut task_manager, 371 | da_recovery_profile: if validator { 372 | DARecoveryProfile::Collator 373 | } else { 374 | DARecoveryProfile::FullNode 375 | }, 376 | import_queue: import_queue_service, 377 | relay_chain_slot_duration, 378 | recovery_handle: Box::new(overseer_handle.clone()), 379 | sync_service: sync_service.clone(), 380 | })?; 381 | 382 | if validator { 383 | start_consensus( 384 | client.clone(), 385 | backend, 386 | block_import, 387 | prometheus_registry.as_ref(), 388 | telemetry.as_ref().map(|t| t.handle()), 389 | &task_manager, 390 | relay_chain_interface, 391 | transaction_pool, 392 | params.keystore_container.keystore(), 393 | relay_chain_slot_duration, 394 | para_id, 395 | collator_key.expect("Command line arguments do not allow this. qed"), 396 | overseer_handle, 397 | announce_block, 398 | )?; 399 | } 400 | 401 | start_network.start_network(); 402 | 403 | Ok((task_manager, client)) 404 | } 405 | -------------------------------------------------------------------------------- /node/src/service/dev.rs: -------------------------------------------------------------------------------- 1 | //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. 2 | 3 | use contracts_node_runtime::{self, opaque::Block, RuntimeApi}; 4 | use futures::FutureExt; 5 | use sc_client_api::Backend; 6 | use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; 7 | use sc_telemetry::{Telemetry, TelemetryWorker}; 8 | use sc_transaction_pool_api::OffchainTransactionPoolFactory; 9 | use std::sync::Arc; 10 | 11 | pub(crate) type FullClient = sc_service::TFullClient< 12 | Block, 13 | RuntimeApi, 14 | sc_executor::WasmExecutor, 15 | >; 16 | type FullBackend = sc_service::TFullBackend; 17 | type FullSelectChain = sc_consensus::LongestChain; 18 | 19 | pub fn new_partial( 20 | config: &Configuration, 21 | ) -> Result< 22 | sc_service::PartialComponents< 23 | FullClient, 24 | FullBackend, 25 | FullSelectChain, 26 | sc_consensus::DefaultImportQueue, 27 | sc_transaction_pool::FullPool, 28 | Option, 29 | >, 30 | ServiceError, 31 | > { 32 | let telemetry = config 33 | .telemetry_endpoints 34 | .clone() 35 | .filter(|x| !x.is_empty()) 36 | .map(|endpoints| -> Result<_, sc_telemetry::Error> { 37 | let worker = TelemetryWorker::new(16)?; 38 | let telemetry = worker.handle().new_telemetry(endpoints); 39 | Ok((worker, telemetry)) 40 | }) 41 | .transpose()?; 42 | 43 | let executor = sc_service::new_wasm_executor(&config.executor); 44 | 45 | let (client, backend, keystore_container, task_manager) = 46 | sc_service::new_full_parts::( 47 | config, 48 | telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), 49 | executor, 50 | )?; 51 | let client = Arc::new(client); 52 | 53 | let select_chain = sc_consensus::LongestChain::new(backend.clone()); 54 | 55 | let telemetry = telemetry.map(|(worker, telemetry)| { 56 | task_manager.spawn_handle().spawn("telemetry", None, worker.run()); 57 | telemetry 58 | }); 59 | 60 | let import_queue = sc_consensus_manual_seal::import_queue( 61 | Box::new(client.clone()), 62 | &task_manager.spawn_essential_handle(), 63 | config.prometheus_registry(), 64 | ); 65 | 66 | let transaction_pool = sc_transaction_pool::BasicPool::new_full( 67 | config.transaction_pool.clone(), 68 | config.role.is_authority().into(), 69 | config.prometheus_registry(), 70 | task_manager.spawn_essential_handle(), 71 | client.clone(), 72 | ); 73 | 74 | Ok(sc_service::PartialComponents { 75 | client, 76 | backend, 77 | task_manager, 78 | import_queue, 79 | keystore_container, 80 | select_chain, 81 | transaction_pool, 82 | other: (telemetry), 83 | }) 84 | } 85 | 86 | pub fn new_full< 87 | N: sc_network::NetworkBackend::Hash>, 88 | >( 89 | config: Configuration, 90 | finalize_delay_sec: u64, 91 | ) -> Result { 92 | let sc_service::PartialComponents { 93 | client, 94 | backend, 95 | mut task_manager, 96 | import_queue, 97 | keystore_container, 98 | select_chain, 99 | transaction_pool, 100 | other: mut telemetry, 101 | } = new_partial(&config)?; 102 | 103 | let net_config = 104 | sc_network::config::FullNetworkConfiguration::< 105 | Block, 106 | ::Hash, 107 | N, 108 | >::new(&config.network, config.prometheus_config.as_ref().map(|cfg| cfg.registry.clone())); 109 | let metrics = N::register_notification_metrics(config.prometheus_registry()); 110 | 111 | let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = 112 | sc_service::build_network(sc_service::BuildNetworkParams { 113 | config: &config, 114 | client: client.clone(), 115 | transaction_pool: transaction_pool.clone(), 116 | spawn_handle: task_manager.spawn_handle(), 117 | import_queue, 118 | net_config, 119 | block_announce_validator_builder: None, 120 | warp_sync_config: None, 121 | block_relay: None, 122 | metrics, 123 | })?; 124 | 125 | if config.offchain_worker.enabled { 126 | task_manager.spawn_handle().spawn( 127 | "offchain-workers-runner", 128 | "offchain-worker", 129 | sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { 130 | runtime_api_provider: client.clone(), 131 | is_validator: config.role.is_authority(), 132 | keystore: Some(keystore_container.keystore()), 133 | offchain_db: backend.offchain_storage(), 134 | transaction_pool: Some(OffchainTransactionPoolFactory::new( 135 | transaction_pool.clone(), 136 | )), 137 | network_provider: Arc::new(network.clone()), 138 | enable_http_requests: true, 139 | custom_extensions: |_| vec![], 140 | }) 141 | .run(client.clone(), task_manager.spawn_handle()) 142 | .boxed(), 143 | ); 144 | } 145 | 146 | let prometheus_registry = config.prometheus_registry().cloned(); 147 | let rpc_extensions_builder = { 148 | let client = client.clone(); 149 | let pool = transaction_pool.clone(); 150 | 151 | Box::new(move |_| { 152 | let deps = crate::rpc::FullDeps { client: client.clone(), pool: pool.clone() }; 153 | crate::rpc::create_full(deps).map_err(Into::into) 154 | }) 155 | }; 156 | 157 | let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { 158 | network, 159 | client: client.clone(), 160 | keystore: keystore_container.keystore(), 161 | task_manager: &mut task_manager, 162 | transaction_pool: transaction_pool.clone(), 163 | rpc_builder: rpc_extensions_builder, 164 | backend, 165 | system_rpc_tx, 166 | tx_handler_controller, 167 | sync_service, 168 | config, 169 | telemetry: telemetry.as_mut(), 170 | })?; 171 | 172 | let proposer = sc_basic_authorship::ProposerFactory::new( 173 | task_manager.spawn_handle(), 174 | client.clone(), 175 | transaction_pool.clone(), 176 | prometheus_registry.as_ref(), 177 | telemetry.as_ref().map(|x| x.handle()), 178 | ); 179 | 180 | let params = sc_consensus_manual_seal::InstantSealParams { 181 | block_import: client.clone(), 182 | env: proposer, 183 | client: client.clone(), 184 | pool: transaction_pool, 185 | select_chain, 186 | consensus_data_provider: None, 187 | create_inherent_data_providers: move |_, ()| async move { 188 | Ok(sp_timestamp::InherentDataProvider::from_system_time()) 189 | }, 190 | }; 191 | 192 | let authorship_future = sc_consensus_manual_seal::run_instant_seal(params); 193 | task_manager 194 | .spawn_essential_handle() 195 | .spawn_blocking("instant-seal", None, authorship_future); 196 | 197 | let delayed_finalize_params = sc_consensus_manual_seal::DelayedFinalizeParams { 198 | client, 199 | spawn_handle: task_manager.spawn_handle(), 200 | delay_sec: finalize_delay_sec, 201 | }; 202 | task_manager.spawn_essential_handle().spawn_blocking( 203 | "delayed_finalize", 204 | None, 205 | sc_consensus_manual_seal::run_delayed_finalize(delayed_finalize_params), 206 | ); 207 | 208 | network_starter.start_network(); 209 | Ok(task_manager) 210 | } 211 | -------------------------------------------------------------------------------- /parachain-runtime/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "contracts-parachain-runtime" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | description = "Parachain Runtime configured for smart contracts via `pallet-contracts` and `pallet-revive`." 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | 11 | [package.metadata.docs.rs] 12 | targets = ["x86_64-unknown-linux-gnu"] 13 | [build-dependencies] 14 | substrate-wasm-builder = { workspace = true, optional = true } 15 | 16 | [dependencies] 17 | codec = { features = ["derive"], workspace = true } 18 | hex-literal = { version = "0.4.1", optional = true } 19 | log = { version = "0.4.21", default-features = false } 20 | scale-info = { workspace = true } 21 | smallvec = "1.11.2" 22 | 23 | # Substrate 24 | frame-benchmarking = { workspace = true, optional = true } 25 | frame-executive = { workspace = true } 26 | frame-support = { workspace = true } 27 | frame-system = { workspace = true } 28 | frame-system-benchmarking = { workspace = true, optional = true } 29 | frame-system-rpc-runtime-api = { workspace = true } 30 | frame-try-runtime = { workspace = true, optional = true } 31 | pallet-aura = { workspace = true } 32 | pallet-authorship = { workspace = true } 33 | pallet-balances = { workspace = true } 34 | pallet-session = { workspace = true } 35 | pallet-message-queue = { workspace = true } 36 | pallet-sudo = { workspace = true } 37 | pallet-timestamp = { workspace = true } 38 | pallet-transaction-payment = { workspace = true } 39 | pallet-transaction-payment-rpc-runtime-api = { workspace = true } 40 | sp-api = { workspace = true } 41 | sp-block-builder = { workspace = true } 42 | sp-consensus-aura = { workspace = true } 43 | sp-core = { workspace = true } 44 | sp-inherents = { workspace = true } 45 | sp-offchain = { workspace = true } 46 | sp-runtime = { workspace = true } 47 | sp-session = { workspace = true } 48 | sp-std = { workspace = true } 49 | sp-transaction-pool = { workspace = true } 50 | sp-version = { workspace = true } 51 | sp-genesis-builder = { workspace = true } 52 | 53 | # Polkadot 54 | pallet-xcm = { workspace = true } 55 | polkadot-parachain-primitives = { workspace = true } 56 | polkadot-runtime-common = { workspace = true } 57 | xcm = { workspace = true } 58 | xcm-builder = { workspace = true } 59 | xcm-executor = { workspace = true } 60 | 61 | # Cumulus 62 | cumulus-pallet-aura-ext = { workspace = true } 63 | cumulus-pallet-dmp-queue = { workspace = true } 64 | cumulus-pallet-parachain-system = { workspace = true } 65 | cumulus-pallet-session-benchmarking = { workspace = true } 66 | cumulus-pallet-xcm = { workspace = true } 67 | cumulus-pallet-xcmp-queue = { workspace = true } 68 | cumulus-primitives-aura = { workspace = true } 69 | cumulus-primitives-core = { workspace = true } 70 | cumulus-primitives-timestamp = { workspace = true } 71 | cumulus-primitives-utility = { workspace = true } 72 | pallet-collator-selection = { workspace = true } 73 | parachain-info = { workspace = true } 74 | parachains-common = { workspace = true } 75 | 76 | # extra deps for setting up pallet-contracts and pallet-revive 77 | pallet-contracts = { workspace = true } 78 | pallet-revive = { workspace = true } 79 | pallet-utility = { workspace = true } 80 | pallet-insecure-randomness-collective-flip = { workspace = true } 81 | pallet-assets = { workspace = true } 82 | 83 | [features] 84 | default = ["std"] 85 | std = [ 86 | "codec/std", 87 | "cumulus-pallet-aura-ext/std", 88 | "cumulus-pallet-dmp-queue/std", 89 | "cumulus-pallet-parachain-system/std", 90 | "cumulus-pallet-xcm/std", 91 | "cumulus-pallet-xcmp-queue/std", 92 | "cumulus-primitives-aura/std", 93 | "cumulus-primitives-core/std", 94 | "cumulus-primitives-timestamp/std", 95 | "cumulus-primitives-utility/std", 96 | "frame-executive/std", 97 | "frame-support/std", 98 | "frame-system-rpc-runtime-api/std", 99 | "frame-system/std", 100 | "log/std", 101 | "pallet-assets/std", 102 | "pallet-aura/std", 103 | "pallet-authorship/std", 104 | "pallet-balances/std", 105 | "pallet-collator-selection/std", 106 | "pallet-contracts/std", 107 | "pallet-revive/std", 108 | "pallet-insecure-randomness-collective-flip/std", 109 | "pallet-session/std", 110 | "pallet-sudo/std", 111 | "pallet-xcm/std", 112 | "pallet-timestamp/std", 113 | "pallet-transaction-payment-rpc-runtime-api/std", 114 | "pallet-transaction-payment/std", 115 | "pallet-xcm/std", 116 | "parachain-info/std", 117 | "polkadot-parachain-primitives/std", 118 | "polkadot-runtime-common/std", 119 | "scale-info/std", 120 | "scale-info/std", 121 | "sp-api/std", 122 | "sp-block-builder/std", 123 | "sp-consensus-aura/std", 124 | "sp-core/std", 125 | "sp-inherents/std", 126 | "sp-offchain/std", 127 | "sp-runtime/std", 128 | "sp-session/std", 129 | "sp-std/std", 130 | "sp-transaction-pool/std", 131 | "sp-version/std", 132 | "substrate-wasm-builder", 133 | "xcm-builder/std", 134 | "xcm-executor/std", 135 | "xcm/std", 136 | ] 137 | 138 | runtime-benchmarks = [ 139 | "cumulus-pallet-parachain-system/runtime-benchmarks", 140 | "cumulus-pallet-session-benchmarking/runtime-benchmarks", 141 | "cumulus-pallet-xcmp-queue/runtime-benchmarks", 142 | "frame-benchmarking/runtime-benchmarks", 143 | "frame-support/runtime-benchmarks", 144 | "frame-system-benchmarking/runtime-benchmarks", 145 | "frame-system/runtime-benchmarks", 146 | "hex-literal", 147 | "polkadot-parachain-primitives/runtime-benchmarks", 148 | "pallet-balances/runtime-benchmarks", 149 | "pallet-collator-selection/runtime-benchmarks", 150 | "pallet-sudo/runtime-benchmarks", 151 | "pallet-timestamp/runtime-benchmarks", 152 | "pallet-xcm/runtime-benchmarks", 153 | "polkadot-runtime-common/runtime-benchmarks", 154 | "sp-runtime/runtime-benchmarks", 155 | "xcm-builder/runtime-benchmarks", 156 | "xcm-executor/runtime-benchmarks", 157 | ] 158 | 159 | try-runtime = [ 160 | "cumulus-pallet-aura-ext/try-runtime", 161 | "cumulus-pallet-dmp-queue/try-runtime", 162 | "cumulus-pallet-parachain-system/try-runtime", 163 | "cumulus-pallet-xcm/try-runtime", 164 | "cumulus-pallet-xcmp-queue/try-runtime", 165 | "frame-executive/try-runtime", 166 | "frame-support/try-runtime", 167 | "frame-system/try-runtime", 168 | "frame-try-runtime/try-runtime", 169 | "pallet-aura/try-runtime", 170 | "pallet-authorship/try-runtime", 171 | "pallet-balances/try-runtime", 172 | "pallet-collator-selection/try-runtime", 173 | "pallet-contracts/try-runtime", 174 | "pallet-revive/try-runtime", 175 | "pallet-session/try-runtime", 176 | "pallet-sudo/try-runtime", 177 | "pallet-timestamp/try-runtime", 178 | "pallet-transaction-payment/try-runtime", 179 | "pallet-xcm/try-runtime", 180 | "parachain-info/try-runtime", 181 | "polkadot-runtime-common/try-runtime", 182 | "sp-runtime/try-runtime", 183 | ] 184 | 185 | parachain = [] 186 | -------------------------------------------------------------------------------- /parachain-runtime/build.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "std")] 2 | fn main() { 3 | substrate_wasm_builder::WasmBuilder::new() 4 | .with_current_project() 5 | .export_heap_base() 6 | .import_memory() 7 | .build() 8 | } 9 | 10 | /// The wasm builder is deactivated when compiling 11 | /// this crate for wasm to speed up the compilation. 12 | #[cfg(not(feature = "std"))] 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /parachain-runtime/src/assets_config.rs: -------------------------------------------------------------------------------- 1 | ../../runtime/src/assets_config.rs -------------------------------------------------------------------------------- /parachain-runtime/src/contracts_config.rs: -------------------------------------------------------------------------------- 1 | ../../runtime/src/contracts_config.rs -------------------------------------------------------------------------------- /parachain-runtime/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. 3 | #![recursion_limit = "256"] 4 | 5 | // Make the WASM binary available. 6 | #[cfg(feature = "std")] 7 | include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); 8 | 9 | mod assets_config; 10 | mod contracts_config; 11 | mod revive_config; 12 | mod weights; 13 | mod xcm_config; 14 | 15 | extern crate alloc; 16 | 17 | use alloc::vec::Vec; 18 | use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; 19 | use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; 20 | use smallvec::smallvec; 21 | use sp_api::impl_runtime_apis; 22 | use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; 23 | use sp_runtime::{ 24 | create_runtime_str, generic, impl_opaque_keys, 25 | traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, 26 | transaction_validity::{TransactionSource, TransactionValidity}, 27 | ApplyExtrinsicResult, MultiSignature, 28 | }; 29 | 30 | use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; 31 | use frame_support::{ 32 | derive_impl, 33 | dispatch::DispatchClass, 34 | genesis_builder_helper::{build_state, get_preset}, 35 | parameter_types, 36 | traits::{ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, TransformOrigin}, 37 | weights::{ 38 | constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, Weight, WeightToFeeCoefficient, 39 | WeightToFeeCoefficients, WeightToFeePolynomial, 40 | }, 41 | PalletId, 42 | }; 43 | use frame_system::{ 44 | limits::{BlockLength, BlockWeights}, 45 | EnsureRoot, 46 | }; 47 | use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; 48 | use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; 49 | pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; 50 | pub use sp_runtime::{MultiAddress, Perbill, Permill}; 51 | #[cfg(feature = "std")] 52 | use sp_version::NativeVersion; 53 | use sp_version::RuntimeVersion; 54 | use xcm_config::{RelayLocation, XcmOriginToTransactDispatchOrigin}; 55 | 56 | #[cfg(any(feature = "std", test))] 57 | pub use sp_runtime::BuildStorage; 58 | 59 | // Polkadot imports 60 | use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; 61 | 62 | use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; 63 | 64 | // XCM Imports 65 | use xcm::latest::prelude::BodyId; 66 | 67 | /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. 68 | pub type Signature = MultiSignature; 69 | 70 | /// Some way of identifying an account on the chain. We intentionally make it equivalent 71 | /// to the public key of our transaction signing scheme. 72 | pub type AccountId = <::Signer as IdentifyAccount>::AccountId; 73 | 74 | /// Balance of an account. 75 | pub type Balance = u128; 76 | 77 | /// Index of a transaction in the chain. 78 | pub type Nonce = u32; 79 | 80 | /// A hash of some data used by the chain. 81 | pub type Hash = sp_core::H256; 82 | 83 | /// An index to a block. 84 | pub type BlockNumber = u32; 85 | 86 | /// The address format for describing accounts. 87 | pub type Address = MultiAddress; 88 | 89 | /// Block header type as expected by this runtime. 90 | pub type Header = generic::Header; 91 | 92 | /// Block type as expected by this runtime. 93 | pub type Block = generic::Block; 94 | 95 | /// A Block signed with a Justification 96 | pub type SignedBlock = generic::SignedBlock; 97 | 98 | /// BlockId type as expected by this runtime. 99 | pub type BlockId = generic::BlockId; 100 | 101 | type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< 102 | Runtime, 103 | RELAY_CHAIN_SLOT_DURATION_MILLIS, 104 | BLOCK_PROCESSING_VELOCITY, 105 | UNINCLUDED_SEGMENT_CAPACITY, 106 | >; 107 | 108 | /// The SignedExtension to the basic transaction logic. 109 | pub type SignedExtra = ( 110 | frame_system::CheckNonZeroSender, 111 | frame_system::CheckSpecVersion, 112 | frame_system::CheckTxVersion, 113 | frame_system::CheckGenesis, 114 | frame_system::CheckEra, 115 | frame_system::CheckNonce, 116 | frame_system::CheckWeight, 117 | pallet_transaction_payment::ChargeTransactionPayment, 118 | ); 119 | 120 | /// Unchecked extrinsic type as expected by this runtime. 121 | pub type UncheckedExtrinsic = 122 | generic::UncheckedExtrinsic; 123 | 124 | /// Executive: handles dispatch to the various modules. 125 | pub type Executive = frame_executive::Executive< 126 | Runtime, 127 | Block, 128 | frame_system::ChainContext, 129 | Runtime, 130 | AllPalletsWithSystem, 131 | >; 132 | 133 | /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the 134 | /// node's balance type. 135 | /// 136 | /// This should typically create a mapping between the following ranges: 137 | /// - `[0, MAXIMUM_BLOCK_WEIGHT]` 138 | /// - `[Balance::min, Balance::max]` 139 | /// 140 | /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: 141 | /// - Setting it to `0` will essentially disable the weight fee. 142 | /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. 143 | pub struct WeightToFee; 144 | impl WeightToFeePolynomial for WeightToFee { 145 | type Balance = Balance; 146 | fn polynomial() -> WeightToFeeCoefficients { 147 | // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: 148 | // We map to 1/10 of that, or 1/10 MILLIUNIT 149 | let p = MILLIUNIT / 10; 150 | let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); 151 | smallvec![WeightToFeeCoefficient { 152 | degree: 1, 153 | negative: false, 154 | coeff_frac: Perbill::from_rational(p % q, q), 155 | coeff_integer: p / q, 156 | }] 157 | } 158 | } 159 | 160 | /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know 161 | /// the specifics of the runtime. They can then be made to be agnostic over specific formats 162 | /// of data like extrinsics, allowing for them to continue syncing the network through upgrades 163 | /// to even the core data structures. 164 | pub mod opaque { 165 | use super::*; 166 | use sp_runtime::{ 167 | generic, 168 | traits::{BlakeTwo256, Hash as HashT}, 169 | }; 170 | 171 | pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; 172 | /// Opaque block header type. 173 | pub type Header = generic::Header; 174 | /// Opaque block type. 175 | pub type Block = generic::Block; 176 | /// Opaque block identifier type. 177 | pub type BlockId = generic::BlockId; 178 | /// Opaque block hash type. 179 | pub type Hash = ::Output; 180 | } 181 | 182 | impl_opaque_keys! { 183 | pub struct SessionKeys { 184 | pub aura: Aura, 185 | } 186 | } 187 | 188 | #[sp_version::runtime_version] 189 | pub const VERSION: RuntimeVersion = RuntimeVersion { 190 | spec_name: create_runtime_str!("contracts-parachain"), 191 | impl_name: create_runtime_str!("contracts-parachain"), 192 | authoring_version: 1, 193 | spec_version: 1, 194 | impl_version: 0, 195 | apis: RUNTIME_API_VERSIONS, 196 | transaction_version: 1, 197 | state_version: 1, 198 | }; 199 | 200 | mod block_times { 201 | /// This determines the average expected block time that we are targeting. Blocks will be 202 | /// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by 203 | /// `pallet_timestamp` which is in turn picked up by `pallet_aura` to implement `fn 204 | /// slot_duration()`. 205 | /// 206 | /// Change this to adjust the block time. 207 | pub const MILLISECS_PER_BLOCK: u64 = 6000; 208 | 209 | // NOTE: Currently it is not possible to change the slot duration after the chain has started. 210 | // Attempting to do so will brick block production. 211 | pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; 212 | } 213 | pub use block_times::*; 214 | 215 | // Time is measured by number of blocks. 216 | pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); 217 | pub const HOURS: BlockNumber = MINUTES * 60; 218 | pub const DAYS: BlockNumber = HOURS * 24; 219 | 220 | // Unit = the base number of indivisible units for balances 221 | pub const UNIT: Balance = 1_000_000_000_000; 222 | pub const MILLIUNIT: Balance = 1_000_000_000; 223 | pub const MICROUNIT: Balance = 1_000_000; 224 | 225 | /// The existential deposit. Set to 1/10 of the Connected Relay Chain. 226 | pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT; 227 | 228 | /// We assume that ~5% of the block weight is consumed by `on_initialize` handlers. This is 229 | /// used to limit the maximal weight of a single extrinsic. 230 | const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5); 231 | 232 | /// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used by 233 | /// `Operational` extrinsics. 234 | const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); 235 | 236 | /// We allow for 2 seconds of compute with a 6 second average block time. 237 | const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts( 238 | WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), 239 | cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64, 240 | ); 241 | 242 | mod async_backing_params { 243 | /// Maximum number of blocks simultaneously accepted by the Runtime, not yet included 244 | /// into the relay chain. 245 | pub(crate) const UNINCLUDED_SEGMENT_CAPACITY: u32 = 3; 246 | /// How many parachain blocks are processed by the relay chain per parent. Limits the 247 | /// number of blocks authored per slot. 248 | pub(crate) const BLOCK_PROCESSING_VELOCITY: u32 = 1; 249 | /// Relay chain slot duration, in milliseconds. 250 | pub(crate) const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; 251 | } 252 | pub(crate) use async_backing_params::*; 253 | 254 | /// The version information used to identify this runtime when compiled natively. 255 | #[cfg(feature = "std")] 256 | pub fn native_version() -> NativeVersion { 257 | NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } 258 | } 259 | 260 | parameter_types! { 261 | pub const Version: RuntimeVersion = VERSION; 262 | 263 | // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`. 264 | // The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the 265 | // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize 266 | // the lazy contract deletion. 267 | pub RuntimeBlockLength: BlockLength = 268 | BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); 269 | pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() 270 | .base_block(BlockExecutionWeight::get()) 271 | .for_class(DispatchClass::all(), |weights| { 272 | weights.base_extrinsic = ExtrinsicBaseWeight::get(); 273 | }) 274 | .for_class(DispatchClass::Normal, |weights| { 275 | weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); 276 | }) 277 | .for_class(DispatchClass::Operational, |weights| { 278 | weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); 279 | // Operational transactions have some extra reserved space, so that they 280 | // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. 281 | weights.reserved = Some( 282 | MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT 283 | ); 284 | }) 285 | .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) 286 | .build_or_panic(); 287 | pub const SS58Prefix: u16 = 42; 288 | } 289 | 290 | /// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from 291 | /// [`ParaChainDefaultConfig`](`struct@frame_system::config_preludes::ParaChainDefaultConfig`), 292 | /// but overridden as needed. 293 | #[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] 294 | impl frame_system::Config for Runtime { 295 | /// The identifier used to distinguish between accounts. 296 | type AccountId = AccountId; 297 | /// The index type for storing how many extrinsics an account has signed. 298 | type Nonce = Nonce; 299 | /// The type for hashing blocks and tries. 300 | type Hash = Hash; 301 | /// The block type. 302 | type Block = Block; 303 | /// Maximum number of block number to block hash mappings to keep (oldest pruned first). 304 | type BlockHashCount = BlockHashCount; 305 | /// Runtime version. 306 | type Version = Version; 307 | /// The data to be stored in an account. 308 | type AccountData = pallet_balances::AccountData; 309 | /// The weight of database operations that the runtime can invoke. 310 | type DbWeight = RocksDbWeight; 311 | /// Block & extrinsics weights: base values and limits. 312 | type BlockWeights = RuntimeBlockWeights; 313 | /// The maximum length of a block (in bytes). 314 | type BlockLength = RuntimeBlockLength; 315 | /// This is used as an identifier of the chain. 42 is the generic substrate prefix. 316 | type SS58Prefix = SS58Prefix; 317 | /// The action to take on a Runtime Upgrade 318 | type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; 319 | type MaxConsumers = frame_support::traits::ConstU32<16>; 320 | } 321 | 322 | impl pallet_timestamp::Config for Runtime { 323 | /// A timestamp: milliseconds since the unix epoch. 324 | type Moment = u64; 325 | type OnTimestampSet = Aura; 326 | type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; 327 | type WeightInfo = (); 328 | } 329 | 330 | impl pallet_authorship::Config for Runtime { 331 | type FindAuthor = pallet_session::FindAccountFromAuthorIndex; 332 | type EventHandler = (CollatorSelection,); 333 | } 334 | 335 | parameter_types! { 336 | pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; 337 | } 338 | 339 | impl pallet_balances::Config for Runtime { 340 | type MaxLocks = ConstU32<50>; 341 | /// The type for recording an account's balance. 342 | type Balance = Balance; 343 | /// The ubiquitous event type. 344 | type RuntimeEvent = RuntimeEvent; 345 | type DustRemoval = (); 346 | type ExistentialDeposit = ExistentialDeposit; 347 | type AccountStore = System; 348 | type WeightInfo = pallet_balances::weights::SubstrateWeight; 349 | type MaxReserves = ConstU32<50>; 350 | type ReserveIdentifier = [u8; 8]; 351 | type RuntimeHoldReason = RuntimeHoldReason; 352 | type RuntimeFreezeReason = RuntimeFreezeReason; 353 | type FreezeIdentifier = (); 354 | type MaxFreezes = ConstU32<50>; 355 | } 356 | 357 | parameter_types! { 358 | /// Relay Chain `TransactionByteFee` / 10 359 | pub const TransactionByteFee: Balance = 10 * MICROUNIT; 360 | } 361 | 362 | impl pallet_transaction_payment::Config for Runtime { 363 | type RuntimeEvent = RuntimeEvent; 364 | type OnChargeTransaction = pallet_transaction_payment::FungibleAdapter; 365 | type WeightToFee = WeightToFee; 366 | type LengthToFee = ConstantMultiplier; 367 | type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; 368 | type OperationalFeeMultiplier = ConstU8<5>; 369 | } 370 | 371 | impl pallet_sudo::Config for Runtime { 372 | type RuntimeEvent = RuntimeEvent; 373 | type RuntimeCall = RuntimeCall; 374 | type WeightInfo = (); 375 | } 376 | 377 | parameter_types! { 378 | pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); 379 | pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); 380 | pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; 381 | } 382 | 383 | impl cumulus_pallet_parachain_system::Config for Runtime { 384 | type WeightInfo = (); 385 | type RuntimeEvent = RuntimeEvent; 386 | type OnSystemEvent = (); 387 | type SelfParaId = parachain_info::Pallet; 388 | type OutboundXcmpMessageSource = XcmpQueue; 389 | type DmpQueue = frame_support::traits::EnqueueWithOrigin; 390 | type ReservedDmpWeight = ReservedDmpWeight; 391 | type XcmpMessageHandler = XcmpQueue; 392 | type ReservedXcmpWeight = ReservedXcmpWeight; 393 | type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; 394 | type ConsensusHook = ConsensusHook; 395 | } 396 | 397 | impl parachain_info::Config for Runtime {} 398 | 399 | parameter_types! { 400 | pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block; 401 | } 402 | 403 | impl pallet_message_queue::Config for Runtime { 404 | type RuntimeEvent = RuntimeEvent; 405 | type WeightInfo = (); 406 | #[cfg(feature = "runtime-benchmarks")] 407 | type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor< 408 | cumulus_primitives_core::AggregateMessageOrigin, 409 | >; 410 | #[cfg(not(feature = "runtime-benchmarks"))] 411 | type MessageProcessor = xcm_builder::ProcessXcmMessage< 412 | AggregateMessageOrigin, 413 | xcm_executor::XcmExecutor, 414 | RuntimeCall, 415 | >; 416 | type Size = u32; 417 | // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: 418 | type QueueChangeHandler = NarrowOriginToSibling; 419 | type QueuePausedQuery = NarrowOriginToSibling; 420 | type HeapSize = ConstU32<{ 64 * 1024 }>; 421 | type MaxStale = ConstU32<8>; 422 | type ServiceWeight = MessageQueueServiceWeight; 423 | type IdleMaxServiceWeight = (); 424 | } 425 | 426 | impl cumulus_pallet_aura_ext::Config for Runtime {} 427 | 428 | impl cumulus_pallet_xcmp_queue::Config for Runtime { 429 | type RuntimeEvent = RuntimeEvent; 430 | type ChannelInfo = ParachainSystem; 431 | type VersionWrapper = (); 432 | // Enqueue XCMP messages from siblings for later processing. 433 | type XcmpQueue = TransformOrigin; 434 | type MaxInboundSuspended = ConstU32<1_000>; 435 | type MaxActiveOutboundChannels = ConstU32<128>; 436 | type MaxPageSize = ConstU32<{ 1 << 16 }>; 437 | type ControllerOrigin = EnsureRoot; 438 | type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; 439 | type WeightInfo = (); 440 | type PriceForSiblingDelivery = NoPriceForMessageDelivery; 441 | } 442 | 443 | parameter_types! { 444 | pub const Period: u32 = 6 * HOURS; 445 | pub const Offset: u32 = 0; 446 | } 447 | 448 | impl pallet_session::Config for Runtime { 449 | type RuntimeEvent = RuntimeEvent; 450 | type ValidatorId = ::AccountId; 451 | // we don't have stash and controller, thus we don't need the convert as well. 452 | type ValidatorIdOf = pallet_collator_selection::IdentityCollator; 453 | type ShouldEndSession = pallet_session::PeriodicSessions; 454 | type NextSessionRotation = pallet_session::PeriodicSessions; 455 | type SessionManager = CollatorSelection; 456 | // Essentially just Aura, but let's be pedantic. 457 | type SessionHandler = ::KeyTypeIdProviders; 458 | type Keys = SessionKeys; 459 | type WeightInfo = (); 460 | } 461 | 462 | impl pallet_aura::Config for Runtime { 463 | type AuthorityId = AuraId; 464 | type DisabledValidators = (); 465 | type MaxAuthorities = ConstU32<100_000>; 466 | type AllowMultipleBlocksPerSlot = ConstBool; 467 | type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; 468 | } 469 | 470 | parameter_types! { 471 | pub const PotId: PalletId = PalletId(*b"PotStake"); 472 | pub const SessionLength: BlockNumber = 6 * HOURS; 473 | // StakingAdmin pluralistic body. 474 | pub const StakingAdminBodyId: BodyId = BodyId::Defense; 475 | } 476 | 477 | /// We allow root and the StakingAdmin to execute privileged collator selection operations. 478 | pub type CollatorSelectionUpdateOrigin = EitherOfDiverse< 479 | EnsureRoot, 480 | EnsureXcm>, 481 | >; 482 | 483 | impl pallet_collator_selection::Config for Runtime { 484 | type RuntimeEvent = RuntimeEvent; 485 | type Currency = Balances; 486 | type UpdateOrigin = CollatorSelectionUpdateOrigin; 487 | type PotId = PotId; 488 | type MaxCandidates = ConstU32<100>; 489 | type MinEligibleCollators = ConstU32<4>; 490 | type MaxInvulnerables = ConstU32<20>; 491 | // should be a multiple of session or things will get inconsistent 492 | type KickThreshold = Period; 493 | type ValidatorId = ::AccountId; 494 | type ValidatorIdOf = pallet_collator_selection::IdentityCollator; 495 | type ValidatorRegistration = Session; 496 | type WeightInfo = (); 497 | } 498 | 499 | pub use pallet_balances::Call as BalancesCall; 500 | impl pallet_insecure_randomness_collective_flip::Config for Runtime {} 501 | impl pallet_utility::Config for Runtime { 502 | type RuntimeEvent = RuntimeEvent; 503 | type RuntimeCall = RuntimeCall; 504 | type PalletsOrigin = OriginCaller; 505 | type WeightInfo = pallet_utility::weights::SubstrateWeight; 506 | } 507 | 508 | // Create the runtime by composing the FRAME pallets that were previously configured. 509 | #[frame_support::runtime] 510 | mod runtime { 511 | 512 | #[runtime::runtime] 513 | #[runtime::derive( 514 | RuntimeCall, 515 | RuntimeEvent, 516 | RuntimeError, 517 | RuntimeOrigin, 518 | RuntimeFreezeReason, 519 | RuntimeHoldReason, 520 | RuntimeSlashReason, 521 | RuntimeLockId, 522 | RuntimeTask 523 | )] 524 | pub struct Runtime; 525 | 526 | // Order should match with Runtime defined in runtime/src/lib.rs 527 | #[runtime::pallet_index(0)] 528 | pub type System = frame_system; 529 | #[runtime::pallet_index(1)] 530 | pub type RandomnessCollectiveFlip = pallet_insecure_randomness_collective_flip; 531 | #[runtime::pallet_index(2)] 532 | pub type Utility = pallet_utility; 533 | #[runtime::pallet_index(3)] 534 | pub type Timestamp = pallet_timestamp; 535 | #[runtime::pallet_index(4)] 536 | pub type Balances = pallet_balances; 537 | #[runtime::pallet_index(5)] 538 | pub type Authorship = pallet_authorship; 539 | #[runtime::pallet_index(6)] 540 | pub type TransactionPayment = pallet_transaction_payment; 541 | #[runtime::pallet_index(7)] 542 | pub type Sudo = pallet_sudo; 543 | #[runtime::pallet_index(8)] 544 | pub type Contracts = pallet_contracts; 545 | #[runtime::pallet_index(9)] 546 | pub type Revive = pallet_revive; 547 | #[runtime::pallet_index(10)] 548 | pub type Assets = pallet_assets; 549 | // Parachain support. 550 | #[runtime::pallet_index(11)] 551 | pub type ParachainSystem = cumulus_pallet_parachain_system; 552 | #[runtime::pallet_index(12)] 553 | pub type ParachainInfo = parachain_info; 554 | 555 | // Collator support. The order of these 4 are important and shall not change. 556 | #[runtime::pallet_index(13)] 557 | pub type CollatorSelection = pallet_collator_selection; 558 | #[runtime::pallet_index(14)] 559 | pub type Session = pallet_session; 560 | #[runtime::pallet_index(15)] 561 | pub type Aura = pallet_aura; 562 | #[runtime::pallet_index(16)] 563 | pub type AuraExt = cumulus_pallet_aura_ext; 564 | // XCM helpers. 565 | #[runtime::pallet_index(17)] 566 | pub type XcmpQueue = cumulus_pallet_xcmp_queue; 567 | #[runtime::pallet_index(18)] 568 | pub type PolkadotXcm = pallet_xcm; 569 | #[runtime::pallet_index(19)] 570 | pub type CumulusXcm = cumulus_pallet_xcm; 571 | #[runtime::pallet_index(20)] 572 | pub type MessageQueue = pallet_message_queue; 573 | } 574 | 575 | #[cfg(feature = "runtime-benchmarks")] 576 | mod benches { 577 | frame_benchmarking::define_benchmarks!( 578 | [frame_system, SystemBench::] 579 | [pallet_balances, Balances] 580 | [pallet_session, SessionBench::] 581 | [pallet_timestamp, Timestamp] 582 | [pallet_message_queue, MessageQueue] 583 | [pallet_sudo, Sudo] 584 | [pallet_collator_selection, CollatorSelection] 585 | [cumulus_pallet_parachain_system, ParachainSystem] 586 | [cumulus_pallet_xcmp_queue, XcmpQueue] 587 | ); 588 | } 589 | 590 | type EventRecord = frame_system::EventRecord< 591 | ::RuntimeEvent, 592 | ::Hash, 593 | >; 594 | 595 | // Prints debug output of the `revive` pallet to stdout if the node is 596 | // started with `-lruntime::revive=trace` or `-lruntime::contracts=debug`. 597 | const CONTRACTS_DEBUG_OUTPUT: pallet_contracts::DebugInfo = 598 | pallet_contracts::DebugInfo::UnsafeDebug; 599 | const CONTRACTS_EVENTS: pallet_contracts::CollectEvents = 600 | pallet_contracts::CollectEvents::UnsafeCollect; 601 | const REVIVE_DEBUG_OUTPUT: pallet_revive::DebugInfo = pallet_revive::DebugInfo::UnsafeDebug; 602 | const REVIVE_EVENTS: pallet_revive::CollectEvents = pallet_revive::CollectEvents::UnsafeCollect; 603 | 604 | impl_runtime_apis! { 605 | impl sp_consensus_aura::AuraApi for Runtime { 606 | fn slot_duration() -> sp_consensus_aura::SlotDuration { 607 | sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION) 608 | } 609 | 610 | fn authorities() -> Vec { 611 | pallet_aura::Authorities::::get().into_inner() 612 | } 613 | } 614 | 615 | impl cumulus_primitives_aura::AuraUnincludedSegmentApi for Runtime { 616 | fn can_build_upon( 617 | included_hash: ::Hash, 618 | slot: cumulus_primitives_aura::Slot 619 | ) -> bool { 620 | ConsensusHook::can_build_upon(included_hash, slot) 621 | } 622 | } 623 | 624 | impl sp_api::Core for Runtime { 625 | fn version() -> RuntimeVersion { 626 | VERSION 627 | } 628 | 629 | fn execute_block(block: Block) { 630 | Executive::execute_block(block) 631 | } 632 | 633 | fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { 634 | Executive::initialize_block(header) 635 | } 636 | } 637 | 638 | impl sp_api::Metadata for Runtime { 639 | fn metadata() -> OpaqueMetadata { 640 | OpaqueMetadata::new(Runtime::metadata().into()) 641 | } 642 | 643 | fn metadata_at_version(version: u32) -> Option { 644 | Runtime::metadata_at_version(version) 645 | } 646 | 647 | fn metadata_versions() -> Vec { 648 | Runtime::metadata_versions() 649 | } 650 | } 651 | 652 | impl sp_block_builder::BlockBuilder for Runtime { 653 | fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { 654 | Executive::apply_extrinsic(extrinsic) 655 | } 656 | 657 | fn finalize_block() -> ::Header { 658 | Executive::finalize_block() 659 | } 660 | 661 | fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { 662 | data.create_extrinsics() 663 | } 664 | 665 | fn check_inherents( 666 | block: Block, 667 | data: sp_inherents::InherentData, 668 | ) -> sp_inherents::CheckInherentsResult { 669 | data.check_extrinsics(&block) 670 | } 671 | } 672 | 673 | impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { 674 | fn validate_transaction( 675 | source: TransactionSource, 676 | tx: ::Extrinsic, 677 | block_hash: ::Hash, 678 | ) -> TransactionValidity { 679 | Executive::validate_transaction(source, tx, block_hash) 680 | } 681 | } 682 | 683 | impl sp_offchain::OffchainWorkerApi for Runtime { 684 | fn offchain_worker(header: &::Header) { 685 | Executive::offchain_worker(header) 686 | } 687 | } 688 | 689 | impl sp_session::SessionKeys for Runtime { 690 | fn generate_session_keys(seed: Option>) -> Vec { 691 | SessionKeys::generate(seed) 692 | } 693 | 694 | fn decode_session_keys( 695 | encoded: Vec, 696 | ) -> Option, KeyTypeId)>> { 697 | SessionKeys::decode_into_raw_public_keys(&encoded) 698 | } 699 | } 700 | 701 | impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { 702 | fn account_nonce(account: AccountId) -> Nonce { 703 | System::account_nonce(account) 704 | } 705 | } 706 | 707 | impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { 708 | fn query_info( 709 | uxt: ::Extrinsic, 710 | len: u32, 711 | ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { 712 | TransactionPayment::query_info(uxt, len) 713 | } 714 | fn query_fee_details( 715 | uxt: ::Extrinsic, 716 | len: u32, 717 | ) -> pallet_transaction_payment::FeeDetails { 718 | TransactionPayment::query_fee_details(uxt, len) 719 | } 720 | fn query_weight_to_fee(weight: Weight) -> Balance { 721 | TransactionPayment::weight_to_fee(weight) 722 | } 723 | fn query_length_to_fee(length: u32) -> Balance { 724 | TransactionPayment::length_to_fee(length) 725 | } 726 | } 727 | 728 | impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi 729 | for Runtime 730 | { 731 | fn query_call_info( 732 | call: RuntimeCall, 733 | len: u32, 734 | ) -> pallet_transaction_payment::RuntimeDispatchInfo { 735 | TransactionPayment::query_call_info(call, len) 736 | } 737 | fn query_call_fee_details( 738 | call: RuntimeCall, 739 | len: u32, 740 | ) -> pallet_transaction_payment::FeeDetails { 741 | TransactionPayment::query_call_fee_details(call, len) 742 | } 743 | fn query_weight_to_fee(weight: Weight) -> Balance { 744 | TransactionPayment::weight_to_fee(weight) 745 | } 746 | fn query_length_to_fee(length: u32) -> Balance { 747 | TransactionPayment::length_to_fee(length) 748 | } 749 | } 750 | 751 | impl cumulus_primitives_core::CollectCollationInfo for Runtime { 752 | fn collect_collation_info(header: &::Header) -> cumulus_primitives_core::CollationInfo { 753 | ParachainSystem::collect_collation_info(header) 754 | } 755 | } 756 | 757 | #[cfg(feature = "try-runtime")] 758 | impl frame_try_runtime::TryRuntime for Runtime { 759 | fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { 760 | let weight = Executive::try_runtime_upgrade(checks).unwrap(); 761 | (weight, RuntimeBlockWeights::get().max_block) 762 | } 763 | 764 | fn execute_block( 765 | block: Block, 766 | state_root_check: bool, 767 | signature_check: bool, 768 | select: frame_try_runtime::TryStateSelect, 769 | ) -> Weight { 770 | // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to 771 | // have a backtrace here. 772 | Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() 773 | } 774 | } 775 | 776 | #[cfg(feature = "runtime-benchmarks")] 777 | impl frame_benchmarking::Benchmark for Runtime { 778 | fn benchmark_metadata(extra: bool) -> ( 779 | Vec, 780 | Vec, 781 | ) { 782 | use frame_benchmarking::{Benchmarking, BenchmarkList}; 783 | use frame_support::traits::StorageInfoTrait; 784 | use frame_system_benchmarking::Pallet as SystemBench; 785 | use cumulus_pallet_session_benchmarking::Pallet as SessionBench; 786 | 787 | let mut list = Vec::::new(); 788 | list_benchmarks!(list, extra); 789 | 790 | let storage_info = AllPalletsWithSystem::storage_info(); 791 | (list, storage_info) 792 | } 793 | 794 | fn dispatch_benchmark( 795 | config: frame_benchmarking::BenchmarkConfig 796 | ) -> Result, sp_runtime::RuntimeString> { 797 | use frame_benchmarking::{BenchmarkError, Benchmarking, BenchmarkBatch}; 798 | 799 | use frame_system_benchmarking::Pallet as SystemBench; 800 | impl frame_system_benchmarking::Config for Runtime { 801 | fn setup_set_code_requirements(code: &Vec) -> Result<(), BenchmarkError> { 802 | ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); 803 | Ok(()) 804 | } 805 | 806 | fn verify_set_code() { 807 | System::assert_last_event(cumulus_pallet_parachain_system::Event::::ValidationFunctionStored.into()); 808 | } 809 | } 810 | 811 | use cumulus_pallet_session_benchmarking::Pallet as SessionBench; 812 | impl cumulus_pallet_session_benchmarking::Config for Runtime {} 813 | 814 | use frame_support::traits::WhitelistedStorageKeys; 815 | let whitelist = AllPalletsWithSystem::whitelisted_storage_keys(); 816 | 817 | let mut batches = Vec::::new(); 818 | let params = (&config, &whitelist); 819 | add_benchmarks!(params, batches); 820 | 821 | if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } 822 | Ok(batches) 823 | } 824 | } 825 | 826 | impl pallet_revive::ReviveApi for Runtime 827 | { 828 | fn call( 829 | origin: AccountId, 830 | dest: AccountId, 831 | value: Balance, 832 | gas_limit: Option, 833 | storage_deposit_limit: Option, 834 | input_data: Vec, 835 | ) -> pallet_revive::ContractExecResult { 836 | Revive::bare_call( 837 | RuntimeOrigin::signed(origin), 838 | dest, 839 | value, 840 | gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block), 841 | storage_deposit_limit.unwrap_or(u128::MAX), 842 | input_data, 843 | REVIVE_DEBUG_OUTPUT, 844 | REVIVE_EVENTS, 845 | ) 846 | } 847 | 848 | fn instantiate( 849 | origin: AccountId, 850 | value: Balance, 851 | gas_limit: Option, 852 | storage_deposit_limit: Option, 853 | code: pallet_revive::Code, 854 | data: Vec, 855 | salt: Vec, 856 | ) -> pallet_revive::ContractInstantiateResult 857 | { 858 | Revive::bare_instantiate( 859 | RuntimeOrigin::signed(origin), 860 | value, 861 | gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block), 862 | storage_deposit_limit.unwrap_or(u128::MAX), 863 | code, 864 | data, 865 | salt, 866 | REVIVE_DEBUG_OUTPUT, 867 | REVIVE_EVENTS, 868 | ) 869 | } 870 | 871 | fn upload_code( 872 | origin: AccountId, 873 | code: Vec, 874 | storage_deposit_limit: Option, 875 | ) -> pallet_revive::CodeUploadResult 876 | { 877 | Revive::bare_upload_code( 878 | RuntimeOrigin::signed(origin), 879 | code, 880 | storage_deposit_limit.unwrap_or(u128::MAX), 881 | ) 882 | } 883 | 884 | fn get_storage( 885 | address: AccountId, 886 | key: Vec, 887 | ) -> pallet_revive::GetStorageResult { 888 | Revive::get_storage( 889 | address, 890 | key 891 | ) 892 | } 893 | } 894 | 895 | impl pallet_contracts::ContractsApi 896 | for Runtime 897 | { 898 | fn call( 899 | origin: AccountId, 900 | dest: AccountId, 901 | value: Balance, 902 | gas_limit: Option, 903 | storage_deposit_limit: Option, 904 | input_data: Vec, 905 | ) -> pallet_contracts::ContractExecResult { 906 | let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block); 907 | Contracts::bare_call( 908 | origin, 909 | dest, 910 | value, 911 | gas_limit, 912 | storage_deposit_limit, 913 | input_data, 914 | CONTRACTS_DEBUG_OUTPUT, 915 | CONTRACTS_EVENTS, 916 | pallet_contracts::Determinism::Enforced, 917 | ) 918 | } 919 | 920 | fn instantiate( 921 | origin: AccountId, 922 | value: Balance, 923 | gas_limit: Option, 924 | storage_deposit_limit: Option, 925 | code: pallet_contracts::Code, 926 | data: Vec, 927 | salt: Vec, 928 | ) -> pallet_contracts::ContractInstantiateResult 929 | { 930 | let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block); 931 | Contracts::bare_instantiate( 932 | origin, 933 | value, 934 | gas_limit, 935 | storage_deposit_limit, 936 | code, 937 | data, 938 | salt, 939 | CONTRACTS_DEBUG_OUTPUT, 940 | CONTRACTS_EVENTS, 941 | ) 942 | } 943 | 944 | fn upload_code( 945 | origin: AccountId, 946 | code: Vec, 947 | storage_deposit_limit: Option, 948 | determinism: pallet_contracts::Determinism, 949 | ) -> pallet_contracts::CodeUploadResult 950 | { 951 | Contracts::bare_upload_code(origin, code, storage_deposit_limit, determinism) 952 | } 953 | 954 | fn get_storage( 955 | address: AccountId, 956 | key: Vec, 957 | ) -> pallet_contracts::GetStorageResult { 958 | Contracts::get_storage(address, key) 959 | } 960 | } 961 | 962 | 963 | impl sp_genesis_builder::GenesisBuilder for Runtime { 964 | fn build_state(config: Vec) -> sp_genesis_builder::Result { 965 | build_state::(config) 966 | } 967 | 968 | fn get_preset(id: &Option) -> Option> { 969 | get_preset::(id, |_| None) 970 | } 971 | 972 | fn preset_names() -> Vec { 973 | Default::default() 974 | } 975 | } 976 | } 977 | 978 | cumulus_pallet_parachain_system::register_validate_block! { 979 | Runtime = Runtime, 980 | BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, 981 | } 982 | -------------------------------------------------------------------------------- /parachain-runtime/src/revive_config.rs: -------------------------------------------------------------------------------- 1 | ../../runtime/src/revive_config.rs -------------------------------------------------------------------------------- /parachain-runtime/src/weights/block_weights.rs: -------------------------------------------------------------------------------- 1 | // This file is part of Substrate. 2 | 3 | // Copyright (C) 2022 Parity Technologies (UK) Ltd. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | pub mod constants { 19 | use frame_support::{ 20 | parameter_types, 21 | weights::{constants, Weight}, 22 | }; 23 | 24 | parameter_types! { 25 | /// Importing a block with 0 Extrinsics. 26 | pub const BlockExecutionWeight: Weight = 27 | Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000), 0); 28 | } 29 | 30 | #[cfg(test)] 31 | mod test_weights { 32 | use frame_support::weights::constants; 33 | 34 | /// Checks that the weight exists and is sane. 35 | // NOTE: If this test fails but you are sure that the generated values are fine, 36 | // you can delete it. 37 | #[test] 38 | fn sane() { 39 | let w = super::constants::BlockExecutionWeight::get(); 40 | 41 | // At least 100 µs. 42 | assert!( 43 | w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS, 44 | "Weight should be at least 100 µs." 45 | ); 46 | // At most 50 ms. 47 | assert!( 48 | w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, 49 | "Weight should be at most 50 ms." 50 | ); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /parachain-runtime/src/weights/extrinsic_weights.rs: -------------------------------------------------------------------------------- 1 | // This file is part of Substrate. 2 | 3 | // Copyright (C) 2022 Parity Technologies (UK) Ltd. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | pub mod constants { 19 | use frame_support::{ 20 | parameter_types, 21 | weights::{constants, Weight}, 22 | }; 23 | 24 | parameter_types! { 25 | /// Executing a NO-OP `System::remarks` Extrinsic. 26 | pub const ExtrinsicBaseWeight: Weight = 27 | Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000), 0); 28 | } 29 | 30 | #[cfg(test)] 31 | mod test_weights { 32 | use frame_support::weights::constants; 33 | 34 | /// Checks that the weight exists and is sane. 35 | // NOTE: If this test fails but you are sure that the generated values are fine, 36 | // you can delete it. 37 | #[test] 38 | fn sane() { 39 | let w = super::constants::ExtrinsicBaseWeight::get(); 40 | 41 | // At least 10 µs. 42 | assert!( 43 | w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, 44 | "Weight should be at least 10 µs." 45 | ); 46 | // At most 1 ms. 47 | assert!( 48 | w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, 49 | "Weight should be at most 1 ms." 50 | ); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /parachain-runtime/src/weights/mod.rs: -------------------------------------------------------------------------------- 1 | // This file is part of Substrate. 2 | 3 | // Copyright (C) 2022 Parity Technologies (UK) Ltd. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | //! Expose the auto generated weight files. 19 | 20 | pub mod block_weights; 21 | pub mod extrinsic_weights; 22 | pub mod paritydb_weights; 23 | pub mod rocksdb_weights; 24 | 25 | pub use block_weights::constants::BlockExecutionWeight; 26 | pub use extrinsic_weights::constants::ExtrinsicBaseWeight; 27 | pub use rocksdb_weights::constants::RocksDbWeight; 28 | -------------------------------------------------------------------------------- /parachain-runtime/src/weights/paritydb_weights.rs: -------------------------------------------------------------------------------- 1 | // This file is part of Substrate. 2 | 3 | // Copyright (C) 2022 Parity Technologies (UK) Ltd. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | pub mod constants { 19 | use frame_support::{ 20 | parameter_types, 21 | weights::{constants, RuntimeDbWeight}, 22 | }; 23 | 24 | parameter_types! { 25 | /// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights 26 | /// are available for brave runtime engineers who may want to try this out as default. 27 | pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { 28 | read: 8_000 * constants::WEIGHT_REF_TIME_PER_NANOS, 29 | write: 50_000 * constants::WEIGHT_REF_TIME_PER_NANOS, 30 | }; 31 | } 32 | 33 | #[cfg(test)] 34 | mod test_db_weights { 35 | use super::constants::ParityDbWeight as W; 36 | use frame_support::weights::constants; 37 | 38 | /// Checks that all weights exist and have sane values. 39 | // NOTE: If this test fails but you are sure that the generated values are fine, 40 | // you can delete it. 41 | #[test] 42 | fn sane() { 43 | // At least 1 µs. 44 | assert!( 45 | W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, 46 | "Read weight should be at least 1 µs." 47 | ); 48 | assert!( 49 | W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, 50 | "Write weight should be at least 1 µs." 51 | ); 52 | // At most 1 ms. 53 | assert!( 54 | W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, 55 | "Read weight should be at most 1 ms." 56 | ); 57 | assert!( 58 | W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, 59 | "Write weight should be at most 1 ms." 60 | ); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /parachain-runtime/src/weights/rocksdb_weights.rs: -------------------------------------------------------------------------------- 1 | // This file is part of Substrate. 2 | 3 | // Copyright (C) 2022 Parity Technologies (UK) Ltd. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | pub mod constants { 19 | use frame_support::{ 20 | parameter_types, 21 | weights::{constants, RuntimeDbWeight}, 22 | }; 23 | 24 | parameter_types! { 25 | /// By default, Substrate uses `RocksDB`, so this will be the weight used throughout 26 | /// the runtime. 27 | pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { 28 | read: 25_000 * constants::WEIGHT_REF_TIME_PER_NANOS, 29 | write: 100_000 * constants::WEIGHT_REF_TIME_PER_NANOS, 30 | }; 31 | } 32 | 33 | #[cfg(test)] 34 | mod test_db_weights { 35 | use super::constants::RocksDbWeight as W; 36 | use frame_support::weights::constants; 37 | 38 | /// Checks that all weights exist and have sane values. 39 | // NOTE: If this test fails but you are sure that the generated values are fine, 40 | // you can delete it. 41 | #[test] 42 | fn sane() { 43 | // At least 1 µs. 44 | assert!( 45 | W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, 46 | "Read weight should be at least 1 µs." 47 | ); 48 | assert!( 49 | W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, 50 | "Write weight should be at least 1 µs." 51 | ); 52 | // At most 1 ms. 53 | assert!( 54 | W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, 55 | "Read weight should be at most 1 ms." 56 | ); 57 | assert!( 58 | W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, 59 | "Write weight should be at most 1 ms." 60 | ); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /parachain-runtime/src/xcm_config.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, 3 | Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, 4 | }; 5 | use frame_support::{ 6 | parameter_types, 7 | traits::{ConstU32, Contains, Everything, Nothing}, 8 | weights::Weight, 9 | }; 10 | use frame_system::EnsureRoot; 11 | use pallet_xcm::XcmPassthrough; 12 | use polkadot_runtime_common::impls::ToAuthor; 13 | use xcm::latest::prelude::*; 14 | #[allow(deprecated)] 15 | use xcm_builder::CurrencyAdapter; 16 | use xcm_builder::{ 17 | AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, 18 | DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, 19 | FrameTransactionalProcessor, IsConcrete, NativeAsset, ParentIsPreset, RelayChainAsNative, 20 | SiblingParachainAsNative, SignedAccountId32AsNative, SignedToAccountId32, 21 | SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, 22 | WithComputedOrigin, WithUniqueTopic, 23 | }; 24 | use xcm_executor::XcmExecutor; 25 | 26 | parameter_types! { 27 | pub const TokenLocation: Location = Here.into_location(); 28 | pub const RelayLocation: Location = Location::parent(); 29 | pub const RelayNetwork: Option = None; 30 | pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); 31 | pub UniversalLocation: InteriorLocation = Parachain(ParachainInfo::parachain_id().into()).into(); 32 | } 33 | 34 | /// Type for specifying how a `Location` can be converted into an `AccountId`. This is used 35 | /// when determining ownership of accounts for asset transacting and when attempting to use XCM 36 | /// `Transact` in order to determine the dispatch Origin. 37 | pub type LocationToAccountId = ( 38 | // Straight up local `AccountId32` origins just alias directly to `AccountId`. 39 | AccountId32Aliases, 40 | // The parent (Relay-chain) origin converts to the parent `AccountId`. 41 | ParentIsPreset, 42 | ); 43 | 44 | /// Means for transacting assets on this chain. 45 | #[allow(deprecated)] 46 | pub type LocalAssetTransactor = CurrencyAdapter< 47 | // Use this currency: 48 | Balances, 49 | // Use this currency when it is a fungible asset matching the given location or name: 50 | IsConcrete, 51 | // Do a simple punn to convert an AccountId32 Location into a native chain account ID: 52 | LocationToAccountId, 53 | // Our chain's account ID type (we can't get away without mentioning it explicitly): 54 | AccountId, 55 | // We don't track any teleports. 56 | (), 57 | >; 58 | 59 | #[allow(deprecated)] 60 | pub type LocalBalancesTransactor = 61 | CurrencyAdapter, LocationToAccountId, AccountId, ()>; 62 | 63 | pub type AssetTransactors = (LocalBalancesTransactor, LocalAssetTransactor); 64 | 65 | /// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, 66 | /// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can 67 | /// biases the kind of local `Origin` it will become. 68 | pub type XcmOriginToTransactDispatchOrigin = ( 69 | // Sovereign account converter; this attempts to derive an `AccountId` from the origin location 70 | // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for 71 | // foreign chains who want to have a local sovereign account on this chain which they control. 72 | SovereignSignedViaLocation, 73 | // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when 74 | // recognized. 75 | RelayChainAsNative, 76 | // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when 77 | // recognized. 78 | SiblingParachainAsNative, 79 | // Native signed account converter; this just converts an `AccountId32` origin into a normal 80 | // `RuntimeOrigin::Signed` origin of the same 32-byte value. 81 | SignedAccountId32AsNative, 82 | // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. 83 | XcmPassthrough, 84 | ); 85 | 86 | parameter_types! { 87 | // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. 88 | pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); 89 | pub const MaxInstructions: u32 = 100; 90 | pub const MaxAssetsIntoHolding: u32 = 64; 91 | } 92 | 93 | pub struct ParentOrParentsPlurality; 94 | impl Contains for ParentOrParentsPlurality { 95 | fn contains(location: &Location) -> bool { 96 | matches!(location.unpack(), (1, []) | (1, [Plurality { .. }])) 97 | } 98 | } 99 | 100 | pub type Barrier = TrailingSetTopicAsId< 101 | DenyThenTry< 102 | DenyReserveTransferToRelayChain, 103 | ( 104 | TakeWeightCredit, 105 | WithComputedOrigin< 106 | ( 107 | AllowTopLevelPaidExecutionFrom, 108 | AllowExplicitUnpaidExecutionFrom, 109 | // ^^^ Parent and its exec plurality get free execution 110 | ), 111 | UniversalLocation, 112 | ConstU32<8>, 113 | >, 114 | ), 115 | >, 116 | >; 117 | 118 | pub struct XcmConfig; 119 | impl xcm_executor::Config for XcmConfig { 120 | type RuntimeCall = RuntimeCall; 121 | type XcmSender = XcmRouter; 122 | type AssetTransactor = AssetTransactors; 123 | type OriginConverter = XcmOriginToTransactDispatchOrigin; 124 | type IsReserve = NativeAsset; 125 | type IsTeleporter = (); // Teleporting is disabled. 126 | type UniversalLocation = UniversalLocation; 127 | type Barrier = Barrier; 128 | type Weigher = FixedWeightBounds; 129 | type Trader = 130 | UsingComponents>; 131 | type ResponseHandler = PolkadotXcm; 132 | type AssetTrap = PolkadotXcm; 133 | type AssetClaims = PolkadotXcm; 134 | type SubscriptionService = PolkadotXcm; 135 | type PalletInstancesInfo = AllPalletsWithSystem; 136 | type MaxAssetsIntoHolding = MaxAssetsIntoHolding; 137 | type AssetLocker = (); 138 | type AssetExchanger = (); 139 | type FeeManager = (); 140 | type MessageExporter = (); 141 | type UniversalAliases = Nothing; 142 | type CallDispatcher = RuntimeCall; 143 | type SafeCallFilter = Everything; 144 | type Aliasers = Nothing; 145 | type TransactionalProcessor = FrameTransactionalProcessor; 146 | type HrmpNewChannelOpenRequestHandler = (); 147 | type HrmpChannelAcceptedHandler = (); 148 | type HrmpChannelClosingHandler = (); 149 | type XcmRecorder = PolkadotXcm; 150 | } 151 | 152 | /// No local origins on this chain are allowed to dispatch XCM sends/executions. 153 | pub type LocalOriginToLocation = SignedToAccountId32; 154 | 155 | /// The means for routing XCM messages which are not for local execution into the right message 156 | /// queues. 157 | pub type XcmRouter = WithUniqueTopic<( 158 | // Two routers - use UMP to communicate with the relay chain: 159 | cumulus_primitives_utility::ParentAsUmp, 160 | // ..and XCMP to communicate with the sibling chains. 161 | XcmpQueue, 162 | )>; 163 | 164 | #[cfg(feature = "runtime-benchmarks")] 165 | parameter_types! { 166 | pub ReachableDest: Option = Some(Parent.into()); 167 | } 168 | 169 | impl pallet_xcm::Config for Runtime { 170 | type RuntimeEvent = RuntimeEvent; 171 | type SendXcmOrigin = EnsureXcmOrigin; 172 | type XcmRouter = XcmRouter; 173 | type ExecuteXcmOrigin = EnsureXcmOrigin; 174 | type XcmExecuteFilter = Everything; 175 | type XcmExecutor = XcmExecutor; 176 | type XcmTeleportFilter = Everything; 177 | type XcmReserveTransferFilter = Nothing; 178 | type Weigher = FixedWeightBounds; 179 | type UniversalLocation = UniversalLocation; 180 | type RuntimeOrigin = RuntimeOrigin; 181 | type RuntimeCall = RuntimeCall; 182 | 183 | const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; 184 | // ^ Override for AdvertisedXcmVersion default 185 | type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; 186 | type Currency = Balances; 187 | type CurrencyMatcher = (); 188 | type TrustedLockers = (); 189 | type SovereignAccountOf = LocationToAccountId; 190 | type MaxLockers = ConstU32<8>; 191 | type WeightInfo = pallet_xcm::TestWeightInfo; 192 | type AdminOrigin = EnsureRoot; 193 | type MaxRemoteLockConsumers = ConstU32<0>; 194 | type RemoteLockConsumerIdentifier = (); 195 | } 196 | 197 | impl cumulus_pallet_xcm::Config for Runtime { 198 | type RuntimeEvent = RuntimeEvent; 199 | type XcmExecutor = XcmExecutor; 200 | } 201 | -------------------------------------------------------------------------------- /runtime/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "contracts-node-runtime" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | description = "Runtime configured for smart contracts via `pallet-contracts` and `pallet-revive`." 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | build = "build.rs" 11 | 12 | [package.metadata.docs.rs] 13 | targets = ["x86_64-unknown-linux-gnu"] 14 | 15 | [dependencies] 16 | codec = { features = ["derive"], workspace = true } 17 | scale-info = { workspace = true } 18 | 19 | frame-executive = { workspace = true } 20 | frame-support = { workspace = true } 21 | frame-system = { workspace = true } 22 | frame-system-rpc-runtime-api = { workspace = true } 23 | frame-try-runtime = { workspace = true, optional = true } 24 | pallet-aura = { workspace = true } 25 | pallet-balances = { workspace = true } 26 | pallet-grandpa = { workspace = true } 27 | pallet-sudo = { workspace = true } 28 | pallet-timestamp = { workspace = true } 29 | pallet-transaction-payment = { workspace = true } 30 | pallet-transaction-payment-rpc-runtime-api = { workspace = true } 31 | sp-api = { workspace = true } 32 | sp-block-builder = { workspace = true } 33 | sp-consensus-aura = { workspace = true } 34 | sp-consensus-grandpa = { workspace = true } 35 | sp-core = { workspace = true } 36 | sp-genesis-builder = { workspace = true } 37 | sp-inherents = { workspace = true } 38 | sp-offchain = { workspace = true } 39 | sp-runtime = { workspace = true } 40 | sp-session = { workspace = true } 41 | sp-storage = { workspace = true } 42 | sp-transaction-pool = { workspace = true } 43 | sp-version = { workspace = true } 44 | 45 | # Polkadot 46 | polkadot-runtime-common = { workspace = true } 47 | 48 | # extra deps for setting up pallet-contracts and pallet-revive 49 | pallet-assets = { workspace = true } 50 | pallet-authorship = { workspace = true } 51 | pallet-insecure-randomness-collective-flip = { workspace = true } 52 | pallet-revive = { workspace = true } 53 | pallet-contracts = { workspace = true } 54 | pallet-utility = { workspace = true } 55 | 56 | # Used for runtime benchmarking 57 | frame-benchmarking = { workspace = true, optional = true } 58 | frame-system-benchmarking = { workspace = true, optional = true } 59 | 60 | [build-dependencies] 61 | substrate-wasm-builder = { workspace = true, optional = true } 62 | 63 | [features] 64 | default = ["std"] 65 | std = [ 66 | "codec/std", 67 | "frame-benchmarking?/std", 68 | "frame-executive/std", 69 | "frame-support/std", 70 | "frame-system-benchmarking?/std", 71 | "frame-system-rpc-runtime-api/std", 72 | "frame-system/std", 73 | "frame-try-runtime?/std", 74 | "pallet-assets/std", 75 | "pallet-aura/std", 76 | "pallet-authorship/std", 77 | "pallet-balances/std", 78 | "pallet-grandpa/std", 79 | "pallet-insecure-randomness-collective-flip/std", 80 | "pallet-revive/std", 81 | "pallet-contracts/std", 82 | "pallet-sudo/std", 83 | "pallet-timestamp/std", 84 | "pallet-transaction-payment-rpc-runtime-api/std", 85 | "pallet-transaction-payment/std", 86 | "scale-info/std", 87 | "sp-api/std", 88 | "sp-block-builder/std", 89 | "sp-consensus-aura/std", 90 | "sp-consensus-grandpa/std", 91 | "sp-core/std", 92 | "sp-genesis-builder/std", 93 | "sp-inherents/std", 94 | "sp-offchain/std", 95 | "sp-runtime/std", 96 | "sp-session/std", 97 | "sp-storage/std", 98 | "sp-transaction-pool/std", 99 | "sp-version/std", 100 | "polkadot-runtime-common/std", 101 | "substrate-wasm-builder", 102 | ] 103 | runtime-benchmarks = [ 104 | "frame-benchmarking/runtime-benchmarks", 105 | "frame-support/runtime-benchmarks", 106 | "frame-system-benchmarking/runtime-benchmarks", 107 | "frame-system/runtime-benchmarks", 108 | "pallet-balances/runtime-benchmarks", 109 | "pallet-grandpa/runtime-benchmarks", 110 | "pallet-sudo/runtime-benchmarks", 111 | "pallet-timestamp/runtime-benchmarks", 112 | "pallet-assets/runtime-benchmarks", 113 | "sp-runtime/runtime-benchmarks", 114 | ] 115 | try-runtime = [ 116 | "frame-executive/try-runtime", 117 | "frame-support/try-runtime", 118 | "frame-system/try-runtime", 119 | "frame-try-runtime/try-runtime", 120 | "pallet-assets/try-runtime", 121 | "pallet-aura/try-runtime", 122 | "pallet-balances/try-runtime", 123 | "pallet-grandpa/try-runtime", 124 | "pallet-sudo/try-runtime", 125 | "pallet-timestamp/try-runtime", 126 | "pallet-transaction-payment/try-runtime", 127 | "pallet-revive/try-runtime", 128 | "pallet-contracts/try-runtime", 129 | "sp-runtime/try-runtime", 130 | ] 131 | parachain = [] 132 | -------------------------------------------------------------------------------- /runtime/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | #[cfg(feature = "std")] 3 | { 4 | substrate_wasm_builder::WasmBuilder::new() 5 | .with_current_project() 6 | .export_heap_base() 7 | .import_memory() 8 | .build(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /runtime/src/assets_config.rs: -------------------------------------------------------------------------------- 1 | use crate::{AccountId, Balance, Balances, Runtime, RuntimeEvent}; 2 | use frame_support::{ 3 | parameter_types, 4 | traits::{AsEnsureOriginWithArg, ConstU128, ConstU32}, 5 | }; 6 | use frame_system::EnsureSigned; 7 | 8 | pub const MILLICENTS: Balance = 1_000_000_000; 9 | pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. 10 | pub const DOLLARS: Balance = 100 * CENTS; 11 | 12 | parameter_types! { 13 | pub const AssetDeposit: Balance = 100 * DOLLARS; 14 | pub const ApprovalDeposit: Balance = 1 * DOLLARS; 15 | pub const StringLimit: u32 = 50; 16 | pub const MetadataDepositBase: Balance = 10 * DOLLARS; 17 | pub const MetadataDepositPerByte: Balance = 1 * DOLLARS; 18 | } 19 | 20 | impl pallet_assets::Config for Runtime { 21 | type RuntimeEvent = RuntimeEvent; 22 | type Balance = u128; 23 | type AssetId = u32; 24 | type AssetIdParameter = codec::Compact; 25 | type CreateOrigin = AsEnsureOriginWithArg>; 26 | type Currency = Balances; 27 | type ForceOrigin = frame_system::EnsureRoot; 28 | type AssetDeposit = AssetDeposit; 29 | type AssetAccountDeposit = ConstU128; 30 | type MetadataDepositBase = MetadataDepositBase; 31 | type MetadataDepositPerByte = MetadataDepositPerByte; 32 | type ApprovalDeposit = ApprovalDeposit; 33 | type StringLimit = StringLimit; 34 | type Freezer = (); 35 | type Extra = (); 36 | type WeightInfo = pallet_assets::weights::SubstrateWeight; 37 | type RemoveItemsLimit = ConstU32<1000>; 38 | type CallbackHandle = (); 39 | #[cfg(feature = "runtime-benchmarks")] 40 | type BenchmarkHelper = (); 41 | } 42 | -------------------------------------------------------------------------------- /runtime/src/contracts_config.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | Balance, Balances, BalancesCall, Perbill, RandomnessCollectiveFlip, Runtime, RuntimeCall, 3 | RuntimeEvent, RuntimeHoldReason, Timestamp, 4 | }; 5 | use frame_support::{ 6 | parameter_types, 7 | traits::{ConstBool, ConstU32}, 8 | }; 9 | use frame_system::EnsureSigned; 10 | 11 | pub enum AllowBalancesCall {} 12 | 13 | impl frame_support::traits::Contains for AllowBalancesCall { 14 | fn contains(call: &RuntimeCall) -> bool { 15 | matches!(call, RuntimeCall::Balances(BalancesCall::transfer_allow_death { .. })) 16 | } 17 | } 18 | 19 | // Unit = the base number of indivisible units for balances 20 | const UNIT: Balance = 1_000_000_000_000; 21 | const MILLIUNIT: Balance = 1_000_000_000; 22 | 23 | const fn deposit(items: u32, bytes: u32) -> Balance { 24 | (items as Balance * UNIT + (bytes as Balance) * (5 * MILLIUNIT / 100)) / 10 25 | } 26 | 27 | fn schedule() -> pallet_contracts::Schedule { 28 | pallet_contracts::Schedule { 29 | limits: pallet_contracts::Limits { 30 | runtime_memory: 1024 * 1024 * 1024, 31 | validator_runtime_memory: 1024 * 1024 * 1024 * 2, 32 | ..Default::default() 33 | }, 34 | ..Default::default() 35 | } 36 | } 37 | 38 | parameter_types! { 39 | pub const DepositPerItem: Balance = deposit(1, 0); 40 | pub const DepositPerByte: Balance = deposit(0, 1); 41 | pub Schedule: pallet_contracts::Schedule = schedule::(); 42 | pub const DefaultDepositLimit: Balance = deposit(1024, 1024 * 1024); 43 | pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0); 44 | pub const MaxDelegateDependencies: u32 = 32; 45 | } 46 | 47 | impl pallet_contracts::Config for Runtime { 48 | type Time = Timestamp; 49 | type Randomness = RandomnessCollectiveFlip; 50 | type Currency = Balances; 51 | type RuntimeEvent = RuntimeEvent; 52 | type RuntimeCall = RuntimeCall; 53 | 54 | /// The safest default is to allow no calls at all. 55 | /// 56 | /// Runtimes should whitelist dispatchables that are allowed to be called from contracts 57 | /// and make sure they are stable. Dispatchables exposed to contracts are not allowed to 58 | /// change because that would break already deployed contracts. The `RuntimeCall` structure 59 | /// itself is not allowed to change the indices of existing pallets, too. 60 | type CallFilter = AllowBalancesCall; 61 | type DepositPerItem = DepositPerItem; 62 | type DepositPerByte = DepositPerByte; 63 | type CallStack = [pallet_contracts::Frame; 23]; 64 | type WeightPrice = pallet_transaction_payment::Pallet; 65 | type WeightInfo = pallet_contracts::weights::SubstrateWeight; 66 | type ChainExtension = (); 67 | type Schedule = Schedule; 68 | type AddressGenerator = pallet_contracts::DefaultAddressGenerator; 69 | // This node is geared towards development and testing of contracts. 70 | // We decided to increase the default allowed contract size for this 71 | // reason (the default is `128 * 1024`). 72 | // 73 | // Our reasoning is that the error code `CodeTooLarge` is thrown 74 | // if a too-large contract is uploaded. We noticed that it poses 75 | // less friction during development when the requirement here is 76 | // just more lax. 77 | type MaxCodeLen = ConstU32<{ 256 * 1024 }>; 78 | type DefaultDepositLimit = DefaultDepositLimit; 79 | type MaxStorageKeyLen = ConstU32<128>; 80 | type MaxTransientStorageSize = ConstU32<{ 1024 * 1024 }>; 81 | type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; 82 | type UnsafeUnstableInterface = ConstBool; 83 | type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; 84 | type MaxDelegateDependencies = MaxDelegateDependencies; 85 | type RuntimeHoldReason = RuntimeHoldReason; 86 | 87 | type Environment = (); 88 | type Debug = (); 89 | type ApiVersion = (); 90 | type Migrations = (); 91 | #[cfg(feature = "parachain")] 92 | type Xcm = pallet_xcm::Pallet; 93 | #[cfg(not(feature = "parachain"))] 94 | type Xcm = (); 95 | 96 | type UploadOrigin = EnsureSigned; 97 | type InstantiateOrigin = EnsureSigned; 98 | } 99 | -------------------------------------------------------------------------------- /runtime/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. 3 | #![recursion_limit = "256"] 4 | 5 | // Make the WASM binary available. 6 | #[cfg(feature = "std")] 7 | include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); 8 | 9 | mod assets_config; 10 | mod contracts_config; 11 | mod revive_config; 12 | 13 | extern crate alloc; 14 | use alloc::vec::Vec; 15 | use frame_support::{ 16 | derive_impl, 17 | dispatch::DispatchClass, 18 | genesis_builder_helper::{build_state, get_preset}, 19 | }; 20 | use frame_system::limits::{BlockLength, BlockWeights}; 21 | use polkadot_runtime_common::SlowAdjustingFeeUpdate; 22 | use sp_api::impl_runtime_apis; 23 | use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; 24 | use sp_runtime::{ 25 | create_runtime_str, generic, impl_opaque_keys, 26 | traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, 27 | transaction_validity::{TransactionSource, TransactionValidity}, 28 | ApplyExtrinsicResult, MultiSignature, 29 | }; 30 | #[cfg(feature = "std")] 31 | use sp_version::NativeVersion; 32 | use sp_version::RuntimeVersion; 33 | 34 | // A few exports that help ease life for downstream crates. 35 | pub use frame_support::{ 36 | construct_runtime, parameter_types, 37 | traits::{ 38 | AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU8, KeyOwnerProofSystem, 39 | Randomness, StorageInfo, 40 | }, 41 | weights::{ 42 | constants::{ 43 | BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, 44 | }, 45 | IdentityFee, Weight, 46 | }, 47 | StorageValue, 48 | }; 49 | pub use frame_system::Call as SystemCall; 50 | pub use pallet_balances::Call as BalancesCall; 51 | pub use pallet_timestamp::Call as TimestampCall; 52 | use pallet_transaction_payment::FungibleAdapter; 53 | #[cfg(any(feature = "std", test))] 54 | pub use sp_runtime::BuildStorage; 55 | pub use sp_runtime::{Perbill, Permill}; 56 | 57 | /// An index to a block. 58 | pub type BlockNumber = u32; 59 | 60 | /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. 61 | pub type Signature = MultiSignature; 62 | 63 | /// Some way of identifying an account on the chain. We intentionally make it equivalent 64 | /// to the public key of our transaction signing scheme. 65 | pub type AccountId = <::Signer as IdentifyAccount>::AccountId; 66 | 67 | /// Balance of an account. 68 | pub type Balance = u128; 69 | 70 | /// Index of a transaction in the chain. 71 | pub type Nonce = u32; 72 | 73 | /// A hash of some data used by the chain. 74 | pub type Hash = sp_core::H256; 75 | 76 | /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know 77 | /// the specifics of the runtime. They can then be made to be agnostic over specific formats 78 | /// of data like extrinsics, allowing for them to continue syncing the network through upgrades 79 | /// to even the core data structures. 80 | pub mod opaque { 81 | use super::*; 82 | 83 | pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; 84 | 85 | /// Opaque block header type. 86 | pub type Header = generic::Header; 87 | /// Opaque block type. 88 | pub type Block = generic::Block; 89 | /// Opaque block identifier type. 90 | pub type BlockId = generic::BlockId; 91 | 92 | impl_opaque_keys! { 93 | pub struct SessionKeys {} 94 | } 95 | } 96 | // To learn more about runtime versioning, see: 97 | // https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning 98 | #[sp_version::runtime_version] 99 | pub const VERSION: RuntimeVersion = RuntimeVersion { 100 | spec_name: create_runtime_str!("substrate-contracts-node"), 101 | impl_name: create_runtime_str!("substrate-contracts-node"), 102 | authoring_version: 1, 103 | // The version of the runtime specification. A full node will not attempt to use its native 104 | // runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, 105 | // `spec_version`, and `authoring_version` are the same between Wasm and native. 106 | // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use 107 | // the compatible custom types. 108 | spec_version: 100, 109 | impl_version: 1, 110 | apis: RUNTIME_API_VERSIONS, 111 | transaction_version: 1, 112 | state_version: 1, 113 | }; 114 | 115 | /// The version information used to identify this runtime when compiled natively. 116 | #[cfg(feature = "std")] 117 | pub fn native_version() -> NativeVersion { 118 | NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } 119 | } 120 | 121 | const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); 122 | 123 | /// We assume that ~10% of the block weight is consumed by `on_initialize` handlers. 124 | /// This is used to limit the maximal weight of a single extrinsic. 125 | const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); 126 | 127 | /// We allow for 2 seconds of compute with a 6 second average block time, with maximum proof size. 128 | const MAXIMUM_BLOCK_WEIGHT: Weight = 129 | Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX); 130 | 131 | // Prints debug output of the `revive` pallet to stdout if the node is 132 | // started with `-lruntime::revive=trace` or `-lruntime::contracts=debug`. 133 | const CONTRACTS_DEBUG_OUTPUT: pallet_contracts::DebugInfo = 134 | pallet_contracts::DebugInfo::UnsafeDebug; 135 | const CONTRACTS_EVENTS: pallet_contracts::CollectEvents = 136 | pallet_contracts::CollectEvents::UnsafeCollect; 137 | const REVIVE_DEBUG_OUTPUT: pallet_revive::DebugInfo = pallet_revive::DebugInfo::UnsafeDebug; 138 | const REVIVE_EVENTS: pallet_revive::CollectEvents = pallet_revive::CollectEvents::UnsafeCollect; 139 | 140 | // Unit = the base number of indivisible units for balances 141 | const MILLIUNIT: Balance = 1_000_000_000; 142 | pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT; 143 | 144 | impl pallet_insecure_randomness_collective_flip::Config for Runtime {} 145 | 146 | parameter_types! { 147 | pub const BlockHashCount: BlockNumber = 2400; 148 | pub const Version: RuntimeVersion = VERSION; 149 | 150 | // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`. 151 | // The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the 152 | // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize 153 | // the lazy contract deletion. 154 | pub RuntimeBlockLength: BlockLength = 155 | BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); 156 | pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() 157 | .base_block(BlockExecutionWeight::get()) 158 | .for_class(DispatchClass::all(), |weights| { 159 | weights.base_extrinsic = ExtrinsicBaseWeight::get(); 160 | }) 161 | .for_class(DispatchClass::Normal, |weights| { 162 | weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); 163 | }) 164 | .for_class(DispatchClass::Operational, |weights| { 165 | weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); 166 | // Operational transactions have some extra reserved space, so that they 167 | // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. 168 | weights.reserved = Some( 169 | MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT 170 | ); 171 | }) 172 | .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) 173 | .build_or_panic(); 174 | 175 | pub const SS58Prefix: u8 = 42; 176 | } 177 | 178 | // Configure FRAME pallets to include in runtime. 179 | 180 | #[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)] 181 | impl frame_system::Config for Runtime { 182 | /// The block type for the runtime. 183 | type Block = Block; 184 | /// Block & extrinsics weights: base values and limits. 185 | type BlockWeights = RuntimeBlockWeights; 186 | /// The maximum length of a block (in bytes). 187 | type BlockLength = RuntimeBlockLength; 188 | /// The identifier used to distinguish between accounts. 189 | type AccountId = AccountId; 190 | /// The type for storing how many extrinsics an account has signed. 191 | type Nonce = Nonce; 192 | /// The type for hashing blocks and tries. 193 | type Hash = Hash; 194 | /// Maximum number of block number to block hash mappings to keep (oldest pruned first). 195 | type BlockHashCount = BlockHashCount; 196 | /// The weight of database operations that the runtime can invoke. 197 | type DbWeight = RocksDbWeight; 198 | /// Version of the runtime. 199 | type Version = Version; 200 | /// The data to be stored in an account. 201 | type AccountData = pallet_balances::AccountData; 202 | /// This is used as an identifier of the chain. 42 is the generic substrate prefix. 203 | type SS58Prefix = SS58Prefix; 204 | type MaxConsumers = frame_support::traits::ConstU32<16>; 205 | } 206 | 207 | parameter_types! { 208 | pub const UncleGenerations: u32 = 0; 209 | } 210 | 211 | impl pallet_authorship::Config for Runtime { 212 | type FindAuthor = (); 213 | type EventHandler = (); 214 | } 215 | 216 | parameter_types! { 217 | pub const MinimumPeriod: u64 = 5; 218 | } 219 | 220 | impl pallet_timestamp::Config for Runtime { 221 | /// A timestamp: milliseconds since the unix epoch. 222 | type Moment = u64; 223 | type OnTimestampSet = (); 224 | type MinimumPeriod = MinimumPeriod; 225 | type WeightInfo = (); 226 | } 227 | 228 | parameter_types! { 229 | pub const MaxLocks: u32 = 50; 230 | pub const MaxReserves: u32 = 50; 231 | } 232 | 233 | impl pallet_balances::Config for Runtime { 234 | type MaxLocks = MaxLocks; 235 | type MaxReserves = MaxReserves; 236 | type ReserveIdentifier = [u8; 8]; 237 | /// The type for recording an account's balance. 238 | type Balance = Balance; 239 | /// The ubiquitous event type. 240 | type RuntimeEvent = RuntimeEvent; 241 | type DustRemoval = (); 242 | type ExistentialDeposit = ConstU128; 243 | type AccountStore = System; 244 | type WeightInfo = pallet_balances::weights::SubstrateWeight; 245 | type FreezeIdentifier = (); 246 | type MaxFreezes = (); 247 | type RuntimeHoldReason = RuntimeHoldReason; 248 | type RuntimeFreezeReason = RuntimeFreezeReason; 249 | } 250 | 251 | impl pallet_transaction_payment::Config for Runtime { 252 | type RuntimeEvent = RuntimeEvent; 253 | type OnChargeTransaction = FungibleAdapter; 254 | type OperationalFeeMultiplier = ConstU8<5>; 255 | type WeightToFee = IdentityFee; 256 | type LengthToFee = IdentityFee; 257 | type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; 258 | } 259 | 260 | impl pallet_sudo::Config for Runtime { 261 | type RuntimeEvent = RuntimeEvent; 262 | type RuntimeCall = RuntimeCall; 263 | type WeightInfo = pallet_sudo::weights::SubstrateWeight; 264 | } 265 | 266 | impl pallet_utility::Config for Runtime { 267 | type RuntimeEvent = RuntimeEvent; 268 | type RuntimeCall = RuntimeCall; 269 | type PalletsOrigin = OriginCaller; 270 | type WeightInfo = pallet_utility::weights::SubstrateWeight; 271 | } 272 | 273 | // Create the runtime by composing the FRAME pallets that were previously configured. 274 | #[frame_support::runtime] 275 | mod runtime { 276 | #[runtime::runtime] 277 | #[runtime::derive( 278 | RuntimeCall, 279 | RuntimeEvent, 280 | RuntimeError, 281 | RuntimeOrigin, 282 | RuntimeFreezeReason, 283 | RuntimeHoldReason, 284 | RuntimeSlashReason, 285 | RuntimeLockId, 286 | RuntimeTask 287 | )] 288 | pub struct Runtime; 289 | #[runtime::pallet_index(0)] 290 | pub type System = frame_system; 291 | #[runtime::pallet_index(1)] 292 | pub type RandomnessCollectiveFlip = pallet_insecure_randomness_collective_flip; 293 | #[runtime::pallet_index(2)] 294 | pub type Utility = pallet_utility; 295 | #[runtime::pallet_index(3)] 296 | pub type Timestamp = pallet_timestamp; 297 | #[runtime::pallet_index(4)] 298 | pub type Balances = pallet_balances; 299 | #[runtime::pallet_index(5)] 300 | pub type Authorship = pallet_authorship; 301 | #[runtime::pallet_index(6)] 302 | pub type TransactionPayment = pallet_transaction_payment; 303 | #[runtime::pallet_index(7)] 304 | pub type Sudo = pallet_sudo; 305 | #[runtime::pallet_index(8)] 306 | pub type Contracts = pallet_contracts; 307 | #[runtime::pallet_index(9)] 308 | pub type Revive = pallet_revive; 309 | #[runtime::pallet_index(10)] 310 | pub type Assets = pallet_assets; 311 | } 312 | 313 | /// The address format for describing accounts. 314 | pub type Address = sp_runtime::MultiAddress; 315 | /// Block header type as expected by this runtime. 316 | pub type Header = generic::Header; 317 | /// Block type as expected by this runtime. 318 | pub type Block = generic::Block; 319 | /// The SignedExtension to the basic transaction logic. 320 | pub type SignedExtra = ( 321 | frame_system::CheckNonZeroSender, 322 | frame_system::CheckSpecVersion, 323 | frame_system::CheckTxVersion, 324 | frame_system::CheckGenesis, 325 | frame_system::CheckEra, 326 | frame_system::CheckNonce, 327 | frame_system::CheckWeight, 328 | pallet_transaction_payment::ChargeTransactionPayment, 329 | ); 330 | /// The payload being signed in transactions. 331 | pub type SignedPayload = generic::SignedPayload; 332 | /// Unchecked extrinsic type as expected by this runtime. 333 | pub type UncheckedExtrinsic = 334 | generic::UncheckedExtrinsic; 335 | /// Executive: handles dispatch to the various modules. 336 | pub type Executive = frame_executive::Executive< 337 | Runtime, 338 | Block, 339 | frame_system::ChainContext, 340 | Runtime, 341 | AllPalletsWithSystem, 342 | >; 343 | 344 | type EventRecord = frame_system::EventRecord< 345 | ::RuntimeEvent, 346 | ::Hash, 347 | >; 348 | 349 | impl_runtime_apis! { 350 | impl sp_api::Core for Runtime { 351 | fn version() -> RuntimeVersion { 352 | VERSION 353 | } 354 | 355 | fn execute_block(block: Block) { 356 | Executive::execute_block(block); 357 | } 358 | 359 | fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { 360 | Executive::initialize_block(header) 361 | } 362 | } 363 | 364 | impl sp_api::Metadata for Runtime { 365 | fn metadata() -> OpaqueMetadata { 366 | OpaqueMetadata::new(Runtime::metadata().into()) 367 | } 368 | fn metadata_at_version(version: u32) -> Option { 369 | Runtime::metadata_at_version(version) 370 | } 371 | 372 | fn metadata_versions() -> Vec { 373 | Runtime::metadata_versions() 374 | } 375 | } 376 | 377 | impl sp_block_builder::BlockBuilder for Runtime { 378 | fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { 379 | Executive::apply_extrinsic(extrinsic) 380 | } 381 | 382 | fn finalize_block() -> ::Header { 383 | Executive::finalize_block() 384 | } 385 | 386 | fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { 387 | data.create_extrinsics() 388 | } 389 | 390 | fn check_inherents( 391 | block: Block, 392 | data: sp_inherents::InherentData, 393 | ) -> sp_inherents::CheckInherentsResult { 394 | data.check_extrinsics(&block) 395 | } 396 | } 397 | 398 | impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { 399 | fn validate_transaction( 400 | source: TransactionSource, 401 | tx: ::Extrinsic, 402 | block_hash: ::Hash, 403 | ) -> TransactionValidity { 404 | Executive::validate_transaction(source, tx, block_hash) 405 | } 406 | } 407 | 408 | impl sp_offchain::OffchainWorkerApi for Runtime { 409 | fn offchain_worker(header: &::Header) { 410 | Executive::offchain_worker(header) 411 | } 412 | } 413 | 414 | impl sp_session::SessionKeys for Runtime { 415 | fn generate_session_keys(seed: Option>) -> Vec { 416 | opaque::SessionKeys::generate(seed) 417 | } 418 | 419 | fn decode_session_keys( 420 | encoded: Vec, 421 | ) -> Option, KeyTypeId)>> { 422 | opaque::SessionKeys::decode_into_raw_public_keys(&encoded) 423 | } 424 | } 425 | 426 | impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { 427 | fn account_nonce(account: AccountId) -> Nonce { 428 | System::account_nonce(account) 429 | } 430 | } 431 | 432 | impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { 433 | fn query_info( 434 | uxt: ::Extrinsic, 435 | len: u32, 436 | ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { 437 | TransactionPayment::query_info(uxt, len) 438 | } 439 | fn query_fee_details( 440 | uxt: ::Extrinsic, 441 | len: u32, 442 | ) -> pallet_transaction_payment::FeeDetails { 443 | TransactionPayment::query_fee_details(uxt, len) 444 | } 445 | fn query_weight_to_fee(weight: Weight) -> Balance { 446 | TransactionPayment::weight_to_fee(weight) 447 | } 448 | fn query_length_to_fee(length: u32) -> Balance { 449 | TransactionPayment::length_to_fee(length) 450 | } 451 | } 452 | 453 | impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi for Runtime { 454 | fn query_call_info( 455 | call: RuntimeCall, 456 | len: u32, 457 | ) -> pallet_transaction_payment::RuntimeDispatchInfo { 458 | TransactionPayment::query_call_info(call, len) 459 | } 460 | fn query_call_fee_details( 461 | call: RuntimeCall, 462 | len: u32, 463 | ) -> pallet_transaction_payment::FeeDetails { 464 | TransactionPayment::query_call_fee_details(call, len) 465 | } 466 | fn query_weight_to_fee(weight: Weight) -> Balance { 467 | TransactionPayment::weight_to_fee(weight) 468 | } 469 | fn query_length_to_fee(length: u32) -> Balance { 470 | TransactionPayment::length_to_fee(length) 471 | } 472 | } 473 | 474 | impl pallet_contracts::ContractsApi 475 | for Runtime 476 | { 477 | fn call( 478 | origin: AccountId, 479 | dest: AccountId, 480 | value: Balance, 481 | gas_limit: Option, 482 | storage_deposit_limit: Option, 483 | input_data: Vec, 484 | ) -> pallet_contracts::ContractExecResult { 485 | let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block); 486 | Contracts::bare_call( 487 | origin, 488 | dest, 489 | value, 490 | gas_limit, 491 | storage_deposit_limit, 492 | input_data, 493 | CONTRACTS_DEBUG_OUTPUT, 494 | CONTRACTS_EVENTS, 495 | pallet_contracts::Determinism::Enforced, 496 | ) 497 | } 498 | 499 | fn instantiate( 500 | origin: AccountId, 501 | value: Balance, 502 | gas_limit: Option, 503 | storage_deposit_limit: Option, 504 | code: pallet_contracts::Code, 505 | data: Vec, 506 | salt: Vec, 507 | ) -> pallet_contracts::ContractInstantiateResult 508 | { 509 | let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block); 510 | Contracts::bare_instantiate( 511 | origin, 512 | value, 513 | gas_limit, 514 | storage_deposit_limit, 515 | code, 516 | data, 517 | salt, 518 | CONTRACTS_DEBUG_OUTPUT, 519 | CONTRACTS_EVENTS, 520 | ) 521 | } 522 | 523 | fn upload_code( 524 | origin: AccountId, 525 | code: Vec, 526 | storage_deposit_limit: Option, 527 | determinism: pallet_contracts::Determinism, 528 | ) -> pallet_contracts::CodeUploadResult 529 | { 530 | Contracts::bare_upload_code(origin, code, storage_deposit_limit, determinism) 531 | } 532 | 533 | fn get_storage( 534 | address: AccountId, 535 | key: Vec, 536 | ) -> pallet_contracts::GetStorageResult { 537 | Contracts::get_storage(address, key) 538 | } 539 | } 540 | 541 | impl pallet_revive::ReviveApi for Runtime 542 | { 543 | fn call( 544 | origin: AccountId, 545 | dest: AccountId, 546 | value: Balance, 547 | gas_limit: Option, 548 | storage_deposit_limit: Option, 549 | input_data: Vec, 550 | ) -> pallet_revive::ContractExecResult { 551 | Revive::bare_call( 552 | RuntimeOrigin::signed(origin), 553 | dest, 554 | value, 555 | gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block), 556 | storage_deposit_limit.unwrap_or(u128::MAX), 557 | input_data, 558 | REVIVE_DEBUG_OUTPUT, 559 | REVIVE_EVENTS, 560 | ) 561 | } 562 | 563 | fn instantiate( 564 | origin: AccountId, 565 | value: Balance, 566 | gas_limit: Option, 567 | storage_deposit_limit: Option, 568 | code: pallet_revive::Code, 569 | data: Vec, 570 | salt: Vec, 571 | ) -> pallet_revive::ContractInstantiateResult 572 | { 573 | Revive::bare_instantiate( 574 | RuntimeOrigin::signed(origin), 575 | value, 576 | gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block), 577 | storage_deposit_limit.unwrap_or(u128::MAX), 578 | code, 579 | data, 580 | salt, 581 | REVIVE_DEBUG_OUTPUT, 582 | REVIVE_EVENTS, 583 | ) 584 | } 585 | 586 | fn upload_code( 587 | origin: AccountId, 588 | code: Vec, 589 | storage_deposit_limit: Option, 590 | ) -> pallet_revive::CodeUploadResult 591 | { 592 | Revive::bare_upload_code( 593 | RuntimeOrigin::signed(origin), 594 | code, 595 | storage_deposit_limit.unwrap_or(u128::MAX), 596 | ) 597 | } 598 | 599 | fn get_storage( 600 | address: AccountId, 601 | key: Vec, 602 | ) -> pallet_revive::GetStorageResult { 603 | Revive::get_storage( 604 | address, 605 | key 606 | ) 607 | } 608 | } 609 | 610 | impl sp_genesis_builder::GenesisBuilder for Runtime { 611 | fn build_state(config: Vec) -> sp_genesis_builder::Result { 612 | build_state::(config) 613 | } 614 | 615 | fn get_preset(id: &Option) -> Option> { 616 | get_preset::(id, |_| None) 617 | } 618 | 619 | fn preset_names() -> Vec { 620 | Default::default() 621 | } 622 | } 623 | } 624 | -------------------------------------------------------------------------------- /runtime/src/revive_config.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | Balance, Balances, BalancesCall, Perbill, Runtime, RuntimeCall, RuntimeEvent, 3 | RuntimeHoldReason, Timestamp, 4 | }; 5 | use frame_support::{ 6 | parameter_types, 7 | traits::{ConstBool, ConstU32}, 8 | }; 9 | use frame_system::EnsureSigned; 10 | 11 | pub enum AllowBalancesCall {} 12 | 13 | impl frame_support::traits::Contains for AllowBalancesCall { 14 | fn contains(call: &RuntimeCall) -> bool { 15 | matches!(call, RuntimeCall::Balances(BalancesCall::transfer_allow_death { .. })) 16 | } 17 | } 18 | 19 | // Unit = the base number of indivisible units for balances 20 | const UNIT: Balance = 1_000_000_000_000; 21 | const MILLIUNIT: Balance = 1_000_000_000; 22 | 23 | const fn deposit(items: u32, bytes: u32) -> Balance { 24 | (items as Balance * UNIT + (bytes as Balance) * (5 * MILLIUNIT / 100)) / 10 25 | } 26 | 27 | parameter_types! { 28 | pub const DepositPerItem: Balance = deposit(1, 0); 29 | pub const DepositPerByte: Balance = deposit(0, 1); 30 | pub const DefaultDepositLimit: Balance = deposit(1024, 1024 * 1024); 31 | pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0); 32 | pub const MaxDelegateDependencies: u32 = 32; 33 | } 34 | 35 | impl pallet_revive::Config for Runtime { 36 | type Time = Timestamp; 37 | type Currency = Balances; 38 | type RuntimeEvent = RuntimeEvent; 39 | type RuntimeCall = RuntimeCall; 40 | /// The safest default is to allow no calls at all. 41 | /// 42 | /// Runtimes should whitelist dispatchables that are allowed to be called from contracts 43 | /// and make sure they are stable. Dispatchables exposed to contracts are not allowed to 44 | /// change because that would break already deployed contracts. The `RuntimeCall` structure 45 | /// itself is not allowed to change the indices of existing pallets, too. 46 | type CallFilter = AllowBalancesCall; 47 | type DepositPerItem = DepositPerItem; 48 | type DepositPerByte = DepositPerByte; 49 | type WeightPrice = pallet_transaction_payment::Pallet; 50 | type WeightInfo = pallet_revive::weights::SubstrateWeight; 51 | type ChainExtension = (); 52 | type AddressGenerator = pallet_revive::DefaultAddressGenerator; 53 | type MaxCodeLen = ConstU32<{ 123 * 1024 }>; 54 | type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>; 55 | type PVFMemory = ConstU32<{ 512 * 1024 * 1024 }>; 56 | type UnsafeUnstableInterface = ConstBool; 57 | type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; 58 | type RuntimeHoldReason = RuntimeHoldReason; 59 | type Debug = (); 60 | type Migrations = (); 61 | #[cfg(feature = "parachain")] 62 | type Xcm = pallet_xcm::Pallet; 63 | #[cfg(not(feature = "parachain"))] 64 | type Xcm = (); 65 | type UploadOrigin = EnsureSigned; 66 | type InstantiateOrigin = EnsureSigned; 67 | } 68 | -------------------------------------------------------------------------------- /scripts/ci/pre_cache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -u 4 | 5 | # if there is no directory for this $CI_COMMIT_REF_NAME/$CI_JOB_NAME 6 | # create such directory and 7 | # copy recursively all the files from the newest dir which has $CI_JOB_NAME, if it exists 8 | 9 | # cache lives in /ci-cache/${CI_PROJECT_NAME}/${2}/${CI_COMMIT_REF_NAME}/${CI_JOB_NAME} 10 | 11 | function prepopulate { 12 | if [[ ! -d $1 ]]; then 13 | mkdir -p "/ci-cache/$CI_PROJECT_NAME/$2/$CI_COMMIT_REF_NAME"; 14 | FRESH_CACHE=$(find "/ci-cache/$CI_PROJECT_NAME/$2" -mindepth 2 -maxdepth 2 \ 15 | -type d -name "$CI_JOB_NAME" -exec stat --printf="%Y\t%n\n" {} \; |sort -n -r |head -1 |cut -f2); 16 | if [[ -d $FRESH_CACHE ]]; then 17 | echo "____Using" "$FRESH_CACHE" "to prepopulate the cache____"; 18 | time cp -r "$FRESH_CACHE" "$1"; 19 | else 20 | echo "_____No such $2 dir, proceeding from scratch_____"; 21 | fi 22 | else 23 | echo "____No need to prepopulate $2 cache____"; 24 | fi 25 | } 26 | 27 | # CARGO_HOME cache is still broken so would be handled some other way. 28 | prepopulate "$CARGO_TARGET_DIR" targets 29 | -------------------------------------------------------------------------------- /zombienet.toml: -------------------------------------------------------------------------------- 1 | # This sample Zombienet configuration file can be used to spawn a local network with a relaychain 2 | # and a substrate-contracts-node parachain. 3 | # 4 | # Requirements: 5 | # - Install zombienet from https://github.com/paritytech/zombienet/releases. 6 | # - Build `polkadot`, `polkadot-execute-worker` and `polkadot-prepare-worker` from `polkadot-sdk` and make the binaries available in your path. 7 | # - Build or install `substrate-contracts-node` and make the binary available in your path. 8 | # 9 | # Usage: 10 | # zombienet spawn --provider native zombienet.toml 11 | 12 | [relaychain] 13 | chain = "rococo-local" 14 | command = "polkadot" 15 | 16 | [[relaychain.nodes]] 17 | name = "alice" 18 | args = [ "--alice", "-lerror,runtime::contracts=trace,xcm=trace,runtime::xcm=trace,runtime::xcmp=info" ] 19 | 20 | [[relaychain.nodes]] 21 | name = "bob" 22 | args = [ "--bob", "-lerror,runtime::contracts=trace,xcm=trace,runtime::xcm=trace,runtime::xcmp=info" ] 23 | 24 | [[parachains]] 25 | id = 1 26 | addToGenesis = true 27 | chain = "contracts-parachain-local" 28 | 29 | [parachains.collator] 30 | name = "collator01" 31 | ws_port = 9944 32 | command = "substrate-contracts-node" 33 | args = [ "-lerror,runtime::contracts=trace,xcm=trace,runtime::xcm=trace,runtime::xcmp=info" ] 34 | --------------------------------------------------------------------------------