├── .devcontainer └── devcontainer.json ├── .editorconfig ├── .envrc ├── .gitignore ├── .vscode └── tasks.json ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── docker-compose.yml ├── docs └── rust-setup.md ├── node ├── Cargo.toml ├── build.rs └── src │ ├── chain_spec.rs │ ├── cli.rs │ ├── command.rs │ ├── command_helper.rs │ ├── lib.rs │ ├── main.rs │ ├── rpc.rs │ └── service.rs ├── pallets └── template │ ├── Cargo.toml │ ├── README.md │ └── src │ ├── benchmarking.rs │ ├── lib.rs │ ├── mock.rs │ └── tests.rs ├── runtime ├── Cargo.toml ├── build.rs └── src │ └── lib.rs ├── rustfmt.toml ├── scripts ├── docker_run.sh └── init.sh └── shell.nix /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Substrate Node template", 3 | "context": "..", 4 | "settings": { 5 | "terminal.integrated.shell.linux": "/bin/bash", 6 | "lldb.executable": "/usr/bin/lldb" 7 | }, 8 | "extensions": [ 9 | "rust-lang.rust", 10 | "bungcip.better-toml", 11 | "vadimcn.vscode-lldb" 12 | ], 13 | "forwardPorts": [ 14 | 3000, 15 | 9944 16 | ], 17 | "onCreateCommand": ["cargo build", "cargo check"], 18 | "postStartCommand": "./target/debug/node-template --dev --ws-external", 19 | "menuActions": [ 20 | {"id": "polkadotjs", 21 | "label": "Open PolkadotJS Apps", 22 | "type": "external-preview", 23 | "args": ["https://polkadot.js.org/apps/?rpc=wss%3A%2F%2F/$HOST/wss"]} 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | # If lorri exists, better try it first. 2 | if has lorri; then 3 | eval "$(lorri direnv)" 4 | else 5 | # Otherwise fall back to pure nix 6 | use nix 7 | fi 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | # Generated by Cargo 4 | # will have compiled files and executables 5 | **/target/ 6 | # These are backup files generated by rustfmt 7 | **/*.rs.bk 8 | 9 | .DS_Store 10 | 11 | # The cache for docker container dependency 12 | .cargo 13 | 14 | # The cache for chain data in container 15 | .local 16 | 17 | # direnv cache 18 | .direnv 19 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Run ", 8 | "type": "shell", 9 | "command": "cargo", 10 | "args": ["run", "--release", "--", "--dev"], 11 | "group": { 12 | "kind": "build", 13 | "isDefault": true 14 | }, 15 | "presentation": { 16 | "reveal": "always", 17 | "panel": "new" 18 | }, 19 | "problemMatcher": [ 20 | { 21 | "owner": "rust", 22 | "fileLocation": ["relative", "${workspaceRoot}"], 23 | "pattern": { 24 | "regexp": "^(.*):(\\d+):(\\d+):\\s+(\\d+):(\\d+)\\s+(warning|error):\\s+(.*)$", 25 | "file": 1, 26 | "line": 2, 27 | "column": 3, 28 | "endLine": 4, 29 | "endColumn": 5, 30 | "severity": 6, 31 | "message": 7 32 | } 33 | } 34 | ] 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "node", 4 | "pallets/template", 5 | "runtime", 6 | ] 7 | [profile.release] 8 | panic = "unwind" 9 | -------------------------------------------------------------------------------- /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 Node Template 2 | 3 | [![Try on playground](https://img.shields.io/badge/Playground-Node_Template-brightgreen?logo=Parity%20Substrate)](https://docs.substrate.io/playground/) [![Matrix](https://img.shields.io/matrix/substrate-technical:matrix.org)](https://matrix.to/#/#substrate-technical:matrix.org) 4 | 5 | A fresh FRAME-based [Substrate](https://www.substrate.io/) node, ready for hacking :rocket: 6 | 7 | ## Getting Started 8 | 9 | Follow the steps below to get started with the Node Template, or get it up and running right from 10 | your browser in just a few clicks using 11 | the [Substrate Playground](https://docs.substrate.io/playground/) :hammer_and_wrench: 12 | 13 | ### Using Nix 14 | 15 | Install [nix](https://nixos.org/) and optionally [direnv](https://github.com/direnv/direnv) and 16 | [lorri](https://github.com/target/lorri) for a fully plug and play experience for setting up the 17 | development environment. To get all the correct dependencies activate direnv `direnv allow` and 18 | lorri `lorri shell`. 19 | 20 | ### Rust Setup 21 | 22 | First, complete the [basic Rust setup instructions](./docs/rust-setup.md). 23 | 24 | ### Run 25 | 26 | Use Rust's native `cargo` command to build and launch the template node: 27 | 28 | ```sh 29 | cargo run --release -- --dev 30 | ``` 31 | 32 | ### Build 33 | 34 | The `cargo run` command will perform an initial build. Use the following command to build the node 35 | without launching it: 36 | 37 | ```sh 38 | cargo build --release 39 | ``` 40 | 41 | ### Embedded Docs 42 | 43 | Once the project has been built, the following command can be used to explore all parameters and 44 | subcommands: 45 | 46 | ```sh 47 | ./target/release/node-template -h 48 | ``` 49 | 50 | ## Run 51 | 52 | The provided `cargo run` command will launch a temporary node and its state will be discarded after 53 | you terminate the process. After the project has been built, there are other ways to launch the 54 | node. 55 | 56 | ### Single-Node Development Chain 57 | 58 | This command will start the single-node development chain with non-persistent state: 59 | 60 | ```bash 61 | ./target/release/node-template --dev 62 | ``` 63 | 64 | Purge the development chain's state: 65 | 66 | ```bash 67 | ./target/release/node-template purge-chain --dev 68 | ``` 69 | 70 | Start the development chain with detailed logging: 71 | 72 | ```bash 73 | RUST_BACKTRACE=1 ./target/release/node-template -ldebug --dev 74 | ``` 75 | 76 | > Development chain means that the state of our chain will be in a tmp folder while the nodes are 77 | > running. Also, **alice** account will be authority and sudo account as declared in the 78 | > [genesis state](https://github.com/substrate-developer-hub/substrate-node-template/blob/main/node/src/chain_spec.rs#L49). 79 | > At the same time the following accounts will be pre-funded: 80 | > - Alice 81 | > - Bob 82 | > - Alice//stash 83 | > - Bob//stash 84 | 85 | In case of being interested in maintaining the chain' state between runs a base path must be added 86 | so the db can be stored in the provided folder instead of a temporal one. We could use this folder 87 | to store different chain databases, as a different folder will be created per different chain that 88 | is ran. The following commands shows how to use a newly created folder as our db base path. 89 | 90 | ```bash 91 | // Create a folder to use as the db base path 92 | $ mkdir my-chain-state 93 | 94 | // Use of that folder to store the chain state 95 | $ ./target/release/node-template --dev --base-path ./my-chain-state/ 96 | 97 | // Check the folder structure created inside the base path after running the chain 98 | $ ls ./my-chain-state 99 | chains 100 | $ ls ./my-chain-state/chains/ 101 | dev 102 | $ ls ./my-chain-state/chains/dev 103 | db keystore network 104 | ``` 105 | 106 | 107 | ### Connect with Polkadot-JS Apps Front-end 108 | 109 | Once the node template is running locally, you can connect it with **Polkadot-JS Apps** front-end 110 | to interact with your chain. [Click 111 | here](https://polkadot.js.org/apps/#/explorer?rpc=ws://localhost:9944) connecting the Apps to your 112 | local node template. 113 | 114 | ### Multi-Node Local Testnet 115 | 116 | If you want to see the multi-node consensus algorithm in action, refer to our 117 | [Start a Private Network tutorial](https://docs.substrate.io/tutorials/v3/private-network). 118 | 119 | ## Template Structure 120 | 121 | A Substrate project such as this consists of a number of components that are spread across a few 122 | directories. 123 | 124 | ### Node 125 | 126 | A blockchain node is an application that allows users to participate in a blockchain network. 127 | Substrate-based blockchain nodes expose a number of capabilities: 128 | 129 | - Networking: Substrate nodes use the [`libp2p`](https://libp2p.io/) networking stack to allow the 130 | nodes in the network to communicate with one another. 131 | - Consensus: Blockchains must have a way to come to 132 | [consensus](https://docs.substrate.io/v3/advanced/consensus) on the state of the 133 | network. Substrate makes it possible to supply custom consensus engines and also ships with 134 | several consensus mechanisms that have been built on top of 135 | [Web3 Foundation research](https://research.web3.foundation/en/latest/polkadot/NPoS/index.html). 136 | - RPC Server: A remote procedure call (RPC) server is used to interact with Substrate nodes. 137 | 138 | There are several files in the `node` directory - take special note of the following: 139 | 140 | - [`chain_spec.rs`](./node/src/chain_spec.rs): A 141 | [chain specification](https://docs.substrate.io/v3/runtime/chain-specs) is a 142 | source code file that defines a Substrate chain's initial (genesis) state. Chain specifications 143 | are useful for development and testing, and critical when architecting the launch of a 144 | production chain. Take note of the `development_config` and `testnet_genesis` functions, which 145 | are used to define the genesis state for the local development chain configuration. These 146 | functions identify some 147 | [well-known accounts](https://docs.substrate.io/v3/tools/subkey#well-known-keys) 148 | and use them to configure the blockchain's initial state. 149 | - [`service.rs`](./node/src/service.rs): This file defines the node implementation. Take note of 150 | the libraries that this file imports and the names of the functions it invokes. In particular, 151 | there are references to consensus-related topics, such as the 152 | [longest chain rule](https://docs.substrate.io/v3/advanced/consensus#longest-chain-rule), 153 | the [Aura](https://docs.substrate.io/v3/advanced/consensus#aura) block authoring 154 | mechanism and the 155 | [GRANDPA](https://docs.substrate.io/v3/advanced/consensus#grandpa) finality 156 | gadget. 157 | 158 | After the node has been [built](#build), refer to the embedded documentation to learn more about the 159 | capabilities and configuration parameters that it exposes: 160 | 161 | ```shell 162 | ./target/release/node-template --help 163 | ``` 164 | 165 | ### Runtime 166 | 167 | In Substrate, the terms 168 | "[runtime](https://docs.substrate.io/v3/getting-started/glossary#runtime)" and 169 | "[state transition function](https://docs.substrate.io/v3/getting-started/glossary#state-transition-function-stf)" 170 | are analogous - they refer to the core logic of the blockchain that is responsible for validating 171 | blocks and executing the state changes they define. The Substrate project in this repository uses 172 | the [FRAME](https://docs.substrate.io/v3/runtime/frame) framework to construct a 173 | blockchain runtime. FRAME allows runtime developers to declare domain-specific logic in modules 174 | called "pallets". At the heart of FRAME is a helpful 175 | [macro language](https://docs.substrate.io/v3/runtime/macros) that makes it easy to 176 | create pallets and flexibly compose them to create blockchains that can address 177 | [a variety of needs](https://www.substrate.io/substrate-users/). 178 | 179 | Review the [FRAME runtime implementation](./runtime/src/lib.rs) included in this template and note 180 | the following: 181 | 182 | - This file configures several pallets to include in the runtime. Each pallet configuration is 183 | defined by a code block that begins with `impl $PALLET_NAME::Config for Runtime`. 184 | - The pallets are composed into a single runtime by way of the 185 | [`construct_runtime!`](https://crates.parity.io/frame_support/macro.construct_runtime.html) 186 | macro, which is part of the core 187 | [FRAME Support](https://docs.substrate.io/v3/runtime/frame#support-crate) 188 | library. 189 | 190 | ### Pallets 191 | 192 | The runtime in this project is constructed using many FRAME pallets that ship with the 193 | [core Substrate repository](https://github.com/paritytech/substrate/tree/master/frame) and a 194 | template pallet that is [defined in the `pallets`](./pallets/template/src/lib.rs) directory. 195 | 196 | A FRAME pallet is comprised of a number of blockchain primitives: 197 | 198 | - Storage: FRAME defines a rich set of powerful 199 | [storage abstractions](https://docs.substrate.io/v3/runtime/storage) that makes 200 | it easy to use Substrate's efficient key-value database to manage the evolving state of a 201 | blockchain. 202 | - Dispatchables: FRAME pallets define special types of functions that can be invoked (dispatched) 203 | from outside of the runtime in order to update its state. 204 | - Events: Substrate uses [events and errors](https://docs.substrate.io/v3/runtime/events-and-errors) 205 | to notify users of important changes in the runtime. 206 | - Errors: When a dispatchable fails, it returns an error. 207 | - Config: The `Config` configuration interface is used to define the types and parameters upon 208 | which a FRAME pallet depends. 209 | 210 | ### Run in Docker 211 | 212 | First, install [Docker](https://docs.docker.com/get-docker/) and 213 | [Docker Compose](https://docs.docker.com/compose/install/). 214 | 215 | Then run the following command to start a single node development chain. 216 | 217 | ```bash 218 | ./scripts/docker_run.sh 219 | ``` 220 | 221 | This command will firstly compile your code, and then start a local development network. You can 222 | also replace the default command 223 | (`cargo build --release && ./target/release/node-template --dev --ws-external`) 224 | by appending your own. A few useful ones are as follow. 225 | 226 | ```bash 227 | # Run Substrate node without re-compiling 228 | ./scripts/docker_run.sh ./target/release/node-template --dev --ws-external 229 | 230 | # Purge the local dev chain 231 | ./scripts/docker_run.sh ./target/release/node-template purge-chain --dev 232 | 233 | # Check whether the code is compilable 234 | ./scripts/docker_run.sh cargo check 235 | ``` 236 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.2" 2 | 3 | services: 4 | dev: 5 | container_name: node-template 6 | image: paritytech/ci-linux:974ba3ac-20201006 7 | working_dir: /var/www/node-template 8 | ports: 9 | - "9944:9944" 10 | environment: 11 | - CARGO_HOME=/var/www/node-template/.cargo 12 | volumes: 13 | - .:/var/www/node-template 14 | - type: bind 15 | source: ./.local 16 | target: /root/.local 17 | command: bash -c "cargo build --release && ./target/release/node-template --dev --ws-external" 18 | -------------------------------------------------------------------------------- /docs/rust-setup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | --- 4 | 5 | This guide is for reference only, please check the latest information on getting starting with Substrate 6 | [here](https://docs.substrate.io/v3/getting-started/installation/). 7 | 8 | This page will guide you through the **2 steps** needed to prepare a computer for **Substrate** development. 9 | Since Substrate is built with [the Rust programming language](https://www.rust-lang.org/), the first 10 | thing you will need to do is prepare the computer for Rust development - these steps will vary based 11 | on the computer's operating system. Once Rust is configured, you will use its toolchains to interact 12 | with Rust projects; the commands for Rust's toolchains will be the same for all supported, 13 | Unix-based operating systems. 14 | 15 | ## Build dependencies 16 | 17 | Substrate development is easiest on Unix-based operating systems like macOS or Linux. The examples 18 | in the [Substrate Docs](https://docs.substrate.io) use Unix-style terminals to demonstrate how to 19 | interact with Substrate from the command line. 20 | 21 | ### Ubuntu/Debian 22 | 23 | Use a terminal shell to execute the following commands: 24 | 25 | ```bash 26 | sudo apt update 27 | # May prompt for location information 28 | sudo apt install -y git clang curl libssl-dev llvm libudev-dev 29 | ``` 30 | 31 | ### Arch Linux 32 | 33 | Run these commands from a terminal: 34 | 35 | ```bash 36 | pacman -Syu --needed --noconfirm curl git clang 37 | ``` 38 | 39 | ### Fedora 40 | 41 | Run these commands from a terminal: 42 | 43 | ```bash 44 | sudo dnf update 45 | sudo dnf install clang curl git openssl-devel 46 | ``` 47 | 48 | ### OpenSUSE 49 | 50 | Run these commands from a terminal: 51 | 52 | ```bash 53 | sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel 54 | ``` 55 | 56 | ### macOS 57 | 58 | > **Apple M1 ARM** 59 | > If you have an Apple M1 ARM system on a chip, make sure that you have Apple Rosetta 2 60 | > installed through `softwareupdate --install-rosetta`. This is only needed to run the 61 | > `protoc` tool during the build. The build itself and the target binaries would remain native. 62 | 63 | Open the Terminal application and execute the following commands: 64 | 65 | ```bash 66 | # Install Homebrew if necessary https://brew.sh/ 67 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" 68 | 69 | # Make sure Homebrew is up-to-date, install openssl 70 | brew update 71 | brew install openssl 72 | ``` 73 | 74 | ### Windows 75 | 76 | **_PLEASE NOTE:_** Native development of Substrate is _not_ very well supported! It is _highly_ 77 | recommend to use [Windows Subsystem Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10) 78 | (WSL) and follow the instructions for [Ubuntu/Debian](#ubuntudebian). 79 | Please refer to the separate 80 | [guide for native Windows development](https://docs.substrate.io/v3/getting-started/windows-users/). 81 | 82 | ## Rust developer environment 83 | 84 | This guide uses installer and the `rustup` tool to manage the Rust toolchain. 85 | First install and configure `rustup`: 86 | 87 | ```bash 88 | # Install 89 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 90 | # Configure 91 | source ~/.cargo/env 92 | ``` 93 | 94 | Configure the Rust toolchain to default to the latest stable version, add nightly and the nightly wasm target: 95 | 96 | ```bash 97 | rustup default stable 98 | rustup update 99 | rustup update nightly 100 | rustup target add wasm32-unknown-unknown --toolchain nightly 101 | ``` 102 | 103 | ## Test your set-up 104 | 105 | Now the best way to ensure that you have successfully prepared a computer for Substrate 106 | development is to follow the steps in [our first Substrate tutorial](https://docs.substrate.io/tutorials/v3/create-your-first-substrate-chain/). 107 | 108 | ## Troubleshooting Substrate builds 109 | 110 | Sometimes you can't get the Substrate node template 111 | to compile out of the box. Here are some tips to help you work through that. 112 | 113 | ### Rust configuration check 114 | 115 | To see what Rust toolchain you are presently using, run: 116 | 117 | ```bash 118 | rustup show 119 | ``` 120 | 121 | This will show something like this (Ubuntu example) output: 122 | 123 | ```text 124 | Default host: x86_64-unknown-linux-gnu 125 | rustup home: /home/user/.rustup 126 | 127 | installed toolchains 128 | -------------------- 129 | 130 | stable-x86_64-unknown-linux-gnu (default) 131 | nightly-2020-10-06-x86_64-unknown-linux-gnu 132 | nightly-x86_64-unknown-linux-gnu 133 | 134 | installed targets for active toolchain 135 | -------------------------------------- 136 | 137 | wasm32-unknown-unknown 138 | x86_64-unknown-linux-gnu 139 | 140 | active toolchain 141 | ---------------- 142 | 143 | stable-x86_64-unknown-linux-gnu (default) 144 | rustc 1.50.0 (cb75ad5db 2021-02-10) 145 | ``` 146 | 147 | As you can see above, the default toolchain is stable, and the 148 | `nightly-x86_64-unknown-linux-gnu` toolchain as well as its `wasm32-unknown-unknown` target is installed. 149 | You also see that `nightly-2020-10-06-x86_64-unknown-linux-gnu` is installed, but is not used unless explicitly defined as illustrated in the [specify your nightly version](#specifying-nightly-version) 150 | section. 151 | 152 | ### WebAssembly compilation 153 | 154 | Substrate uses [WebAssembly](https://webassembly.org) (Wasm) to produce portable blockchain 155 | runtimes. You will need to configure your Rust compiler to use 156 | [`nightly` builds](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html) to allow you to 157 | compile Substrate runtime code to the Wasm target. 158 | 159 | > There are upstream issues in Rust that need to be resolved before all of Substrate can use the stable Rust toolchain. 160 | > [This is our tracking issue](https://github.com/paritytech/substrate/issues/1252) if you're curious as to why and how this will be resolved. 161 | 162 | #### Latest nightly for Substrate `master` 163 | 164 | Developers who are building Substrate _itself_ should always use the latest bug-free versions of 165 | Rust stable and nightly. This is because the Substrate codebase follows the tip of Rust nightly, 166 | which means that changes in Substrate often depend on upstream changes in the Rust nightly compiler. 167 | To ensure your Rust compiler is always up to date, you should run: 168 | 169 | ```bash 170 | rustup update 171 | rustup update nightly 172 | rustup target add wasm32-unknown-unknown --toolchain nightly 173 | ``` 174 | 175 | > NOTE: It may be necessary to occasionally rerun `rustup update` if a change in the upstream Substrate 176 | > codebase depends on a new feature of the Rust compiler. When you do this, both your nightly 177 | > and stable toolchains will be pulled to the most recent release, and for nightly, it is 178 | > generally _not_ expected to compile WASM without error (although it very often does). 179 | > Be sure to [specify your nightly version](#specifying-nightly-version) if you get WASM build errors 180 | > from `rustup` and [downgrade nightly as needed](#downgrading-rust-nightly). 181 | 182 | #### Rust nightly toolchain 183 | 184 | If you want to guarantee that your build works on your computer as you update Rust and other 185 | dependencies, you should use a specific Rust nightly version that is known to be 186 | compatible with the version of Substrate they are using; this version will vary from project to 187 | project and different projects may use different mechanisms to communicate this version to 188 | developers. For instance, the Polkadot client specifies this information in its 189 | [release notes](https://github.com/paritytech/polkadot/releases). 190 | 191 | ```bash 192 | # Specify the specific nightly toolchain in the date below: 193 | rustup install nightly- 194 | ``` 195 | 196 | #### Wasm toolchain 197 | 198 | Now, configure the nightly version to work with the Wasm compilation target: 199 | 200 | ```bash 201 | rustup target add wasm32-unknown-unknown --toolchain nightly- 202 | ``` 203 | 204 | ### Specifying nightly version 205 | 206 | Use the `WASM_BUILD_TOOLCHAIN` environment variable to specify the Rust nightly version a Substrate 207 | project should use for Wasm compilation: 208 | 209 | ```bash 210 | WASM_BUILD_TOOLCHAIN=nightly- cargo build --release 211 | ``` 212 | 213 | > Note that this only builds _the runtime_ with the specified nightly. The rest of project will be 214 | > compiled with **your default toolchain**, i.e. the latest installed stable toolchain. 215 | 216 | ### Downgrading Rust nightly 217 | 218 | If your computer is configured to use the latest Rust nightly and you would like to downgrade to a 219 | specific nightly version, follow these steps: 220 | 221 | ```bash 222 | rustup uninstall nightly 223 | rustup install nightly- 224 | rustup target add wasm32-unknown-unknown --toolchain nightly- 225 | ``` 226 | -------------------------------------------------------------------------------- /node/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "node-template" 3 | version = "4.0.0-dev" 4 | description = "A fresh FRAME-based Substrate node, ready for hacking." 5 | authors = ["Substrate DevHub "] 6 | homepage = "https://substrate.io/" 7 | edition = "2021" 8 | license = "Unlicense" 9 | publish = false 10 | repository = "https://github.com/substrate-developer-hub/substrate-node-template/" 11 | build = "build.rs" 12 | 13 | [package.metadata.docs.rs] 14 | targets = ["x86_64-unknown-linux-gnu"] 15 | 16 | [[bin]] 17 | name = "node-template" 18 | 19 | [dependencies] 20 | clap = { version = "3.1.6", features = ["derive"] } 21 | 22 | sc-cli = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19", features = ["wasmtime"] } 23 | sp-core = { version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 24 | sc-executor = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19", features = ["wasmtime"] } 25 | sc-service = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19", features = ["wasmtime"] } 26 | sc-telemetry = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 27 | sc-keystore = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 28 | sc-transaction-pool = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 29 | sc-transaction-pool-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 30 | sc-consensus-aura = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 31 | sp-consensus-aura = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 32 | sp-consensus = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 33 | sc-consensus = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 34 | sc-finality-grandpa = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 35 | sp-finality-grandpa = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 36 | sc-client-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 37 | sp-runtime = { version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 38 | sp-timestamp = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 39 | sp-inherents = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 40 | sp-keyring = { version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 41 | frame-system = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 42 | pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 43 | 44 | # These dependencies are used for the node template's RPCs 45 | jsonrpc-core = "18.0.0" 46 | sc-rpc = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 47 | sp-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 48 | sc-rpc-api = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 49 | sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 50 | sp-block-builder = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 51 | sc-basic-authorship = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 52 | substrate-frame-rpc-system = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 53 | pallet-transaction-payment-rpc = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 54 | 55 | # These dependencies are used for runtime benchmarking 56 | frame-benchmarking = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 57 | frame-benchmarking-cli = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 58 | 59 | # Local Dependencies 60 | node-template-runtime = { version = "4.0.0-dev", path = "../runtime" } 61 | 62 | # CLI-specific dependencies 63 | try-runtime-cli = { version = "0.10.0-dev", optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 64 | 65 | [build-dependencies] 66 | substrate-build-script-utils = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 67 | 68 | [features] 69 | default = [] 70 | runtime-benchmarks = ["node-template-runtime/runtime-benchmarks"] 71 | # Enable features that allow the runtime to be tried and debugged. Name might be subject to change 72 | # in the near future. 73 | try-runtime = ["node-template-runtime/try-runtime", "try-runtime-cli"] 74 | -------------------------------------------------------------------------------- /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 | use sc_service::{Properties}; //import Properties 2 | use node_template_runtime::{ 3 | AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig, 4 | SystemConfig, WASM_BINARY, 5 | }; 6 | use sc_service::ChainType; 7 | use sp_consensus_aura::sr25519::AuthorityId as AuraId; 8 | use sp_core::{sr25519, Pair, Public}; 9 | use sp_finality_grandpa::AuthorityId as GrandpaId; 10 | use sp_runtime::traits::{IdentifyAccount, Verify}; 11 | 12 | // The URL for the telemetry server. 13 | // const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; 14 | 15 | /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. 16 | pub type ChainSpec = sc_service::GenericChainSpec; 17 | 18 | /// Generate a crypto pair from seed. 19 | pub fn get_from_seed(seed: &str) -> ::Public { 20 | TPublic::Pair::from_string(&format!("//{}", seed), None) 21 | .expect("static values are valid; qed") 22 | .public() 23 | } 24 | 25 | type AccountPublic = ::Signer; 26 | 27 | /// Generate an account ID from seed. 28 | pub fn get_account_id_from_seed(seed: &str) -> AccountId 29 | where 30 | AccountPublic: From<::Public>, 31 | { 32 | AccountPublic::from(get_from_seed::(seed)).into_account() 33 | } 34 | 35 | /// Generate an Aura authority key. 36 | pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { 37 | (get_from_seed::(s), get_from_seed::(s)) 38 | } 39 | 40 | pub fn development_config() -> Result { 41 | let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; 42 | 43 | // Give your base currency a unit name and decimal places 44 | let mut properties = Properties::new(); 45 | properties.insert("tokenSymbol".into(), "CLC".into()); 46 | properties.insert("tokenDecimals".into(), 12.into()); 47 | properties.insert("ss58Format".into(), 42.into()); 48 | 49 | Ok(ChainSpec::from_genesis( 50 | // Name 51 | "Development", 52 | // ID 53 | "dev", 54 | ChainType::Development, 55 | move || { 56 | testnet_genesis( 57 | wasm_binary, 58 | // Initial PoA authorities 59 | vec![authority_keys_from_seed("Alice")], 60 | // Sudo account 61 | get_account_id_from_seed::("Alice"), 62 | // Pre-funded accounts 63 | vec![ 64 | get_account_id_from_seed::("Alice"), 65 | ], 66 | true, 67 | ) 68 | }, 69 | // Bootnodes 70 | vec![], 71 | // Telemetry 72 | None, 73 | // Protocol ID 74 | None, 75 | None, 76 | // Properties 77 | None, 78 | // Extensions 79 | None, 80 | )) 81 | } 82 | 83 | pub fn local_testnet_config() -> Result { 84 | let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; 85 | 86 | Ok(ChainSpec::from_genesis( 87 | // Name 88 | "Local Testnet", 89 | // ID 90 | "local_testnet", 91 | ChainType::Local, 92 | move || { 93 | testnet_genesis( 94 | wasm_binary, 95 | // Initial PoA authorities 96 | vec![authority_keys_from_seed("Alice"), authority_keys_from_seed("Bob")], 97 | // Sudo account 98 | get_account_id_from_seed::("Alice"), 99 | // Pre-funded accounts 100 | vec![ 101 | get_account_id_from_seed::("Alice"), 102 | get_account_id_from_seed::("Bob"), 103 | get_account_id_from_seed::("Charlie"), 104 | get_account_id_from_seed::("Dave"), 105 | get_account_id_from_seed::("Eve"), 106 | get_account_id_from_seed::("Ferdie"), 107 | get_account_id_from_seed::("Alice//stash"), 108 | get_account_id_from_seed::("Bob//stash"), 109 | get_account_id_from_seed::("Charlie//stash"), 110 | get_account_id_from_seed::("Dave//stash"), 111 | get_account_id_from_seed::("Eve//stash"), 112 | get_account_id_from_seed::("Ferdie//stash"), 113 | ], 114 | true, 115 | ) 116 | }, 117 | // Bootnodes 118 | vec![], 119 | // Telemetry 120 | None, 121 | // Protocol ID 122 | None, 123 | // Properties 124 | None, 125 | None, 126 | // Extensions 127 | None, 128 | )) 129 | } 130 | 131 | /// Configure initial storage state for FRAME modules. 132 | fn testnet_genesis( 133 | wasm_binary: &[u8], 134 | initial_authorities: Vec<(AuraId, GrandpaId)>, 135 | root_key: AccountId, 136 | endowed_accounts: Vec, 137 | _enable_println: bool, 138 | ) -> GenesisConfig { 139 | GenesisConfig { 140 | system: SystemConfig { 141 | // Add Wasm runtime to storage. 142 | code: wasm_binary.to_vec(), 143 | }, 144 | balances: BalancesConfig { 145 | // Configure endowed accounts with initial balance of 1 << 60. 146 | // balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), 147 | balances: endowed_accounts.iter().cloned().map(|k| (k, 29000000000)).collect(), 148 | }, 149 | aura: AuraConfig { 150 | authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), 151 | }, 152 | grandpa: GrandpaConfig { 153 | authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), 154 | }, 155 | sudo: SudoConfig { 156 | // Assign network admin rights. 157 | key: Some(root_key), 158 | }, 159 | transaction_payment: Default::default(), 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /node/src/cli.rs: -------------------------------------------------------------------------------- 1 | use sc_cli::RunCmd; 2 | 3 | #[derive(Debug, clap::Parser)] 4 | pub struct Cli { 5 | #[clap(subcommand)] 6 | pub subcommand: Option, 7 | 8 | #[clap(flatten)] 9 | pub run: RunCmd, 10 | } 11 | 12 | #[derive(Debug, clap::Subcommand)] 13 | pub enum Subcommand { 14 | /// Key management cli utilities 15 | #[clap(subcommand)] 16 | Key(sc_cli::KeySubcommand), 17 | 18 | /// Build a chain specification. 19 | BuildSpec(sc_cli::BuildSpecCmd), 20 | 21 | /// Validate blocks. 22 | CheckBlock(sc_cli::CheckBlockCmd), 23 | 24 | /// Export blocks. 25 | ExportBlocks(sc_cli::ExportBlocksCmd), 26 | 27 | /// Export the state of a given block into a chain spec. 28 | ExportState(sc_cli::ExportStateCmd), 29 | 30 | /// Import blocks. 31 | ImportBlocks(sc_cli::ImportBlocksCmd), 32 | 33 | /// Remove the whole chain. 34 | PurgeChain(sc_cli::PurgeChainCmd), 35 | 36 | /// Revert the chain to a previous state. 37 | Revert(sc_cli::RevertCmd), 38 | 39 | /// Sub-commands concerned with benchmarking. 40 | #[clap(subcommand)] 41 | Benchmark(frame_benchmarking_cli::BenchmarkCmd), 42 | 43 | /// Try some command against runtime state. 44 | #[cfg(feature = "try-runtime")] 45 | TryRuntime(try_runtime_cli::TryRuntimeCmd), 46 | 47 | /// Try some command against runtime state. Note: `try-runtime` feature must be enabled. 48 | #[cfg(not(feature = "try-runtime"))] 49 | TryRuntime, 50 | } 51 | -------------------------------------------------------------------------------- /node/src/command.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | chain_spec, 3 | cli::{Cli, Subcommand}, 4 | command_helper::{inherent_benchmark_data, BenchmarkExtrinsicBuilder}, 5 | service, 6 | }; 7 | use frame_benchmarking_cli::BenchmarkCmd; 8 | use node_template_runtime::Block; 9 | use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; 10 | use sc_service::PartialComponents; 11 | use std::sync::Arc; 12 | 13 | impl SubstrateCli for Cli { 14 | fn impl_name() -> String { 15 | "Substrate Node".into() 16 | } 17 | 18 | fn impl_version() -> String { 19 | env!("SUBSTRATE_CLI_IMPL_VERSION").into() 20 | } 21 | 22 | fn description() -> String { 23 | env!("CARGO_PKG_DESCRIPTION").into() 24 | } 25 | 26 | fn author() -> String { 27 | env!("CARGO_PKG_AUTHORS").into() 28 | } 29 | 30 | fn support_url() -> String { 31 | "support.anonymous.an".into() 32 | } 33 | 34 | fn copyright_start_year() -> i32 { 35 | 2017 36 | } 37 | 38 | fn load_spec(&self, id: &str) -> Result, String> { 39 | Ok(match id { 40 | "dev" => Box::new(chain_spec::development_config()?), 41 | "" | "local" => Box::new(chain_spec::local_testnet_config()?), 42 | path => 43 | Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), 44 | }) 45 | } 46 | 47 | fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { 48 | &node_template_runtime::VERSION 49 | } 50 | } 51 | 52 | /// Parse and run command line arguments 53 | pub fn run() -> sc_cli::Result<()> { 54 | let cli = Cli::from_args(); 55 | 56 | match &cli.subcommand { 57 | Some(Subcommand::Key(cmd)) => cmd.run(&cli), 58 | Some(Subcommand::BuildSpec(cmd)) => { 59 | let runner = cli.create_runner(cmd)?; 60 | runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) 61 | }, 62 | Some(Subcommand::CheckBlock(cmd)) => { 63 | let runner = cli.create_runner(cmd)?; 64 | runner.async_run(|config| { 65 | let PartialComponents { client, task_manager, import_queue, .. } = 66 | service::new_partial(&config)?; 67 | Ok((cmd.run(client, import_queue), task_manager)) 68 | }) 69 | }, 70 | Some(Subcommand::ExportBlocks(cmd)) => { 71 | let runner = cli.create_runner(cmd)?; 72 | runner.async_run(|config| { 73 | let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; 74 | Ok((cmd.run(client, config.database), task_manager)) 75 | }) 76 | }, 77 | Some(Subcommand::ExportState(cmd)) => { 78 | let runner = cli.create_runner(cmd)?; 79 | runner.async_run(|config| { 80 | let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; 81 | Ok((cmd.run(client, config.chain_spec), task_manager)) 82 | }) 83 | }, 84 | Some(Subcommand::ImportBlocks(cmd)) => { 85 | let runner = cli.create_runner(cmd)?; 86 | runner.async_run(|config| { 87 | let PartialComponents { client, task_manager, import_queue, .. } = 88 | service::new_partial(&config)?; 89 | Ok((cmd.run(client, import_queue), task_manager)) 90 | }) 91 | }, 92 | Some(Subcommand::PurgeChain(cmd)) => { 93 | let runner = cli.create_runner(cmd)?; 94 | runner.sync_run(|config| cmd.run(config.database)) 95 | }, 96 | Some(Subcommand::Revert(cmd)) => { 97 | let runner = cli.create_runner(cmd)?; 98 | runner.async_run(|config| { 99 | let PartialComponents { client, task_manager, backend, .. } = 100 | service::new_partial(&config)?; 101 | let aux_revert = Box::new(move |client, _, blocks| { 102 | sc_finality_grandpa::revert(client, blocks)?; 103 | Ok(()) 104 | }); 105 | Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) 106 | }) 107 | }, 108 | Some(Subcommand::Benchmark(cmd)) => { 109 | let runner = cli.create_runner(cmd)?; 110 | 111 | runner.sync_run(|config| { 112 | let PartialComponents { client, backend, .. } = service::new_partial(&config)?; 113 | 114 | // This switch needs to be in the client, since the client decides 115 | // which sub-commands it wants to support. 116 | match cmd { 117 | BenchmarkCmd::Pallet(cmd) => { 118 | if !cfg!(feature = "runtime-benchmarks") { 119 | return Err( 120 | "Runtime benchmarking wasn't enabled when building the node. \ 121 | You can enable it with `--features runtime-benchmarks`." 122 | .into(), 123 | ) 124 | } 125 | 126 | cmd.run::(config) 127 | }, 128 | BenchmarkCmd::Block(cmd) => cmd.run(client), 129 | BenchmarkCmd::Storage(cmd) => { 130 | let db = backend.expose_db(); 131 | let storage = backend.expose_storage(); 132 | 133 | cmd.run(config, client, db, storage) 134 | }, 135 | BenchmarkCmd::Overhead(cmd) => { 136 | let ext_builder = BenchmarkExtrinsicBuilder::new(client.clone()); 137 | 138 | cmd.run(config, client, inherent_benchmark_data()?, Arc::new(ext_builder)) 139 | }, 140 | } 141 | }) 142 | }, 143 | #[cfg(feature = "try-runtime")] 144 | Some(Subcommand::TryRuntime(cmd)) => { 145 | let runner = cli.create_runner(cmd)?; 146 | runner.async_run(|config| { 147 | // we don't need any of the components of new_partial, just a runtime, or a task 148 | // manager to do `async_run`. 149 | let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); 150 | let task_manager = 151 | sc_service::TaskManager::new(config.tokio_handle.clone(), registry) 152 | .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; 153 | Ok((cmd.run::(config), task_manager)) 154 | }) 155 | }, 156 | #[cfg(not(feature = "try-runtime"))] 157 | Some(Subcommand::TryRuntime) => Err("TryRuntime wasn't enabled when building the node. \ 158 | You can enable it with `--features try-runtime`." 159 | .into()), 160 | None => { 161 | let runner = cli.create_runner(&cli.run)?; 162 | runner.run_node_until_exit(|config| async move { 163 | service::new_full(config).map_err(sc_cli::Error::Service) 164 | }) 165 | }, 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /node/src/command_helper.rs: -------------------------------------------------------------------------------- 1 | // This file is part of Substrate. 2 | 3 | // Copyright (C) 2022 Parity Technologies (UK) Ltd. 4 | // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 5 | 6 | // This program is free software: you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License as published by 8 | // the Free Software Foundation, either version 3 of the License, or 9 | // (at your option) any later version. 10 | 11 | // This program is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU General Public License for more details. 15 | 16 | // You should have received a copy of the GNU General Public License 17 | // along with this program. If not, see . 18 | 19 | //! Contains code to setup the command invocations in [`super::command`] which would 20 | //! otherwise bloat that module. 21 | 22 | use crate::service::FullClient; 23 | 24 | use node_template_runtime as runtime; 25 | use runtime::SystemCall; 26 | use sc_cli::Result; 27 | use sc_client_api::BlockBackend; 28 | use sp_core::{Encode, Pair}; 29 | use sp_inherents::{InherentData, InherentDataProvider}; 30 | use sp_keyring::Sr25519Keyring; 31 | use sp_runtime::{OpaqueExtrinsic, SaturatedConversion}; 32 | 33 | use std::{sync::Arc, time::Duration}; 34 | 35 | /// Generates extrinsics for the `benchmark overhead` command. 36 | /// 37 | /// Note: Should only be used for benchmarking. 38 | pub struct BenchmarkExtrinsicBuilder { 39 | client: Arc, 40 | } 41 | 42 | impl BenchmarkExtrinsicBuilder { 43 | /// Creates a new [`Self`] from the given client. 44 | pub fn new(client: Arc) -> Self { 45 | Self { client } 46 | } 47 | } 48 | 49 | impl frame_benchmarking_cli::ExtrinsicBuilder for BenchmarkExtrinsicBuilder { 50 | fn remark(&self, nonce: u32) -> std::result::Result { 51 | let acc = Sr25519Keyring::Bob.pair(); 52 | let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( 53 | self.client.as_ref(), 54 | acc, 55 | SystemCall::remark { remark: vec![] }.into(), 56 | nonce, 57 | ) 58 | .into(); 59 | 60 | Ok(extrinsic) 61 | } 62 | } 63 | 64 | /// Create a transaction using the given `call`. 65 | /// 66 | /// Note: Should only be used for benchmarking. 67 | pub fn create_benchmark_extrinsic( 68 | client: &FullClient, 69 | sender: sp_core::sr25519::Pair, 70 | call: runtime::Call, 71 | nonce: u32, 72 | ) -> runtime::UncheckedExtrinsic { 73 | let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); 74 | let best_hash = client.chain_info().best_hash; 75 | let best_block = client.chain_info().best_number; 76 | 77 | let period = runtime::BlockHashCount::get() 78 | .checked_next_power_of_two() 79 | .map(|c| c / 2) 80 | .unwrap_or(2) as u64; 81 | let extra: runtime::SignedExtra = ( 82 | frame_system::CheckNonZeroSender::::new(), 83 | frame_system::CheckSpecVersion::::new(), 84 | frame_system::CheckTxVersion::::new(), 85 | frame_system::CheckGenesis::::new(), 86 | frame_system::CheckEra::::from(sp_runtime::generic::Era::mortal( 87 | period, 88 | best_block.saturated_into(), 89 | )), 90 | frame_system::CheckNonce::::from(nonce), 91 | frame_system::CheckWeight::::new(), 92 | pallet_transaction_payment::ChargeTransactionPayment::::from(0), 93 | ); 94 | 95 | let raw_payload = runtime::SignedPayload::from_raw( 96 | call.clone(), 97 | extra.clone(), 98 | ( 99 | (), 100 | runtime::VERSION.spec_version, 101 | runtime::VERSION.transaction_version, 102 | genesis_hash, 103 | best_hash, 104 | (), 105 | (), 106 | (), 107 | ), 108 | ); 109 | let signature = raw_payload.using_encoded(|e| sender.sign(e)); 110 | 111 | runtime::UncheckedExtrinsic::new_signed( 112 | call.clone(), 113 | sp_runtime::AccountId32::from(sender.public()).into(), 114 | runtime::Signature::Sr25519(signature.clone()), 115 | extra.clone(), 116 | ) 117 | } 118 | 119 | /// Generates inherent data for the `benchmark overhead` command. 120 | /// 121 | /// Note: Should only be used for benchmarking. 122 | pub fn inherent_benchmark_data() -> Result { 123 | let mut inherent_data = InherentData::new(); 124 | let d = Duration::from_millis(0); 125 | let timestamp = sp_timestamp::InherentDataProvider::new(d.into()); 126 | 127 | timestamp 128 | .provide_inherent_data(&mut inherent_data) 129 | .map_err(|e| format!("creating inherent data: {:?}", e))?; 130 | Ok(inherent_data) 131 | } 132 | -------------------------------------------------------------------------------- /node/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod chain_spec; 2 | pub mod rpc; 3 | pub mod service; 4 | -------------------------------------------------------------------------------- /node/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Substrate Node Template CLI library. 2 | #![warn(missing_docs)] 3 | 4 | mod chain_spec; 5 | #[macro_use] 6 | mod service; 7 | mod cli; 8 | mod command; 9 | mod command_helper; 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 node_template_runtime::{opaque::Block, AccountId, Balance, Index}; 11 | pub use sc_rpc_api::DenyUnsafe; 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 | /// Full client dependencies. 18 | pub struct FullDeps { 19 | /// The client instance to use. 20 | pub client: Arc, 21 | /// Transaction pool instance. 22 | pub pool: Arc

, 23 | /// Whether to deny unsafe calls 24 | pub deny_unsafe: DenyUnsafe, 25 | } 26 | 27 | /// Instantiate all full RPC extensions. 28 | pub fn create_full(deps: FullDeps) -> jsonrpc_core::IoHandler 29 | where 30 | C: ProvideRuntimeApi, 31 | C: HeaderBackend + HeaderMetadata + 'static, 32 | C: Send + Sync + 'static, 33 | C::Api: substrate_frame_rpc_system::AccountNonceApi, 34 | C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, 35 | C::Api: BlockBuilder, 36 | P: TransactionPool + 'static, 37 | { 38 | use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; 39 | use substrate_frame_rpc_system::{FullSystem, SystemApi}; 40 | 41 | let mut io = jsonrpc_core::IoHandler::default(); 42 | let FullDeps { client, pool, deny_unsafe } = deps; 43 | 44 | io.extend_with(SystemApi::to_delegate(FullSystem::new(client.clone(), pool, deny_unsafe))); 45 | 46 | io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone()))); 47 | 48 | // Extend this RPC with a custom API by using the following syntax. 49 | // `YourRpcStruct` should have a reference to a client, which is needed 50 | // to call into the runtime. 51 | // `io.extend_with(YourRpcTrait::to_delegate(YourRpcStruct::new(ReferenceToClient, ...)));` 52 | 53 | io 54 | } 55 | -------------------------------------------------------------------------------- /node/src/service.rs: -------------------------------------------------------------------------------- 1 | //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. 2 | 3 | use node_template_runtime::{self, opaque::Block, RuntimeApi}; 4 | use sc_client_api::{BlockBackend, ExecutorProvider}; 5 | use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; 6 | pub use sc_executor::NativeElseWasmExecutor; 7 | use sc_finality_grandpa::SharedVoterState; 8 | use sc_keystore::LocalKeystore; 9 | use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; 10 | use sc_telemetry::{Telemetry, TelemetryWorker}; 11 | use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; 12 | use std::{sync::Arc, time::Duration}; 13 | 14 | // Our native executor instance. 15 | pub struct ExecutorDispatch; 16 | 17 | impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { 18 | /// Only enable the benchmarking host functions when we actually want to benchmark. 19 | #[cfg(feature = "runtime-benchmarks")] 20 | type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; 21 | /// Otherwise we only use the default Substrate host functions. 22 | #[cfg(not(feature = "runtime-benchmarks"))] 23 | type ExtendHostFunctions = (); 24 | 25 | fn dispatch(method: &str, data: &[u8]) -> Option> { 26 | node_template_runtime::api::dispatch(method, data) 27 | } 28 | 29 | fn native_version() -> sc_executor::NativeVersion { 30 | node_template_runtime::native_version() 31 | } 32 | } 33 | 34 | pub(crate) type FullClient = 35 | sc_service::TFullClient>; 36 | type FullBackend = sc_service::TFullBackend; 37 | type FullSelectChain = sc_consensus::LongestChain; 38 | 39 | pub fn new_partial( 40 | config: &Configuration, 41 | ) -> Result< 42 | sc_service::PartialComponents< 43 | FullClient, 44 | FullBackend, 45 | FullSelectChain, 46 | sc_consensus::DefaultImportQueue, 47 | sc_transaction_pool::FullPool, 48 | ( 49 | sc_finality_grandpa::GrandpaBlockImport< 50 | FullBackend, 51 | Block, 52 | FullClient, 53 | FullSelectChain, 54 | >, 55 | sc_finality_grandpa::LinkHalf, 56 | Option, 57 | ), 58 | >, 59 | ServiceError, 60 | > { 61 | if config.keystore_remote.is_some() { 62 | return Err(ServiceError::Other("Remote Keystores are not supported.".into())) 63 | } 64 | 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 executor = NativeElseWasmExecutor::::new( 77 | config.wasm_method, 78 | config.default_heap_pages, 79 | config.max_runtime_instances, 80 | config.runtime_cache_size, 81 | ); 82 | 83 | let (client, backend, keystore_container, task_manager) = 84 | sc_service::new_full_parts::( 85 | &config, 86 | telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), 87 | executor, 88 | )?; 89 | let client = Arc::new(client); 90 | 91 | let telemetry = telemetry.map(|(worker, telemetry)| { 92 | task_manager.spawn_handle().spawn("telemetry", None, worker.run()); 93 | telemetry 94 | }); 95 | 96 | let select_chain = sc_consensus::LongestChain::new(backend.clone()); 97 | 98 | let transaction_pool = sc_transaction_pool::BasicPool::new_full( 99 | config.transaction_pool.clone(), 100 | config.role.is_authority().into(), 101 | config.prometheus_registry(), 102 | task_manager.spawn_essential_handle(), 103 | client.clone(), 104 | ); 105 | 106 | let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( 107 | client.clone(), 108 | &(client.clone() as Arc<_>), 109 | select_chain.clone(), 110 | telemetry.as_ref().map(|x| x.handle()), 111 | )?; 112 | 113 | let slot_duration = sc_consensus_aura::slot_duration(&*client)?; 114 | 115 | let import_queue = 116 | sc_consensus_aura::import_queue::(ImportQueueParams { 117 | block_import: grandpa_block_import.clone(), 118 | justification_import: Some(Box::new(grandpa_block_import.clone())), 119 | client: client.clone(), 120 | create_inherent_data_providers: move |_, ()| async move { 121 | let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); 122 | 123 | let slot = 124 | sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( 125 | *timestamp, 126 | slot_duration, 127 | ); 128 | 129 | Ok((timestamp, slot)) 130 | }, 131 | spawner: &task_manager.spawn_essential_handle(), 132 | can_author_with: sp_consensus::CanAuthorWithNativeVersion::new( 133 | client.executor().clone(), 134 | ), 135 | registry: config.prometheus_registry(), 136 | check_for_equivocation: Default::default(), 137 | telemetry: telemetry.as_ref().map(|x| x.handle()), 138 | })?; 139 | 140 | Ok(sc_service::PartialComponents { 141 | client, 142 | backend, 143 | task_manager, 144 | import_queue, 145 | keystore_container, 146 | select_chain, 147 | transaction_pool, 148 | other: (grandpa_block_import, grandpa_link, telemetry), 149 | }) 150 | } 151 | 152 | fn remote_keystore(_url: &String) -> Result, &'static str> { 153 | // FIXME: here would the concrete keystore be built, 154 | // must return a concrete type (NOT `LocalKeystore`) that 155 | // implements `CryptoStore` and `SyncCryptoStore` 156 | Err("Remote Keystore not supported.") 157 | } 158 | 159 | /// Builds a new service for a full client. 160 | pub fn new_full(mut config: Configuration) -> Result { 161 | let sc_service::PartialComponents { 162 | client, 163 | backend, 164 | mut task_manager, 165 | import_queue, 166 | mut keystore_container, 167 | select_chain, 168 | transaction_pool, 169 | other: (block_import, grandpa_link, mut telemetry), 170 | } = new_partial(&config)?; 171 | 172 | if let Some(url) = &config.keystore_remote { 173 | match remote_keystore(url) { 174 | Ok(k) => keystore_container.set_remote_keystore(k), 175 | Err(e) => 176 | return Err(ServiceError::Other(format!( 177 | "Error hooking up remote keystore for {}: {}", 178 | url, e 179 | ))), 180 | }; 181 | } 182 | let grandpa_protocol_name = sc_finality_grandpa::protocol_standard_name( 183 | &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), 184 | &config.chain_spec, 185 | ); 186 | 187 | config 188 | .network 189 | .extra_sets 190 | .push(sc_finality_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); 191 | let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( 192 | backend.clone(), 193 | grandpa_link.shared_authority_set().clone(), 194 | Vec::default(), 195 | )); 196 | 197 | let (network, system_rpc_tx, network_starter) = 198 | sc_service::build_network(sc_service::BuildNetworkParams { 199 | config: &config, 200 | client: client.clone(), 201 | transaction_pool: transaction_pool.clone(), 202 | spawn_handle: task_manager.spawn_handle(), 203 | import_queue, 204 | block_announce_validator_builder: None, 205 | warp_sync: Some(warp_sync), 206 | })?; 207 | 208 | if config.offchain_worker.enabled { 209 | sc_service::build_offchain_workers( 210 | &config, 211 | task_manager.spawn_handle(), 212 | client.clone(), 213 | network.clone(), 214 | ); 215 | } 216 | 217 | let role = config.role.clone(); 218 | let force_authoring = config.force_authoring; 219 | let backoff_authoring_blocks: Option<()> = None; 220 | let name = config.network.node_name.clone(); 221 | let enable_grandpa = !config.disable_grandpa; 222 | let prometheus_registry = config.prometheus_registry().cloned(); 223 | 224 | let rpc_extensions_builder = { 225 | let client = client.clone(); 226 | let pool = transaction_pool.clone(); 227 | 228 | Box::new(move |deny_unsafe, _| { 229 | let deps = 230 | crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; 231 | 232 | Ok(crate::rpc::create_full(deps)) 233 | }) 234 | }; 235 | 236 | let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { 237 | network: network.clone(), 238 | client: client.clone(), 239 | keystore: keystore_container.sync_keystore(), 240 | task_manager: &mut task_manager, 241 | transaction_pool: transaction_pool.clone(), 242 | rpc_extensions_builder, 243 | backend, 244 | system_rpc_tx, 245 | config, 246 | telemetry: telemetry.as_mut(), 247 | })?; 248 | 249 | if role.is_authority() { 250 | let proposer_factory = sc_basic_authorship::ProposerFactory::new( 251 | task_manager.spawn_handle(), 252 | client.clone(), 253 | transaction_pool, 254 | prometheus_registry.as_ref(), 255 | telemetry.as_ref().map(|x| x.handle()), 256 | ); 257 | 258 | let can_author_with = 259 | sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); 260 | 261 | let slot_duration = sc_consensus_aura::slot_duration(&*client)?; 262 | 263 | let aura = sc_consensus_aura::start_aura::( 264 | StartAuraParams { 265 | slot_duration, 266 | client: client.clone(), 267 | select_chain, 268 | block_import, 269 | proposer_factory, 270 | create_inherent_data_providers: move |_, ()| async move { 271 | let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); 272 | 273 | let slot = 274 | sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( 275 | *timestamp, 276 | slot_duration, 277 | ); 278 | 279 | Ok((timestamp, slot)) 280 | }, 281 | force_authoring, 282 | backoff_authoring_blocks, 283 | keystore: keystore_container.sync_keystore(), 284 | can_author_with, 285 | sync_oracle: network.clone(), 286 | justification_sync_link: network.clone(), 287 | block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), 288 | max_block_proposal_slot_portion: None, 289 | telemetry: telemetry.as_ref().map(|x| x.handle()), 290 | }, 291 | )?; 292 | 293 | // the AURA authoring task is considered essential, i.e. if it 294 | // fails we take down the service with it. 295 | task_manager 296 | .spawn_essential_handle() 297 | .spawn_blocking("aura", Some("block-authoring"), aura); 298 | } 299 | 300 | // if the node isn't actively participating in consensus then it doesn't 301 | // need a keystore, regardless of which protocol we use below. 302 | let keystore = 303 | if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; 304 | 305 | let grandpa_config = sc_finality_grandpa::Config { 306 | // FIXME #1578 make this available through chainspec 307 | gossip_duration: Duration::from_millis(333), 308 | justification_period: 512, 309 | name: Some(name), 310 | observer_enabled: false, 311 | keystore, 312 | local_role: role, 313 | telemetry: telemetry.as_ref().map(|x| x.handle()), 314 | protocol_name: grandpa_protocol_name, 315 | }; 316 | 317 | if enable_grandpa { 318 | // start the full GRANDPA voter 319 | // NOTE: non-authorities could run the GRANDPA observer protocol, but at 320 | // this point the full voter should provide better guarantees of block 321 | // and vote data availability than the observer. The observer has not 322 | // been tested extensively yet and having most nodes in a network run it 323 | // could lead to finality stalls. 324 | let grandpa_config = sc_finality_grandpa::GrandpaParams { 325 | config: grandpa_config, 326 | link: grandpa_link, 327 | network, 328 | voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), 329 | prometheus_registry, 330 | shared_voter_state: SharedVoterState::empty(), 331 | telemetry: telemetry.as_ref().map(|x| x.handle()), 332 | }; 333 | 334 | // the GRANDPA voter task is considered infallible, i.e. 335 | // if it fails we take down the service with it. 336 | task_manager.spawn_essential_handle().spawn_blocking( 337 | "grandpa-voter", 338 | None, 339 | sc_finality_grandpa::run_grandpa_voter(grandpa_config)?, 340 | ); 341 | } 342 | 343 | network_starter.start_network(); 344 | Ok(task_manager) 345 | } 346 | -------------------------------------------------------------------------------- /pallets/template/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pallet-template" 3 | version = "4.0.0-dev" 4 | description = "FRAME pallet template for defining custom runtime logic." 5 | authors = ["Substrate DevHub "] 6 | homepage = "https://substrate.io/" 7 | edition = "2021" 8 | license = "Unlicense" 9 | publish = false 10 | repository = "https://github.com/substrate-developer-hub/substrate-node-template/" 11 | 12 | [package.metadata.docs.rs] 13 | targets = ["x86_64-unknown-linux-gnu"] 14 | 15 | [dependencies] 16 | codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ 17 | "derive", 18 | ] } 19 | scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } 20 | frame-support = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19"} 21 | frame-system = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 22 | frame-benchmarking = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19", optional = true } 23 | 24 | [dev-dependencies] 25 | sp-core = { default-features = false, version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 26 | sp-io = { default-features = false, version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 27 | sp-runtime = { default-features = false, version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 28 | 29 | [features] 30 | default = ["std"] 31 | std = [ 32 | "codec/std", 33 | "scale-info/std", 34 | "frame-support/std", 35 | "frame-system/std", 36 | "frame-benchmarking/std", 37 | ] 38 | 39 | runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] 40 | try-runtime = ["frame-support/try-runtime"] 41 | -------------------------------------------------------------------------------- /pallets/template/README.md: -------------------------------------------------------------------------------- 1 | License: Unlicense -------------------------------------------------------------------------------- /pallets/template/src/benchmarking.rs: -------------------------------------------------------------------------------- 1 | //! Benchmarking setup for pallet-template 2 | 3 | use super::*; 4 | 5 | #[allow(unused)] 6 | use crate::Pallet as Template; 7 | use frame_benchmarking::{benchmarks, whitelisted_caller}; 8 | use frame_system::RawOrigin; 9 | 10 | benchmarks! { 11 | do_something { 12 | let s in 0 .. 100; 13 | let caller: T::AccountId = whitelisted_caller(); 14 | }: _(RawOrigin::Signed(caller), s) 15 | verify { 16 | assert_eq!(Something::::get(), Some(s)); 17 | } 18 | 19 | impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test); 20 | } 21 | -------------------------------------------------------------------------------- /pallets/template/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | 3 | /// Edit this file to define custom logic or remove it if it is not needed. 4 | /// Learn more about FRAME and the core library of Substrate FRAME pallets: 5 | /// 6 | pub use pallet::*; 7 | 8 | #[cfg(test)] 9 | mod mock; 10 | 11 | #[cfg(test)] 12 | mod tests; 13 | 14 | #[cfg(feature = "runtime-benchmarks")] 15 | mod benchmarking; 16 | 17 | #[frame_support::pallet] 18 | pub mod pallet { 19 | use frame_support::pallet_prelude::*; 20 | use frame_system::pallet_prelude::*; 21 | 22 | /// Configure the pallet by specifying the parameters and types on which it depends. 23 | #[pallet::config] 24 | pub trait Config: frame_system::Config { 25 | /// Because this pallet emits events, it depends on the runtime's definition of an event. 26 | type Event: From> + IsType<::Event>; 27 | } 28 | 29 | #[pallet::pallet] 30 | #[pallet::generate_store(pub(super) trait Store)] 31 | pub struct Pallet(_); 32 | 33 | // The pallet's runtime storage items. 34 | // https://docs.substrate.io/v3/runtime/storage 35 | #[pallet::storage] 36 | #[pallet::getter(fn something)] 37 | // Learn more about declaring storage items: 38 | // https://docs.substrate.io/v3/runtime/storage#declaring-storage-items 39 | pub type Something = StorageValue<_, u32>; 40 | 41 | // Pallets use events to inform users when important changes are made. 42 | // https://docs.substrate.io/v3/runtime/events-and-errors 43 | #[pallet::event] 44 | #[pallet::generate_deposit(pub(super) fn deposit_event)] 45 | pub enum Event { 46 | /// Event documentation should end with an array that provides descriptive names for event 47 | /// parameters. [something, who] 48 | SomethingStored(u32, T::AccountId), 49 | } 50 | 51 | // Errors inform users that something went wrong. 52 | #[pallet::error] 53 | pub enum Error { 54 | /// Error names should be descriptive. 55 | NoneValue, 56 | /// Errors should have helpful documentation associated with them. 57 | StorageOverflow, 58 | } 59 | 60 | // Dispatchable functions allows users to interact with the pallet and invoke state changes. 61 | // These functions materialize as "extrinsics", which are often compared to transactions. 62 | // Dispatchable functions must be annotated with a weight and must return a DispatchResult. 63 | #[pallet::call] 64 | impl Pallet { 65 | /// An example dispatchable that takes a singles value as a parameter, writes the value to 66 | /// storage and emits an event. This function must be dispatched by a signed extrinsic. 67 | #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] 68 | pub fn do_something(origin: OriginFor, something: u32) -> DispatchResult { 69 | // Check that the extrinsic was signed and get the signer. 70 | // This function will return an error if the extrinsic is not signed. 71 | // https://docs.substrate.io/v3/runtime/origins 72 | let who = ensure_signed(origin)?; 73 | 74 | // Update storage. 75 | >::put(something); 76 | 77 | // Emit an event. 78 | Self::deposit_event(Event::SomethingStored(something, who)); 79 | // Return a successful DispatchResultWithPostInfo 80 | Ok(()) 81 | } 82 | 83 | /// An example dispatchable that may throw a custom error. 84 | #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))] 85 | pub fn cause_error(origin: OriginFor) -> DispatchResult { 86 | let _who = ensure_signed(origin)?; 87 | 88 | // Read a value from storage. 89 | match >::get() { 90 | // Return an error if the value has not been set. 91 | None => Err(Error::::NoneValue)?, 92 | Some(old) => { 93 | // Increment the value read from storage; will error in the event of overflow. 94 | let new = old.checked_add(1).ok_or(Error::::StorageOverflow)?; 95 | // Update the value in storage with the incremented result. 96 | >::put(new); 97 | Ok(()) 98 | }, 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /pallets/template/src/mock.rs: -------------------------------------------------------------------------------- 1 | use crate as pallet_template; 2 | use frame_support::traits::{ConstU16, ConstU64}; 3 | use frame_system as system; 4 | use sp_core::H256; 5 | use sp_runtime::{ 6 | testing::Header, 7 | traits::{BlakeTwo256, IdentityLookup}, 8 | }; 9 | 10 | type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; 11 | type Block = frame_system::mocking::MockBlock; 12 | 13 | // Configure a mock runtime to test the pallet. 14 | frame_support::construct_runtime!( 15 | pub enum Test where 16 | Block = Block, 17 | NodeBlock = Block, 18 | UncheckedExtrinsic = UncheckedExtrinsic, 19 | { 20 | System: frame_system::{Pallet, Call, Config, Storage, Event}, 21 | TemplateModule: pallet_template::{Pallet, Call, Storage, Event}, 22 | } 23 | ); 24 | 25 | impl system::Config for Test { 26 | type BaseCallFilter = frame_support::traits::Everything; 27 | type BlockWeights = (); 28 | type BlockLength = (); 29 | type DbWeight = (); 30 | type Origin = Origin; 31 | type Call = Call; 32 | type Index = u64; 33 | type BlockNumber = u64; 34 | type Hash = H256; 35 | type Hashing = BlakeTwo256; 36 | type AccountId = u64; 37 | type Lookup = IdentityLookup; 38 | type Header = Header; 39 | type Event = Event; 40 | type BlockHashCount = ConstU64<250>; 41 | type Version = (); 42 | type PalletInfo = PalletInfo; 43 | type AccountData = (); 44 | type OnNewAccount = (); 45 | type OnKilledAccount = (); 46 | type SystemWeightInfo = (); 47 | type SS58Prefix = ConstU16<42>; 48 | type OnSetCode = (); 49 | type MaxConsumers = frame_support::traits::ConstU32<16>; 50 | } 51 | 52 | impl pallet_template::Config for Test { 53 | type Event = Event; 54 | } 55 | 56 | // Build genesis storage according to the mock runtime. 57 | pub fn new_test_ext() -> sp_io::TestExternalities { 58 | system::GenesisConfig::default().build_storage::().unwrap().into() 59 | } 60 | -------------------------------------------------------------------------------- /pallets/template/src/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::{mock::*, Error}; 2 | use frame_support::{assert_noop, assert_ok}; 3 | 4 | #[test] 5 | fn it_works_for_default_value() { 6 | new_test_ext().execute_with(|| { 7 | // Dispatch a signed extrinsic. 8 | assert_ok!(TemplateModule::do_something(Origin::signed(1), 42)); 9 | // Read pallet storage and assert an expected result. 10 | assert_eq!(TemplateModule::something(), Some(42)); 11 | }); 12 | } 13 | 14 | #[test] 15 | fn correct_error_for_none_value() { 16 | new_test_ext().execute_with(|| { 17 | // Ensure the expected error is thrown when no value is present. 18 | assert_noop!(TemplateModule::cause_error(Origin::signed(1)), Error::::NoneValue); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /runtime/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "node-template-runtime" 3 | version = "4.0.0-dev" 4 | description = "A fresh FRAME-based Substrate runtime, ready for hacking." 5 | authors = ["Substrate DevHub "] 6 | homepage = "https://substrate.io/" 7 | edition = "2021" 8 | license = "Unlicense" 9 | publish = false 10 | repository = "https://github.com/substrate-developer-hub/substrate-node-template/" 11 | 12 | [package.metadata.docs.rs] 13 | targets = ["x86_64-unknown-linux-gnu"] 14 | 15 | [dependencies] 16 | codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } 17 | scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } 18 | 19 | pallet-aura = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 20 | pallet-balances = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 21 | frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 22 | pallet-grandpa = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 23 | pallet-randomness-collective-flip = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 24 | pallet-sudo = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 25 | frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 26 | frame-try-runtime = { version = "0.10.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19", optional = true } 27 | pallet-timestamp = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 28 | pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 29 | frame-executive = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 30 | sp-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 31 | sp-block-builder = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19"} 32 | sp-consensus-aura = { version = "0.10.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 33 | sp-core = { version = "6.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 34 | sp-inherents = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19"} 35 | sp-offchain = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 36 | sp-runtime = { version = "6.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 37 | sp-session = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 38 | sp-std = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 39 | sp-transaction-pool = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 40 | sp-version = { version = "5.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 41 | 42 | # Used for the node template's RPCs 43 | frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 44 | pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 45 | 46 | # Used for runtime benchmarking 47 | frame-benchmarking = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19", optional = true } 48 | frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19", optional = true } 49 | hex-literal = { version = "0.3.4", optional = true } 50 | 51 | # Local Dependencies 52 | pallet-template = { version = "4.0.0-dev", default-features = false, path = "../pallets/template" } 53 | 54 | [build-dependencies] 55 | substrate-wasm-builder = { version = "5.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.19" } 56 | 57 | [features] 58 | default = ["std"] 59 | std = [ 60 | "codec/std", 61 | "scale-info/std", 62 | "frame-executive/std", 63 | "frame-support/std", 64 | "frame-system-rpc-runtime-api/std", 65 | "frame-system/std", 66 | "pallet-aura/std", 67 | "pallet-balances/std", 68 | "pallet-grandpa/std", 69 | "pallet-randomness-collective-flip/std", 70 | "pallet-sudo/std", 71 | "pallet-template/std", 72 | "pallet-timestamp/std", 73 | "pallet-transaction-payment-rpc-runtime-api/std", 74 | "pallet-transaction-payment/std", 75 | "sp-api/std", 76 | "sp-block-builder/std", 77 | "sp-consensus-aura/std", 78 | "sp-core/std", 79 | "sp-inherents/std", 80 | "sp-offchain/std", 81 | "sp-runtime/std", 82 | "sp-session/std", 83 | "sp-std/std", 84 | "sp-transaction-pool/std", 85 | "sp-version/std", 86 | ] 87 | runtime-benchmarks = [ 88 | "frame-benchmarking/runtime-benchmarks", 89 | "frame-support/runtime-benchmarks", 90 | "frame-system-benchmarking", 91 | "frame-system/runtime-benchmarks", 92 | "hex-literal", 93 | "pallet-balances/runtime-benchmarks", 94 | "pallet-template/runtime-benchmarks", 95 | "pallet-timestamp/runtime-benchmarks", 96 | "sp-runtime/runtime-benchmarks", 97 | ] 98 | try-runtime = [ 99 | "frame-executive/try-runtime", 100 | "frame-try-runtime", 101 | "frame-system/try-runtime", 102 | "pallet-balances/try-runtime", 103 | "pallet-grandpa/try-runtime", 104 | "pallet-randomness-collective-flip/try-runtime", 105 | "pallet-sudo/try-runtime", 106 | "pallet-timestamp/try-runtime", 107 | "pallet-transaction-payment/try-runtime", 108 | ] 109 | -------------------------------------------------------------------------------- /runtime/build.rs: -------------------------------------------------------------------------------- 1 | use substrate_wasm_builder::WasmBuilder; 2 | 3 | fn main() { 4 | WasmBuilder::new() 5 | .with_current_project() 6 | .export_heap_base() 7 | .import_memory() 8 | .build() 9 | } 10 | -------------------------------------------------------------------------------- /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 | use pallet_grandpa::{ 10 | fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, 11 | }; 12 | use sp_api::impl_runtime_apis; 13 | use sp_consensus_aura::sr25519::AuthorityId as AuraId; 14 | use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; 15 | use sp_runtime::{ 16 | create_runtime_str, generic, impl_opaque_keys, 17 | traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, Verify}, 18 | transaction_validity::{TransactionSource, TransactionValidity}, 19 | ApplyExtrinsicResult, MultiSignature, 20 | }; 21 | use sp_std::prelude::*; 22 | #[cfg(feature = "std")] 23 | use sp_version::NativeVersion; 24 | use sp_version::RuntimeVersion; 25 | 26 | // A few exports that help ease life for downstream crates. 27 | pub use frame_support::{ 28 | construct_runtime, parameter_types, 29 | traits::{ConstU128, ConstU32, ConstU8, KeyOwnerProofSystem, Randomness, StorageInfo}, 30 | weights::{ 31 | constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, 32 | IdentityFee, Weight, 33 | }, 34 | StorageValue, 35 | }; 36 | pub use frame_system::Call as SystemCall; 37 | pub use pallet_balances::Call as BalancesCall; 38 | pub use pallet_timestamp::Call as TimestampCall; 39 | use pallet_transaction_payment::CurrencyAdapter; 40 | #[cfg(any(feature = "std", test))] 41 | pub use sp_runtime::BuildStorage; 42 | pub use sp_runtime::{Perbill, Permill}; 43 | 44 | /// Import the template pallet. 45 | pub use pallet_template; 46 | 47 | /// An index to a block. 48 | pub type BlockNumber = u32; 49 | 50 | /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. 51 | pub type Signature = MultiSignature; 52 | 53 | /// Some way of identifying an account on the chain. We intentionally make it equivalent 54 | /// to the public key of our transaction signing scheme. 55 | pub type AccountId = <::Signer as IdentifyAccount>::AccountId; 56 | 57 | /// Balance of an account. 58 | pub type Balance = u128; 59 | 60 | /// Index of a transaction in the chain. 61 | pub type Index = u32; 62 | 63 | /// A hash of some data used by the chain. 64 | pub type Hash = sp_core::H256; 65 | 66 | /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know 67 | /// the specifics of the runtime. They can then be made to be agnostic over specific formats 68 | /// of data like extrinsics, allowing for them to continue syncing the network through upgrades 69 | /// to even the core data structures. 70 | pub mod opaque { 71 | use super::*; 72 | 73 | pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; 74 | 75 | /// Opaque block header type. 76 | pub type Header = generic::Header; 77 | /// Opaque block type. 78 | pub type Block = generic::Block; 79 | /// Opaque block identifier type. 80 | pub type BlockId = generic::BlockId; 81 | 82 | impl_opaque_keys! { 83 | pub struct SessionKeys { 84 | pub aura: Aura, 85 | pub grandpa: Grandpa, 86 | } 87 | } 88 | } 89 | 90 | // To learn more about runtime versioning and what each of the following value means: 91 | // https://docs.substrate.io/v3/runtime/upgrades#runtime-versioning 92 | #[sp_version::runtime_version] 93 | pub const VERSION: RuntimeVersion = RuntimeVersion { 94 | spec_name: create_runtime_str!("node-template"), 95 | impl_name: create_runtime_str!("node-template"), 96 | authoring_version: 1, 97 | // The version of the runtime specification. A full node will not attempt to use its native 98 | // runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, 99 | // `spec_version`, and `authoring_version` are the same between Wasm and native. 100 | // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use 101 | // the compatible custom types. 102 | spec_version: 100, 103 | impl_version: 1, 104 | apis: RUNTIME_API_VERSIONS, 105 | transaction_version: 1, 106 | state_version: 1, 107 | }; 108 | 109 | /// This determines the average expected block time that we are targeting. 110 | /// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. 111 | /// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked 112 | /// up by `pallet_aura` to implement `fn slot_duration()`. 113 | /// 114 | /// Change this to adjust the block time. 115 | pub const MILLISECS_PER_BLOCK: u64 = 6000; 116 | 117 | // NOTE: Currently it is not possible to change the slot duration after the chain has started. 118 | // Attempting to do so will brick block production. 119 | pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; 120 | 121 | // Time is measured by number of blocks. 122 | pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); 123 | pub const HOURS: BlockNumber = MINUTES * 60; 124 | pub const DAYS: BlockNumber = HOURS * 24; 125 | 126 | /// The version information used to identify this runtime when compiled natively. 127 | #[cfg(feature = "std")] 128 | pub fn native_version() -> NativeVersion { 129 | NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } 130 | } 131 | 132 | const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); 133 | 134 | parameter_types! { 135 | pub const Version: RuntimeVersion = VERSION; 136 | pub const BlockHashCount: BlockNumber = 2400; 137 | /// We allow for 2 seconds of compute with a 6 second average block time. 138 | pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights 139 | ::with_sensible_defaults(2 * WEIGHT_PER_SECOND, NORMAL_DISPATCH_RATIO); 140 | pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength 141 | ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); 142 | pub const SS58Prefix: u8 = 42; 143 | } 144 | 145 | // Configure FRAME pallets to include in runtime. 146 | 147 | impl frame_system::Config for Runtime { 148 | /// The basic call filter to use in dispatchable. 149 | type BaseCallFilter = frame_support::traits::Everything; 150 | /// Block & extrinsics weights: base values and limits. 151 | type BlockWeights = BlockWeights; 152 | /// The maximum length of a block (in bytes). 153 | type BlockLength = BlockLength; 154 | /// The identifier used to distinguish between accounts. 155 | type AccountId = AccountId; 156 | /// The aggregated dispatch type that is available for extrinsics. 157 | type Call = Call; 158 | /// The lookup mechanism to get account ID from whatever is passed in dispatchers. 159 | type Lookup = AccountIdLookup; 160 | /// The index type for storing how many extrinsics an account has signed. 161 | type Index = Index; 162 | /// The index type for blocks. 163 | type BlockNumber = BlockNumber; 164 | /// The type for hashing blocks and tries. 165 | type Hash = Hash; 166 | /// The hashing algorithm used. 167 | type Hashing = BlakeTwo256; 168 | /// The header type. 169 | type Header = generic::Header; 170 | /// The ubiquitous event type. 171 | type Event = Event; 172 | /// The ubiquitous origin type. 173 | type Origin = Origin; 174 | /// Maximum number of block number to block hash mappings to keep (oldest pruned first). 175 | type BlockHashCount = BlockHashCount; 176 | /// The weight of database operations that the runtime can invoke. 177 | type DbWeight = RocksDbWeight; 178 | /// Version of the runtime. 179 | type Version = Version; 180 | /// Converts a module to the index of the module in `construct_runtime!`. 181 | /// 182 | /// This type is being generated by `construct_runtime!`. 183 | type PalletInfo = PalletInfo; 184 | /// What to do if a new account is created. 185 | type OnNewAccount = (); 186 | /// What to do if an account is fully reaped from the system. 187 | type OnKilledAccount = (); 188 | /// The data to be stored in an account. 189 | type AccountData = pallet_balances::AccountData; 190 | /// Weight information for the extrinsics of this pallet. 191 | type SystemWeightInfo = (); 192 | /// This is used as an identifier of the chain. 42 is the generic substrate prefix. 193 | type SS58Prefix = SS58Prefix; 194 | /// The set code logic, just the default since we're not a parachain. 195 | type OnSetCode = (); 196 | type MaxConsumers = frame_support::traits::ConstU32<16>; 197 | } 198 | 199 | impl pallet_randomness_collective_flip::Config for Runtime {} 200 | 201 | impl pallet_aura::Config for Runtime { 202 | type AuthorityId = AuraId; 203 | type DisabledValidators = (); 204 | type MaxAuthorities = ConstU32<32>; 205 | } 206 | 207 | impl pallet_grandpa::Config for Runtime { 208 | type Event = Event; 209 | type Call = Call; 210 | 211 | type KeyOwnerProofSystem = (); 212 | 213 | type KeyOwnerProof = 214 | >::Proof; 215 | 216 | type KeyOwnerIdentification = >::IdentificationTuple; 220 | 221 | type HandleEquivocation = (); 222 | 223 | type WeightInfo = (); 224 | type MaxAuthorities = ConstU32<32>; 225 | } 226 | 227 | parameter_types! { 228 | pub const MinimumPeriod: u64 = SLOT_DURATION / 2; 229 | } 230 | 231 | impl pallet_timestamp::Config for Runtime { 232 | /// A timestamp: milliseconds since the unix epoch. 233 | type Moment = u64; 234 | type OnTimestampSet = Aura; 235 | type MinimumPeriod = MinimumPeriod; 236 | type WeightInfo = (); 237 | } 238 | 239 | impl pallet_balances::Config for Runtime { 240 | type MaxLocks = ConstU32<50>; 241 | type MaxReserves = (); 242 | type ReserveIdentifier = [u8; 8]; 243 | /// The type for recording an account's balance. 244 | type Balance = Balance; 245 | /// The ubiquitous event type. 246 | type Event = Event; 247 | type DustRemoval = (); 248 | type ExistentialDeposit = ConstU128<500>; 249 | type AccountStore = System; 250 | type WeightInfo = pallet_balances::weights::SubstrateWeight; 251 | } 252 | 253 | impl pallet_transaction_payment::Config for Runtime { 254 | type OnChargeTransaction = CurrencyAdapter; 255 | type OperationalFeeMultiplier = ConstU8<5>; 256 | type WeightToFee = IdentityFee; 257 | type LengthToFee = IdentityFee; 258 | type FeeMultiplierUpdate = (); 259 | } 260 | 261 | impl pallet_sudo::Config for Runtime { 262 | type Event = Event; 263 | type Call = Call; 264 | } 265 | 266 | /// Configure the pallet-template in pallets/template. 267 | impl pallet_template::Config for Runtime { 268 | type Event = Event; 269 | } 270 | 271 | // Create the runtime by composing the FRAME pallets that were previously configured. 272 | construct_runtime!( 273 | pub enum Runtime where 274 | Block = Block, 275 | NodeBlock = opaque::Block, 276 | UncheckedExtrinsic = UncheckedExtrinsic 277 | { 278 | System: frame_system, 279 | RandomnessCollectiveFlip: pallet_randomness_collective_flip, 280 | Timestamp: pallet_timestamp, 281 | Aura: pallet_aura, 282 | Grandpa: pallet_grandpa, 283 | Balances: pallet_balances, 284 | TransactionPayment: pallet_transaction_payment, 285 | Sudo: pallet_sudo, 286 | // Include the custom logic from the pallet-template in the runtime. 287 | TemplateModule: pallet_template, 288 | } 289 | ); 290 | 291 | /// The address format for describing accounts. 292 | pub type Address = sp_runtime::MultiAddress; 293 | /// Block header type as expected by this runtime. 294 | pub type Header = generic::Header; 295 | /// Block type as expected by this runtime. 296 | pub type Block = generic::Block; 297 | /// The SignedExtension to the basic transaction logic. 298 | pub type SignedExtra = ( 299 | frame_system::CheckNonZeroSender, 300 | frame_system::CheckSpecVersion, 301 | frame_system::CheckTxVersion, 302 | frame_system::CheckGenesis, 303 | frame_system::CheckEra, 304 | frame_system::CheckNonce, 305 | frame_system::CheckWeight, 306 | pallet_transaction_payment::ChargeTransactionPayment, 307 | ); 308 | /// Unchecked extrinsic type as expected by this runtime. 309 | pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; 310 | /// The payload being signed in transactions. 311 | pub type SignedPayload = generic::SignedPayload; 312 | /// Executive: handles dispatch to the various modules. 313 | pub type Executive = frame_executive::Executive< 314 | Runtime, 315 | Block, 316 | frame_system::ChainContext, 317 | Runtime, 318 | AllPalletsWithSystem, 319 | >; 320 | 321 | #[cfg(feature = "runtime-benchmarks")] 322 | #[macro_use] 323 | extern crate frame_benchmarking; 324 | 325 | #[cfg(feature = "runtime-benchmarks")] 326 | mod benches { 327 | define_benchmarks!( 328 | [frame_benchmarking, BaselineBench::] 329 | [frame_system, SystemBench::] 330 | [pallet_balances, Balances] 331 | [pallet_timestamp, Timestamp] 332 | [pallet_template, TemplateModule] 333 | ); 334 | } 335 | 336 | impl_runtime_apis! { 337 | impl sp_api::Core for Runtime { 338 | fn version() -> RuntimeVersion { 339 | VERSION 340 | } 341 | 342 | fn execute_block(block: Block) { 343 | Executive::execute_block(block); 344 | } 345 | 346 | fn initialize_block(header: &::Header) { 347 | Executive::initialize_block(header) 348 | } 349 | } 350 | 351 | impl sp_api::Metadata for Runtime { 352 | fn metadata() -> OpaqueMetadata { 353 | OpaqueMetadata::new(Runtime::metadata().into()) 354 | } 355 | } 356 | 357 | impl sp_block_builder::BlockBuilder for Runtime { 358 | fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { 359 | Executive::apply_extrinsic(extrinsic) 360 | } 361 | 362 | fn finalize_block() -> ::Header { 363 | Executive::finalize_block() 364 | } 365 | 366 | fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { 367 | data.create_extrinsics() 368 | } 369 | 370 | fn check_inherents( 371 | block: Block, 372 | data: sp_inherents::InherentData, 373 | ) -> sp_inherents::CheckInherentsResult { 374 | data.check_extrinsics(&block) 375 | } 376 | } 377 | 378 | impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { 379 | fn validate_transaction( 380 | source: TransactionSource, 381 | tx: ::Extrinsic, 382 | block_hash: ::Hash, 383 | ) -> TransactionValidity { 384 | Executive::validate_transaction(source, tx, block_hash) 385 | } 386 | } 387 | 388 | impl sp_offchain::OffchainWorkerApi for Runtime { 389 | fn offchain_worker(header: &::Header) { 390 | Executive::offchain_worker(header) 391 | } 392 | } 393 | 394 | impl sp_consensus_aura::AuraApi for Runtime { 395 | fn slot_duration() -> sp_consensus_aura::SlotDuration { 396 | sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) 397 | } 398 | 399 | fn authorities() -> Vec { 400 | Aura::authorities().into_inner() 401 | } 402 | } 403 | 404 | impl sp_session::SessionKeys for Runtime { 405 | fn generate_session_keys(seed: Option>) -> Vec { 406 | opaque::SessionKeys::generate(seed) 407 | } 408 | 409 | fn decode_session_keys( 410 | encoded: Vec, 411 | ) -> Option, KeyTypeId)>> { 412 | opaque::SessionKeys::decode_into_raw_public_keys(&encoded) 413 | } 414 | } 415 | 416 | impl fg_primitives::GrandpaApi for Runtime { 417 | fn grandpa_authorities() -> GrandpaAuthorityList { 418 | Grandpa::grandpa_authorities() 419 | } 420 | 421 | fn current_set_id() -> fg_primitives::SetId { 422 | Grandpa::current_set_id() 423 | } 424 | 425 | fn submit_report_equivocation_unsigned_extrinsic( 426 | _equivocation_proof: fg_primitives::EquivocationProof< 427 | ::Hash, 428 | NumberFor, 429 | >, 430 | _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, 431 | ) -> Option<()> { 432 | None 433 | } 434 | 435 | fn generate_key_ownership_proof( 436 | _set_id: fg_primitives::SetId, 437 | _authority_id: GrandpaId, 438 | ) -> Option { 439 | // NOTE: this is the only implementation possible since we've 440 | // defined our key owner proof type as a bottom type (i.e. a type 441 | // with no values). 442 | None 443 | } 444 | } 445 | 446 | impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { 447 | fn account_nonce(account: AccountId) -> Index { 448 | System::account_nonce(account) 449 | } 450 | } 451 | 452 | impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { 453 | fn query_info( 454 | uxt: ::Extrinsic, 455 | len: u32, 456 | ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { 457 | TransactionPayment::query_info(uxt, len) 458 | } 459 | fn query_fee_details( 460 | uxt: ::Extrinsic, 461 | len: u32, 462 | ) -> pallet_transaction_payment::FeeDetails { 463 | TransactionPayment::query_fee_details(uxt, len) 464 | } 465 | } 466 | 467 | #[cfg(feature = "runtime-benchmarks")] 468 | impl frame_benchmarking::Benchmark for Runtime { 469 | fn benchmark_metadata(extra: bool) -> ( 470 | Vec, 471 | Vec, 472 | ) { 473 | use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; 474 | use frame_support::traits::StorageInfoTrait; 475 | use frame_system_benchmarking::Pallet as SystemBench; 476 | use baseline::Pallet as BaselineBench; 477 | 478 | let mut list = Vec::::new(); 479 | list_benchmarks!(list, extra); 480 | 481 | let storage_info = AllPalletsWithSystem::storage_info(); 482 | 483 | return (list, storage_info) 484 | } 485 | 486 | fn dispatch_benchmark( 487 | config: frame_benchmarking::BenchmarkConfig 488 | ) -> Result, sp_runtime::RuntimeString> { 489 | use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, TrackedStorageKey}; 490 | 491 | use frame_system_benchmarking::Pallet as SystemBench; 492 | use baseline::Pallet as BaselineBench; 493 | 494 | impl frame_system_benchmarking::Config for Runtime {} 495 | impl baseline::Config for Runtime {} 496 | 497 | let whitelist: Vec = vec![ 498 | // Block Number 499 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), 500 | // Total Issuance 501 | hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(), 502 | // Execution Phase 503 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), 504 | // Event Count 505 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), 506 | // System Events 507 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), 508 | ]; 509 | 510 | let mut batches = Vec::::new(); 511 | let params = (&config, &whitelist); 512 | add_benchmarks!(params, batches); 513 | 514 | Ok(batches) 515 | } 516 | } 517 | 518 | #[cfg(feature = "try-runtime")] 519 | impl frame_try_runtime::TryRuntime for Runtime { 520 | fn on_runtime_upgrade() -> (Weight, Weight) { 521 | // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to 522 | // have a backtrace here. If any of the pre/post migration checks fail, we shall stop 523 | // right here and right now. 524 | let weight = Executive::try_runtime_upgrade().unwrap(); 525 | (weight, BlockWeights::get().max_block) 526 | } 527 | 528 | fn execute_block_no_check(block: Block) -> Weight { 529 | Executive::execute_block_no_check(block) 530 | } 531 | } 532 | } 533 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /scripts/docker_run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script is meant to be run on Unix/Linux based systems 3 | set -e 4 | 5 | echo "*** Start Substrate node template ***" 6 | 7 | cd $(dirname ${BASH_SOURCE[0]})/.. 8 | 9 | docker-compose down --remove-orphans 10 | docker-compose run --rm --service-ports dev $@ 11 | -------------------------------------------------------------------------------- /scripts/init.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script is meant to be run on Unix/Linux based systems 3 | set -e 4 | 5 | echo "*** Initializing WASM build environment" 6 | 7 | if [ -z $CI_PROJECT_NAME ] ; then 8 | rustup update nightly 9 | rustup update stable 10 | fi 11 | 12 | rustup target add wasm32-unknown-unknown --toolchain nightly 13 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | let 2 | mozillaOverlay = 3 | import (builtins.fetchGit { 4 | url = "https://github.com/mozilla/nixpkgs-mozilla.git"; 5 | rev = "57c8084c7ef41366993909c20491e359bbb90f54"; 6 | }); 7 | pinned = builtins.fetchGit { 8 | # Descriptive name to make the store path easier to identify 9 | url = "https://github.com/nixos/nixpkgs/"; 10 | # Commit hash for nixos-unstable as of 2020-04-26 11 | # `git ls-remote https://github.com/nixos/nixpkgs nixos-unstable` 12 | ref = "refs/heads/nixos-unstable"; 13 | rev = "1fe6ed37fd9beb92afe90671c0c2a662a03463dd"; 14 | }; 15 | nixpkgs = import pinned { overlays = [ mozillaOverlay ]; }; 16 | toolchain = with nixpkgs; (rustChannelOf { date = "2021-09-14"; channel = "nightly"; }); 17 | rust-wasm = toolchain.rust.override { 18 | targets = [ "wasm32-unknown-unknown" ]; 19 | }; 20 | in 21 | with nixpkgs; pkgs.mkShell { 22 | buildInputs = [ 23 | clang 24 | pkg-config 25 | rust-wasm 26 | ] ++ stdenv.lib.optionals stdenv.isDarwin [ 27 | darwin.apple_sdk.frameworks.Security 28 | ]; 29 | 30 | LIBCLANG_PATH = "${llvmPackages.libclang}/lib"; 31 | PROTOC = "${protobuf}/bin/protoc"; 32 | RUST_SRC_PATH = "${toolchain.rust-src}/lib/rustlib/src/rust/library/"; 33 | ROCKSDB_LIB_DIR = "${rocksdb}/lib"; 34 | 35 | } 36 | --------------------------------------------------------------------------------