├── pallets └── template │ ├── README.md │ ├── src │ ├── benchmarking.rs │ ├── tests.rs │ ├── mock.rs │ └── lib.rs │ └── Cargo.toml ├── node ├── src │ ├── lib.rs │ ├── main.rs │ ├── cli.rs │ ├── rpc.rs │ ├── command.rs │ ├── chain_spec.rs │ └── service.rs ├── build.rs └── Cargo.toml ├── Cargo.toml ├── .envrc ├── runtime ├── build.rs ├── Cargo.toml └── src │ └── lib.rs ├── .editorconfig ├── scripts ├── docker_run.sh └── init.sh ├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── ask-a-question.md │ ├── suggest-a-feature.md │ └── report-a-bug.md └── workflows │ └── check.yml ├── docker-compose.yml ├── rustfmt.toml ├── .devcontainer └── devcontainer.json ├── .vscode └── tasks.json ├── LICENSE ├── shell.nix ├── docs └── rust-setup.md └── README.md /pallets/template/README.md: -------------------------------------------------------------------------------- 1 | License: Unlicense -------------------------------------------------------------------------------- /node/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod chain_spec; 2 | pub mod rpc; 3 | pub mod service; 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | 'node', 4 | 'pallets/template', 5 | 'runtime', 6 | ] 7 | [profile.release] 8 | panic = 'unwind' 9 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 rpc; 10 | 11 | fn main() -> sc_cli::Result<()> { 12 | command::run() 13 | } 14 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | **/target/ 4 | # These are backup files generated by rustfmt 5 | **/*.rs.bk 6 | 7 | .DS_Store 8 | 9 | # The cache for docker container dependency 10 | .cargo 11 | 12 | # The cache for chain data in container 13 | .local 14 | 15 | # direnv cache 16 | .direnv 17 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/ask-a-question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Ask a Question 3 | about: Ask a question about this template. 4 | title: "" 5 | labels: question 6 | assignees: "" 7 | --- 8 | 9 | **Question** 10 | 11 | _Please include information such as the following: is your question to clarify an existing resource 12 | or are you asking about something new? what are you trying to accomplish? where have you looked for 13 | answers?_ 14 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/suggest-a-feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Suggest a Feature 3 | about: Suggest a new feature or an improvement to an existing feature for this template. 4 | title: "" 5 | labels: enhancement 6 | assignees: "" 7 | --- 8 | 9 | **Motivation** 10 | 11 | _Describe the need or frustration that motivated you to make this suggestion. Please note that the 12 | goal of this project is to provide a general-purpose template project, so please take care when 13 | suggesting features that may be specific to a particular use case._ 14 | 15 | **Suggested Solution** 16 | 17 | _Describe your suggested solution to the need or frustration that you are experiencing._ 18 | 19 | **Alternatives** 20 | 21 | _Describe any alternative solutions or features you considered and why you believe your suggested 22 | solution is preferable._ 23 | 24 | **Additional Information** 25 | 26 | _Provide any additional information that you believe may help us evaluate your suggestion._ 27 | -------------------------------------------------------------------------------- /node/src/cli.rs: -------------------------------------------------------------------------------- 1 | use sc_cli::RunCmd; 2 | use structopt::StructOpt; 3 | 4 | #[derive(Debug, StructOpt)] 5 | pub struct Cli { 6 | #[structopt(subcommand)] 7 | pub subcommand: Option, 8 | 9 | #[structopt(flatten)] 10 | pub run: RunCmd, 11 | } 12 | 13 | #[derive(Debug, StructOpt)] 14 | pub enum Subcommand { 15 | /// Key management cli utilities 16 | Key(sc_cli::KeySubcommand), 17 | /// Build a chain specification. 18 | BuildSpec(sc_cli::BuildSpecCmd), 19 | 20 | /// Validate blocks. 21 | CheckBlock(sc_cli::CheckBlockCmd), 22 | 23 | /// Export blocks. 24 | ExportBlocks(sc_cli::ExportBlocksCmd), 25 | 26 | /// Export the state of a given block into a chain spec. 27 | ExportState(sc_cli::ExportStateCmd), 28 | 29 | /// Import blocks. 30 | ImportBlocks(sc_cli::ImportBlocksCmd), 31 | 32 | /// Remove the whole chain. 33 | PurgeChain(sc_cli::PurgeChainCmd), 34 | 35 | /// Revert the chain to a previous state. 36 | Revert(sc_cli::RevertCmd), 37 | 38 | /// The custom benchmark subcommand benchmarking runtime pallets. 39 | #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] 40 | Benchmark(frame_benchmarking_cli::BenchmarkCmd), 41 | } 42 | -------------------------------------------------------------------------------- /.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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/report-a-bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Report a Bug 3 | about: Report a problem with this template. 4 | title: "" 5 | labels: bug 6 | assignees: "" 7 | --- 8 | 9 | **Description** 10 | 11 | _Tell us what happened. In particular, be specific about any changes you made to this template. 12 | Ideally, provide a link to your project's GitHub repository. Please note that we are not able to 13 | support all conceivable changes to this template project, but the more information you are able to 14 | provide the more equipped we will be to help._ 15 | 16 | **Steps to Reproduce** 17 | 18 | _Replace the example steps below with actual steps to reproduce the bug you're reporting._ 19 | 20 | 1. Go to '...' 21 | 2. Click on '....' 22 | 3. Scroll down to '....' 23 | 4. See error 24 | 25 | **Expected vs. Actual Behavior** 26 | 27 | _What did you expect to happen after you followed the steps you described in the last section? What 28 | actually happened?_ 29 | 30 | **Environment** 31 | 32 | _Describe the environment in which you encountered this bug. Use the list below as a starting point 33 | and add additional information if you think it's relevant._ 34 | 35 | - Operating system: 36 | - Template version/tag: 37 | - Rust version (run `rustup show`): 38 | 39 | **Logs, Errors or Screenshots** 40 | 41 | _Please provide the text of any logs or errors that you experienced; if 42 | applicable, provide screenshots to help illustrate the problem._ 43 | 44 | **Additional Information** 45 | 46 | _Please add any other details that you think may help us solve your problem._ 47 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: Check Set-Up & Build 2 | 3 | # Controls when the action will run. 4 | on: 5 | # Triggers the workflow on push or pull request events but only for the master branch 6 | push: 7 | branches: [ master ] 8 | pull_request: 9 | branches: [ master ] 10 | 11 | # Allows you to run this workflow manually from the Actions tab 12 | workflow_dispatch: 13 | 14 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 15 | jobs: 16 | check: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-20.04 19 | 20 | # Steps represent a sequence of tasks that will be executed as part of the job 21 | steps: 22 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 23 | - uses: actions/checkout@v2 24 | 25 | - name: Set-Up 26 | run: sudo apt install -y cmake pkg-config libssl-dev git build-essential clang libclang-dev curl 27 | 28 | - name: Install Rustup 29 | run: | 30 | curl https://sh.rustup.rs -sSf | sh -s -- -y 31 | source ~/.cargo/env 32 | rustup default stable 33 | rustup update nightly 34 | rustup update stable 35 | rustup target add wasm32-unknown-unknown --toolchain nightly 36 | 37 | - name: Check Build 38 | run: | 39 | SKIP_WASM_BUILD=1 cargo check --release 40 | 41 | - name: Check Build for Benchmarking 42 | run: > 43 | pushd node && 44 | cargo check --features=runtime-benchmarks --release 45 | -------------------------------------------------------------------------------- /pallets/template/src/mock.rs: -------------------------------------------------------------------------------- 1 | use crate as pallet_template; 2 | use frame_support::parameter_types; 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 | parameter_types! { 26 | pub const BlockHashCount: u64 = 250; 27 | pub const SS58Prefix: u8 = 42; 28 | } 29 | 30 | impl system::Config for Test { 31 | type BaseCallFilter = frame_support::traits::Everything; 32 | type BlockWeights = (); 33 | type BlockLength = (); 34 | type DbWeight = (); 35 | type Origin = Origin; 36 | type Call = Call; 37 | type Index = u64; 38 | type BlockNumber = u64; 39 | type Hash = H256; 40 | type Hashing = BlakeTwo256; 41 | type AccountId = u64; 42 | type Lookup = IdentityLookup; 43 | type Header = Header; 44 | type Event = Event; 45 | type BlockHashCount = BlockHashCount; 46 | type Version = (); 47 | type PalletInfo = PalletInfo; 48 | type AccountData = (); 49 | type OnNewAccount = (); 50 | type OnKilledAccount = (); 51 | type SystemWeightInfo = (); 52 | type SS58Prefix = SS58Prefix; 53 | type OnSetCode = (); 54 | } 55 | 56 | impl pallet_template::Config for Test { 57 | type Event = Event; 58 | } 59 | 60 | // Build genesis storage according to the mock runtime. 61 | pub fn new_test_ext() -> sp_io::TestExternalities { 62 | system::GenesisConfig::default().build_storage::().unwrap().into() 63 | } 64 | -------------------------------------------------------------------------------- /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 = "2.0.0", default-features = false, features = [ 17 | "derive", 18 | ] } 19 | scale-info = { version = "1.0", default-features = false, features = ["derive"] } 20 | frame-support = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest"} 21 | frame-system = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 22 | frame-benchmarking = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest", optional = true } 23 | 24 | [dev-dependencies] 25 | sp-core = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 26 | sp-io = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 27 | sp-runtime = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /docs/rust-setup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | --- 4 | 5 | This page will guide you through the steps needed to prepare a computer for development with the 6 | Substrate Node Template. Since Substrate is built with 7 | [the Rust programming language](https://www.rust-lang.org/), the first thing you will need to do is 8 | prepare the computer for Rust development - these steps will vary based on the computer's operating 9 | system. Once Rust is configured, you will use its toolchains to interact with Rust projects; the 10 | commands for Rust's toolchains will be the same for all supported, Unix-based operating systems. 11 | 12 | ## Unix-Based Operating Systems 13 | 14 | Substrate development is easiest on Unix-based operating systems like macOS or Linux. The examples 15 | in the Substrate [Tutorials](https://docs.substrate.io/tutorials/v3) and 16 | [How-to Guides](https://docs.substrate.io/how-to-guides/v3) use Unix-style terminals to demonstrate 17 | how to interact with Substrate from the command line. 18 | 19 | ### macOS 20 | 21 | Open the Terminal application and execute the following commands: 22 | 23 | ```bash 24 | # Install Homebrew if necessary https://brew.sh/ 25 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" 26 | 27 | # Make sure Homebrew is up-to-date, install openssl and cmake 28 | brew update 29 | brew install openssl cmake 30 | ``` 31 | 32 | ### Ubuntu/Debian 33 | 34 | Use a terminal shell to execute the following commands: 35 | 36 | ```bash 37 | sudo apt update 38 | # May prompt for location information 39 | sudo apt install -y cmake pkg-config libssl-dev git build-essential clang libclang-dev curl 40 | ``` 41 | 42 | ### Arch Linux 43 | 44 | Run these commands from a terminal: 45 | 46 | ```bash 47 | pacman -Syu --needed --noconfirm cmake gcc openssl-1.0 pkgconf git clang 48 | export OPENSSL_LIB_DIR="/usr/lib/openssl-1.0" 49 | export OPENSSL_INCLUDE_DIR="/usr/include/openssl-1.0" 50 | ``` 51 | 52 | ### Fedora/RHEL/CentOS 53 | 54 | Use a terminal to run the following commands: 55 | 56 | ```bash 57 | # Update 58 | sudo dnf update 59 | # Install packages 60 | sudo dnf install cmake pkgconfig rocksdb rocksdb-devel llvm git libcurl libcurl-devel curl-devel clang 61 | ``` 62 | 63 | ## Rust Developer Environment 64 | 65 | This project uses [`rustup`](https://rustup.rs/) to help manage the Rust toolchain. First install 66 | and configure `rustup`: 67 | 68 | ```bash 69 | # Install 70 | curl https://sh.rustup.rs -sSf | sh 71 | # Configure 72 | source ~/.cargo/env 73 | ``` 74 | 75 | Finally, configure the Rust toolchain: 76 | 77 | ```bash 78 | rustup default stable 79 | rustup update nightly 80 | rustup update stable 81 | rustup target add wasm32-unknown-unknown --toolchain nightly 82 | ``` 83 | -------------------------------------------------------------------------------- /node/src/command.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | chain_spec, 3 | cli::{Cli, Subcommand}, 4 | service, 5 | }; 6 | use node_template_runtime::Block; 7 | use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; 8 | use sc_service::PartialComponents; 9 | 10 | impl SubstrateCli for Cli { 11 | fn impl_name() -> String { 12 | "Substrate Node".into() 13 | } 14 | 15 | fn impl_version() -> String { 16 | env!("SUBSTRATE_CLI_IMPL_VERSION").into() 17 | } 18 | 19 | fn description() -> String { 20 | env!("CARGO_PKG_DESCRIPTION").into() 21 | } 22 | 23 | fn author() -> String { 24 | env!("CARGO_PKG_AUTHORS").into() 25 | } 26 | 27 | fn support_url() -> String { 28 | "support.anonymous.an".into() 29 | } 30 | 31 | fn copyright_start_year() -> i32 { 32 | 2017 33 | } 34 | 35 | fn load_spec(&self, id: &str) -> Result, String> { 36 | Ok(match id { 37 | "dev" => Box::new(chain_spec::development_config()?), 38 | "" | "local" => Box::new(chain_spec::local_testnet_config()?), 39 | path => 40 | Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), 41 | }) 42 | } 43 | 44 | fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { 45 | &node_template_runtime::VERSION 46 | } 47 | } 48 | 49 | /// Parse and run command line arguments 50 | pub fn run() -> sc_cli::Result<()> { 51 | let cli = Cli::from_args(); 52 | 53 | match &cli.subcommand { 54 | Some(Subcommand::Key(cmd)) => cmd.run(&cli), 55 | Some(Subcommand::BuildSpec(cmd)) => { 56 | let runner = cli.create_runner(cmd)?; 57 | runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) 58 | }, 59 | Some(Subcommand::CheckBlock(cmd)) => { 60 | let runner = cli.create_runner(cmd)?; 61 | runner.async_run(|config| { 62 | let PartialComponents { client, task_manager, import_queue, .. } = 63 | service::new_partial(&config)?; 64 | Ok((cmd.run(client, import_queue), task_manager)) 65 | }) 66 | }, 67 | Some(Subcommand::ExportBlocks(cmd)) => { 68 | let runner = cli.create_runner(cmd)?; 69 | runner.async_run(|config| { 70 | let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; 71 | Ok((cmd.run(client, config.database), task_manager)) 72 | }) 73 | }, 74 | Some(Subcommand::ExportState(cmd)) => { 75 | let runner = cli.create_runner(cmd)?; 76 | runner.async_run(|config| { 77 | let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; 78 | Ok((cmd.run(client, config.chain_spec), task_manager)) 79 | }) 80 | }, 81 | Some(Subcommand::ImportBlocks(cmd)) => { 82 | let runner = cli.create_runner(cmd)?; 83 | runner.async_run(|config| { 84 | let PartialComponents { client, task_manager, import_queue, .. } = 85 | service::new_partial(&config)?; 86 | Ok((cmd.run(client, import_queue), task_manager)) 87 | }) 88 | }, 89 | Some(Subcommand::PurgeChain(cmd)) => { 90 | let runner = cli.create_runner(cmd)?; 91 | runner.sync_run(|config| cmd.run(config.database)) 92 | }, 93 | Some(Subcommand::Revert(cmd)) => { 94 | let runner = cli.create_runner(cmd)?; 95 | runner.async_run(|config| { 96 | let PartialComponents { client, task_manager, backend, .. } = 97 | service::new_partial(&config)?; 98 | Ok((cmd.run(client, backend), task_manager)) 99 | }) 100 | }, 101 | Some(Subcommand::Benchmark(cmd)) => 102 | if cfg!(feature = "runtime-benchmarks") { 103 | let runner = cli.create_runner(cmd)?; 104 | 105 | runner.sync_run(|config| cmd.run::(config)) 106 | } else { 107 | Err("Benchmarking wasn't enabled when building the node. You can enable it with \ 108 | `--features runtime-benchmarks`." 109 | .into()) 110 | }, 111 | None => { 112 | let runner = cli.create_runner(&cli.run)?; 113 | runner.run_node_until_exit(|config| async move { 114 | service::new_full(config).map_err(sc_cli::Error::Service) 115 | }) 116 | }, 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | structopt = "0.3.25" 21 | 22 | sc-cli = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 23 | sp-core = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 24 | sc-executor = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 25 | sc-service = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 26 | sc-telemetry = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 27 | sc-keystore = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 28 | sc-transaction-pool = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 29 | sc-transaction-pool-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 30 | sc-consensus-aura = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 31 | sp-consensus-aura = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 32 | sp-consensus = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 33 | sc-consensus = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 34 | sc-finality-grandpa = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 35 | sp-finality-grandpa = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 36 | sc-client-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 37 | sp-runtime = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 38 | sp-timestamp = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 39 | 40 | # These dependencies are used for the node template's RPCs 41 | jsonrpc-core = "18.0.0" 42 | sc-rpc = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 43 | sp-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 44 | sc-rpc-api = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 45 | sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 46 | sp-block-builder = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 47 | sc-basic-authorship = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 48 | substrate-frame-rpc-system = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 49 | pallet-transaction-payment-rpc = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 50 | 51 | # These dependencies are used for runtime benchmarking 52 | frame-benchmarking = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 53 | frame-benchmarking-cli = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 54 | 55 | # Local Dependencies 56 | node-template-runtime = { version = "4.0.0-dev", path = "../runtime" } 57 | 58 | [build-dependencies] 59 | substrate-build-script-utils = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 60 | 61 | [features] 62 | default = [] 63 | runtime-benchmarks = [ 64 | "node-template-runtime/runtime-benchmarks", 65 | ] 66 | -------------------------------------------------------------------------------- /node/src/chain_spec.rs: -------------------------------------------------------------------------------- 1 | use node_template_runtime::{ 2 | AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig, 3 | SystemConfig, WASM_BINARY, 4 | }; 5 | use sc_service::ChainType; 6 | use sp_consensus_aura::sr25519::AuthorityId as AuraId; 7 | use sp_core::{sr25519, Pair, Public}; 8 | use sp_finality_grandpa::AuthorityId as GrandpaId; 9 | use sp_runtime::traits::{IdentifyAccount, Verify}; 10 | 11 | // The URL for the telemetry server. 12 | // const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; 13 | 14 | /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. 15 | pub type ChainSpec = sc_service::GenericChainSpec; 16 | 17 | /// Generate a crypto pair from seed. 18 | pub fn get_from_seed(seed: &str) -> ::Public { 19 | TPublic::Pair::from_string(&format!("//{}", seed), None) 20 | .expect("static values are valid; qed") 21 | .public() 22 | } 23 | 24 | type AccountPublic = ::Signer; 25 | 26 | /// Generate an account ID from seed. 27 | pub fn get_account_id_from_seed(seed: &str) -> AccountId 28 | where 29 | AccountPublic: From<::Public>, 30 | { 31 | AccountPublic::from(get_from_seed::(seed)).into_account() 32 | } 33 | 34 | /// Generate an Aura authority key. 35 | pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { 36 | (get_from_seed::(s), get_from_seed::(s)) 37 | } 38 | 39 | pub fn development_config() -> Result { 40 | let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; 41 | 42 | Ok(ChainSpec::from_genesis( 43 | // Name 44 | "Development", 45 | // ID 46 | "dev", 47 | ChainType::Development, 48 | move || { 49 | testnet_genesis( 50 | wasm_binary, 51 | // Initial PoA authorities 52 | vec![authority_keys_from_seed("Alice")], 53 | // Sudo account 54 | get_account_id_from_seed::("Alice"), 55 | // Pre-funded accounts 56 | vec![ 57 | get_account_id_from_seed::("Alice"), 58 | get_account_id_from_seed::("Bob"), 59 | get_account_id_from_seed::("Alice//stash"), 60 | get_account_id_from_seed::("Bob//stash"), 61 | ], 62 | true, 63 | ) 64 | }, 65 | // Bootnodes 66 | vec![], 67 | // Telemetry 68 | None, 69 | // Protocol ID 70 | None, 71 | // Properties 72 | None, 73 | // Extensions 74 | None, 75 | )) 76 | } 77 | 78 | pub fn local_testnet_config() -> Result { 79 | let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; 80 | 81 | Ok(ChainSpec::from_genesis( 82 | // Name 83 | "Local Testnet", 84 | // ID 85 | "local_testnet", 86 | ChainType::Local, 87 | move || { 88 | testnet_genesis( 89 | wasm_binary, 90 | // Initial PoA authorities 91 | vec![authority_keys_from_seed("Alice"), authority_keys_from_seed("Bob")], 92 | // Sudo account 93 | get_account_id_from_seed::("Alice"), 94 | // Pre-funded accounts 95 | vec![ 96 | get_account_id_from_seed::("Alice"), 97 | get_account_id_from_seed::("Bob"), 98 | get_account_id_from_seed::("Charlie"), 99 | get_account_id_from_seed::("Dave"), 100 | get_account_id_from_seed::("Eve"), 101 | get_account_id_from_seed::("Ferdie"), 102 | get_account_id_from_seed::("Alice//stash"), 103 | get_account_id_from_seed::("Bob//stash"), 104 | get_account_id_from_seed::("Charlie//stash"), 105 | get_account_id_from_seed::("Dave//stash"), 106 | get_account_id_from_seed::("Eve//stash"), 107 | get_account_id_from_seed::("Ferdie//stash"), 108 | ], 109 | true, 110 | ) 111 | }, 112 | // Bootnodes 113 | vec![], 114 | // Telemetry 115 | None, 116 | // Protocol ID 117 | None, 118 | // Properties 119 | None, 120 | // Extensions 121 | None, 122 | )) 123 | } 124 | 125 | /// Configure initial storage state for FRAME modules. 126 | fn testnet_genesis( 127 | wasm_binary: &[u8], 128 | initial_authorities: Vec<(AuraId, GrandpaId)>, 129 | root_key: AccountId, 130 | endowed_accounts: Vec, 131 | _enable_println: bool, 132 | ) -> GenesisConfig { 133 | GenesisConfig { 134 | system: SystemConfig { 135 | // Add Wasm runtime to storage. 136 | code: wasm_binary.to_vec(), 137 | }, 138 | balances: BalancesConfig { 139 | // Configure endowed accounts with initial balance of 1 << 60. 140 | balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), 141 | }, 142 | aura: AuraConfig { 143 | authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), 144 | }, 145 | grandpa: GrandpaConfig { 146 | authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), 147 | }, 148 | sudo: SudoConfig { 149 | // Assign network admin rights. 150 | key: root_key, 151 | }, 152 | transaction_payment: Default::default(), 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /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 = "2.0.0", default-features = false, features = ["derive"] } 17 | scale-info = { version = "1.0", default-features = false, features = ["derive"] } 18 | 19 | pallet-aura = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 20 | pallet-balances = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 21 | frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 22 | pallet-grandpa = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 23 | pallet-randomness-collective-flip = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 24 | pallet-sudo = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 25 | frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 26 | pallet-timestamp = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 27 | pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 28 | frame-executive = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 29 | sp-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 30 | sp-block-builder = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest"} 31 | sp-consensus-aura = { version = "0.10.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 32 | sp-core = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 33 | sp-inherents = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest"} 34 | sp-offchain = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 35 | sp-runtime = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 36 | sp-session = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 37 | sp-std = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 38 | sp-transaction-pool = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 39 | sp-version = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 40 | 41 | # Used for the node template's RPCs 42 | frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 43 | pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 44 | 45 | # Used for runtime benchmarking 46 | frame-benchmarking = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest", optional = true } 47 | frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest", optional = true } 48 | hex-literal = { version = "0.3.4", optional = true } 49 | 50 | # Local Dependencies 51 | pallet-template = { version = "4.0.0-dev", default-features = false, path = "../pallets/template" } 52 | 53 | [build-dependencies] 54 | substrate-wasm-builder = { version = "5.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "devhub/latest" } 55 | 56 | [features] 57 | default = ["std"] 58 | std = [ 59 | "codec/std", 60 | "scale-info/std", 61 | "frame-executive/std", 62 | "frame-support/std", 63 | "frame-system-rpc-runtime-api/std", 64 | "frame-system/std", 65 | "pallet-aura/std", 66 | "pallet-balances/std", 67 | "pallet-grandpa/std", 68 | "pallet-randomness-collective-flip/std", 69 | "pallet-sudo/std", 70 | "pallet-template/std", 71 | "pallet-timestamp/std", 72 | "pallet-transaction-payment-rpc-runtime-api/std", 73 | "pallet-transaction-payment/std", 74 | "sp-api/std", 75 | "sp-block-builder/std", 76 | "sp-consensus-aura/std", 77 | "sp-core/std", 78 | "sp-inherents/std", 79 | "sp-offchain/std", 80 | "sp-runtime/std", 81 | "sp-session/std", 82 | "sp-std/std", 83 | "sp-transaction-pool/std", 84 | "sp-version/std", 85 | ] 86 | runtime-benchmarks = [ 87 | "frame-benchmarking/runtime-benchmarks", 88 | "frame-support/runtime-benchmarks", 89 | "frame-system-benchmarking", 90 | "frame-system/runtime-benchmarks", 91 | "hex-literal", 92 | "pallet-balances/runtime-benchmarks", 93 | "pallet-template/runtime-benchmarks", 94 | "pallet-timestamp/runtime-benchmarks", 95 | "sp-runtime/runtime-benchmarks", 96 | ] 97 | -------------------------------------------------------------------------------- /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 compromised 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 | -------------------------------------------------------------------------------- /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::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::SlotData; 12 | use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; 13 | use std::{sync::Arc, time::Duration}; 14 | 15 | // Our native executor instance. 16 | pub struct ExecutorDispatch; 17 | 18 | impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { 19 | /// Only enable the benchmarking host functions when we actually want to benchmark. 20 | #[cfg(feature = "runtime-benchmarks")] 21 | type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; 22 | /// Otherwise we only use the default Substrate host functions. 23 | #[cfg(not(feature = "runtime-benchmarks"))] 24 | type ExtendHostFunctions = (); 25 | 26 | fn dispatch(method: &str, data: &[u8]) -> Option> { 27 | node_template_runtime::api::dispatch(method, data) 28 | } 29 | 30 | fn native_version() -> sc_executor::NativeVersion { 31 | node_template_runtime::native_version() 32 | } 33 | } 34 | 35 | type FullClient = 36 | sc_service::TFullClient>; 37 | type FullBackend = sc_service::TFullBackend; 38 | type FullSelectChain = sc_consensus::LongestChain; 39 | 40 | pub fn new_partial( 41 | config: &Configuration, 42 | ) -> Result< 43 | sc_service::PartialComponents< 44 | FullClient, 45 | FullBackend, 46 | FullSelectChain, 47 | sc_consensus::DefaultImportQueue, 48 | sc_transaction_pool::FullPool, 49 | ( 50 | sc_finality_grandpa::GrandpaBlockImport< 51 | FullBackend, 52 | Block, 53 | FullClient, 54 | FullSelectChain, 55 | >, 56 | sc_finality_grandpa::LinkHalf, 57 | Option, 58 | ), 59 | >, 60 | ServiceError, 61 | > { 62 | if config.keystore_remote.is_some() { 63 | return Err(ServiceError::Other(format!("Remote Keystores are not supported."))) 64 | } 65 | 66 | let telemetry = config 67 | .telemetry_endpoints 68 | .clone() 69 | .filter(|x| !x.is_empty()) 70 | .map(|endpoints| -> Result<_, sc_telemetry::Error> { 71 | let worker = TelemetryWorker::new(16)?; 72 | let telemetry = worker.handle().new_telemetry(endpoints); 73 | Ok((worker, telemetry)) 74 | }) 75 | .transpose()?; 76 | 77 | let executor = NativeElseWasmExecutor::::new( 78 | config.wasm_method, 79 | config.default_heap_pages, 80 | config.max_runtime_instances, 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)?.slot_duration(); 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_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 | 183 | config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); 184 | let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( 185 | backend.clone(), 186 | grandpa_link.shared_authority_set().clone(), 187 | Vec::default(), 188 | )); 189 | 190 | let (network, system_rpc_tx, network_starter) = 191 | sc_service::build_network(sc_service::BuildNetworkParams { 192 | config: &config, 193 | client: client.clone(), 194 | transaction_pool: transaction_pool.clone(), 195 | spawn_handle: task_manager.spawn_handle(), 196 | import_queue, 197 | block_announce_validator_builder: None, 198 | warp_sync: Some(warp_sync), 199 | })?; 200 | 201 | if config.offchain_worker.enabled { 202 | sc_service::build_offchain_workers( 203 | &config, 204 | task_manager.spawn_handle(), 205 | client.clone(), 206 | network.clone(), 207 | ); 208 | } 209 | 210 | let role = config.role.clone(); 211 | let force_authoring = config.force_authoring; 212 | let backoff_authoring_blocks: Option<()> = None; 213 | let name = config.network.node_name.clone(); 214 | let enable_grandpa = !config.disable_grandpa; 215 | let prometheus_registry = config.prometheus_registry().cloned(); 216 | 217 | let rpc_extensions_builder = { 218 | let client = client.clone(); 219 | let pool = transaction_pool.clone(); 220 | 221 | Box::new(move |deny_unsafe, _| { 222 | let deps = 223 | crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; 224 | 225 | Ok(crate::rpc::create_full(deps)) 226 | }) 227 | }; 228 | 229 | let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { 230 | network: network.clone(), 231 | client: client.clone(), 232 | keystore: keystore_container.sync_keystore(), 233 | task_manager: &mut task_manager, 234 | transaction_pool: transaction_pool.clone(), 235 | rpc_extensions_builder, 236 | backend, 237 | system_rpc_tx, 238 | config, 239 | telemetry: telemetry.as_mut(), 240 | })?; 241 | 242 | if role.is_authority() { 243 | let proposer_factory = sc_basic_authorship::ProposerFactory::new( 244 | task_manager.spawn_handle(), 245 | client.clone(), 246 | transaction_pool, 247 | prometheus_registry.as_ref(), 248 | telemetry.as_ref().map(|x| x.handle()), 249 | ); 250 | 251 | let can_author_with = 252 | sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); 253 | 254 | let slot_duration = sc_consensus_aura::slot_duration(&*client)?; 255 | let raw_slot_duration = slot_duration.slot_duration(); 256 | 257 | let aura = sc_consensus_aura::start_aura::( 258 | StartAuraParams { 259 | slot_duration, 260 | client: client.clone(), 261 | select_chain, 262 | block_import, 263 | proposer_factory, 264 | create_inherent_data_providers: move |_, ()| async move { 265 | let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); 266 | 267 | let slot = 268 | sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( 269 | *timestamp, 270 | raw_slot_duration, 271 | ); 272 | 273 | Ok((timestamp, slot)) 274 | }, 275 | force_authoring, 276 | backoff_authoring_blocks, 277 | keystore: keystore_container.sync_keystore(), 278 | can_author_with, 279 | sync_oracle: network.clone(), 280 | justification_sync_link: network.clone(), 281 | block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), 282 | max_block_proposal_slot_portion: None, 283 | telemetry: telemetry.as_ref().map(|x| x.handle()), 284 | }, 285 | )?; 286 | 287 | // the AURA authoring task is considered essential, i.e. if it 288 | // fails we take down the service with it. 289 | task_manager 290 | .spawn_essential_handle() 291 | .spawn_blocking("aura", Some("block-authoring"), aura); 292 | } 293 | 294 | // if the node isn't actively participating in consensus then it doesn't 295 | // need a keystore, regardless of which protocol we use below. 296 | let keystore = 297 | if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; 298 | 299 | let grandpa_config = sc_finality_grandpa::Config { 300 | // FIXME #1578 make this available through chainspec 301 | gossip_duration: Duration::from_millis(333), 302 | justification_period: 512, 303 | name: Some(name), 304 | observer_enabled: false, 305 | keystore, 306 | local_role: role, 307 | telemetry: telemetry.as_ref().map(|x| x.handle()), 308 | }; 309 | 310 | if enable_grandpa { 311 | // start the full GRANDPA voter 312 | // NOTE: non-authorities could run the GRANDPA observer protocol, but at 313 | // this point the full voter should provide better guarantees of block 314 | // and vote data availability than the observer. The observer has not 315 | // been tested extensively yet and having most nodes in a network run it 316 | // could lead to finality stalls. 317 | let grandpa_config = sc_finality_grandpa::GrandpaParams { 318 | config: grandpa_config, 319 | link: grandpa_link, 320 | network, 321 | voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), 322 | prometheus_registry, 323 | shared_voter_state: SharedVoterState::empty(), 324 | telemetry: telemetry.as_ref().map(|x| x.handle()), 325 | }; 326 | 327 | // the GRANDPA voter task is considered infallible, i.e. 328 | // if it fails we take down the service with it. 329 | task_manager.spawn_essential_handle().spawn_blocking( 330 | "grandpa-voter", 331 | None, 332 | sc_finality_grandpa::run_grandpa_voter(grandpa_config)?, 333 | ); 334 | } 335 | 336 | network_starter.start_network(); 337 | Ok(task_manager) 338 | } 339 | -------------------------------------------------------------------------------- /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::{KeyOwnerProofSystem, Randomness, StorageInfo}, 30 | weights::{ 31 | constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, 32 | IdentityFee, Weight, 33 | }, 34 | StorageValue, 35 | }; 36 | pub use pallet_balances::Call as BalancesCall; 37 | pub use pallet_timestamp::Call as TimestampCall; 38 | use pallet_transaction_payment::CurrencyAdapter; 39 | #[cfg(any(feature = "std", test))] 40 | pub use sp_runtime::BuildStorage; 41 | pub use sp_runtime::{Perbill, Permill}; 42 | 43 | /// Import the template pallet. 44 | pub use pallet_template; 45 | 46 | /// An index to a block. 47 | pub type BlockNumber = u32; 48 | 49 | /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. 50 | pub type Signature = MultiSignature; 51 | 52 | /// Some way of identifying an account on the chain. We intentionally make it equivalent 53 | /// to the public key of our transaction signing scheme. 54 | pub type AccountId = <::Signer as IdentifyAccount>::AccountId; 55 | 56 | /// Balance of an account. 57 | pub type Balance = u128; 58 | 59 | /// Index of a transaction in the chain. 60 | pub type Index = u32; 61 | 62 | /// A hash of some data used by the chain. 63 | pub type Hash = sp_core::H256; 64 | 65 | /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know 66 | /// the specifics of the runtime. They can then be made to be agnostic over specific formats 67 | /// of data like extrinsics, allowing for them to continue syncing the network through upgrades 68 | /// to even the core data structures. 69 | pub mod opaque { 70 | use super::*; 71 | 72 | pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; 73 | 74 | /// Opaque block header type. 75 | pub type Header = generic::Header; 76 | /// Opaque block type. 77 | pub type Block = generic::Block; 78 | /// Opaque block identifier type. 79 | pub type BlockId = generic::BlockId; 80 | 81 | impl_opaque_keys! { 82 | pub struct SessionKeys { 83 | pub aura: Aura, 84 | pub grandpa: Grandpa, 85 | } 86 | } 87 | } 88 | 89 | // To learn more about runtime versioning and what each of the following value means: 90 | // https://docs.substrate.io/v3/runtime/upgrades#runtime-versioning 91 | #[sp_version::runtime_version] 92 | pub const VERSION: RuntimeVersion = RuntimeVersion { 93 | spec_name: create_runtime_str!("node-template"), 94 | impl_name: create_runtime_str!("node-template"), 95 | authoring_version: 1, 96 | // The version of the runtime specification. A full node will not attempt to use its native 97 | // runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, 98 | // `spec_version`, and `authoring_version` are the same between Wasm and native. 99 | // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use 100 | // the compatible custom types. 101 | spec_version: 100, 102 | impl_version: 1, 103 | apis: RUNTIME_API_VERSIONS, 104 | transaction_version: 1, 105 | }; 106 | 107 | /// This determines the average expected block time that we are targeting. 108 | /// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. 109 | /// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked 110 | /// up by `pallet_aura` to implement `fn slot_duration()`. 111 | /// 112 | /// Change this to adjust the block time. 113 | pub const MILLISECS_PER_BLOCK: u64 = 6000; 114 | 115 | // NOTE: Currently it is not possible to change the slot duration after the chain has started. 116 | // Attempting to do so will brick block production. 117 | pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; 118 | 119 | // Time is measured by number of blocks. 120 | pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); 121 | pub const HOURS: BlockNumber = MINUTES * 60; 122 | pub const DAYS: BlockNumber = HOURS * 24; 123 | 124 | /// The version information used to identify this runtime when compiled natively. 125 | #[cfg(feature = "std")] 126 | pub fn native_version() -> NativeVersion { 127 | NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } 128 | } 129 | 130 | const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); 131 | 132 | parameter_types! { 133 | pub const Version: RuntimeVersion = VERSION; 134 | pub const BlockHashCount: BlockNumber = 2400; 135 | /// We allow for 2 seconds of compute with a 6 second average block time. 136 | pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights 137 | ::with_sensible_defaults(2 * WEIGHT_PER_SECOND, NORMAL_DISPATCH_RATIO); 138 | pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength 139 | ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); 140 | pub const SS58Prefix: u8 = 42; 141 | } 142 | 143 | // Configure FRAME pallets to include in runtime. 144 | 145 | impl frame_system::Config for Runtime { 146 | /// The basic call filter to use in dispatchable. 147 | type BaseCallFilter = frame_support::traits::Everything; 148 | /// Block & extrinsics weights: base values and limits. 149 | type BlockWeights = BlockWeights; 150 | /// The maximum length of a block (in bytes). 151 | type BlockLength = BlockLength; 152 | /// The identifier used to distinguish between accounts. 153 | type AccountId = AccountId; 154 | /// The aggregated dispatch type that is available for extrinsics. 155 | type Call = Call; 156 | /// The lookup mechanism to get account ID from whatever is passed in dispatchers. 157 | type Lookup = AccountIdLookup; 158 | /// The index type for storing how many extrinsics an account has signed. 159 | type Index = Index; 160 | /// The index type for blocks. 161 | type BlockNumber = BlockNumber; 162 | /// The type for hashing blocks and tries. 163 | type Hash = Hash; 164 | /// The hashing algorithm used. 165 | type Hashing = BlakeTwo256; 166 | /// The header type. 167 | type Header = generic::Header; 168 | /// The ubiquitous event type. 169 | type Event = Event; 170 | /// The ubiquitous origin type. 171 | type Origin = Origin; 172 | /// Maximum number of block number to block hash mappings to keep (oldest pruned first). 173 | type BlockHashCount = BlockHashCount; 174 | /// The weight of database operations that the runtime can invoke. 175 | type DbWeight = RocksDbWeight; 176 | /// Version of the runtime. 177 | type Version = Version; 178 | /// Converts a module to the index of the module in `construct_runtime!`. 179 | /// 180 | /// This type is being generated by `construct_runtime!`. 181 | type PalletInfo = PalletInfo; 182 | /// What to do if a new account is created. 183 | type OnNewAccount = (); 184 | /// What to do if an account is fully reaped from the system. 185 | type OnKilledAccount = (); 186 | /// The data to be stored in an account. 187 | type AccountData = pallet_balances::AccountData; 188 | /// Weight information for the extrinsics of this pallet. 189 | type SystemWeightInfo = (); 190 | /// This is used as an identifier of the chain. 42 is the generic substrate prefix. 191 | type SS58Prefix = SS58Prefix; 192 | /// The set code logic, just the default since we're not a parachain. 193 | type OnSetCode = (); 194 | } 195 | 196 | impl pallet_randomness_collective_flip::Config for Runtime {} 197 | 198 | parameter_types! { 199 | pub const MaxAuthorities: u32 = 32; 200 | } 201 | 202 | impl pallet_aura::Config for Runtime { 203 | type AuthorityId = AuraId; 204 | type DisabledValidators = (); 205 | type MaxAuthorities = MaxAuthorities; 206 | } 207 | 208 | impl pallet_grandpa::Config for Runtime { 209 | type Event = Event; 210 | type Call = Call; 211 | 212 | type KeyOwnerProofSystem = (); 213 | 214 | type KeyOwnerProof = 215 | >::Proof; 216 | 217 | type KeyOwnerIdentification = >::IdentificationTuple; 221 | 222 | type HandleEquivocation = (); 223 | 224 | type WeightInfo = (); 225 | type MaxAuthorities = MaxAuthorities; 226 | } 227 | 228 | parameter_types! { 229 | pub const MinimumPeriod: u64 = SLOT_DURATION / 2; 230 | } 231 | 232 | impl pallet_timestamp::Config for Runtime { 233 | /// A timestamp: milliseconds since the unix epoch. 234 | type Moment = u64; 235 | type OnTimestampSet = Aura; 236 | type MinimumPeriod = MinimumPeriod; 237 | type WeightInfo = (); 238 | } 239 | 240 | parameter_types! { 241 | pub const ExistentialDeposit: u128 = 500; 242 | pub const MaxLocks: u32 = 50; 243 | } 244 | 245 | impl pallet_balances::Config for Runtime { 246 | type MaxLocks = MaxLocks; 247 | type MaxReserves = (); 248 | type ReserveIdentifier = [u8; 8]; 249 | /// The type for recording an account's balance. 250 | type Balance = Balance; 251 | /// The ubiquitous event type. 252 | type Event = Event; 253 | type DustRemoval = (); 254 | type ExistentialDeposit = ExistentialDeposit; 255 | type AccountStore = System; 256 | type WeightInfo = pallet_balances::weights::SubstrateWeight; 257 | } 258 | 259 | parameter_types! { 260 | pub const TransactionByteFee: Balance = 1; 261 | pub OperationalFeeMultiplier: u8 = 5; 262 | } 263 | 264 | impl pallet_transaction_payment::Config for Runtime { 265 | type OnChargeTransaction = CurrencyAdapter; 266 | type TransactionByteFee = TransactionByteFee; 267 | type OperationalFeeMultiplier = OperationalFeeMultiplier; 268 | type WeightToFee = IdentityFee; 269 | type FeeMultiplierUpdate = (); 270 | } 271 | 272 | impl pallet_sudo::Config for Runtime { 273 | type Event = Event; 274 | type Call = Call; 275 | } 276 | 277 | /// Configure the pallet-template in pallets/template. 278 | impl pallet_template::Config for Runtime { 279 | type Event = Event; 280 | } 281 | 282 | // Create the runtime by composing the FRAME pallets that were previously configured. 283 | construct_runtime!( 284 | pub enum Runtime where 285 | Block = Block, 286 | NodeBlock = opaque::Block, 287 | UncheckedExtrinsic = UncheckedExtrinsic 288 | { 289 | System: frame_system, 290 | RandomnessCollectiveFlip: pallet_randomness_collective_flip, 291 | Timestamp: pallet_timestamp, 292 | Aura: pallet_aura, 293 | Grandpa: pallet_grandpa, 294 | Balances: pallet_balances, 295 | TransactionPayment: pallet_transaction_payment, 296 | Sudo: pallet_sudo, 297 | // Include the custom logic from the pallet-template in the runtime. 298 | TemplateModule: pallet_template, 299 | } 300 | ); 301 | 302 | /// The address format for describing accounts. 303 | pub type Address = sp_runtime::MultiAddress; 304 | /// Block header type as expected by this runtime. 305 | pub type Header = generic::Header; 306 | /// Block type as expected by this runtime. 307 | pub type Block = generic::Block; 308 | /// The SignedExtension to the basic transaction logic. 309 | pub type SignedExtra = ( 310 | frame_system::CheckSpecVersion, 311 | frame_system::CheckTxVersion, 312 | frame_system::CheckGenesis, 313 | frame_system::CheckEra, 314 | frame_system::CheckNonce, 315 | frame_system::CheckWeight, 316 | pallet_transaction_payment::ChargeTransactionPayment, 317 | ); 318 | /// Unchecked extrinsic type as expected by this runtime. 319 | pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; 320 | /// Executive: handles dispatch to the various modules. 321 | pub type Executive = frame_executive::Executive< 322 | Runtime, 323 | Block, 324 | frame_system::ChainContext, 325 | Runtime, 326 | AllPallets, 327 | >; 328 | 329 | impl_runtime_apis! { 330 | impl sp_api::Core for Runtime { 331 | fn version() -> RuntimeVersion { 332 | VERSION 333 | } 334 | 335 | fn execute_block(block: Block) { 336 | Executive::execute_block(block); 337 | } 338 | 339 | fn initialize_block(header: &::Header) { 340 | Executive::initialize_block(header) 341 | } 342 | } 343 | 344 | impl sp_api::Metadata for Runtime { 345 | fn metadata() -> OpaqueMetadata { 346 | OpaqueMetadata::new(Runtime::metadata().into()) 347 | } 348 | } 349 | 350 | impl sp_block_builder::BlockBuilder for Runtime { 351 | fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { 352 | Executive::apply_extrinsic(extrinsic) 353 | } 354 | 355 | fn finalize_block() -> ::Header { 356 | Executive::finalize_block() 357 | } 358 | 359 | fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { 360 | data.create_extrinsics() 361 | } 362 | 363 | fn check_inherents( 364 | block: Block, 365 | data: sp_inherents::InherentData, 366 | ) -> sp_inherents::CheckInherentsResult { 367 | data.check_extrinsics(&block) 368 | } 369 | } 370 | 371 | impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { 372 | fn validate_transaction( 373 | source: TransactionSource, 374 | tx: ::Extrinsic, 375 | block_hash: ::Hash, 376 | ) -> TransactionValidity { 377 | Executive::validate_transaction(source, tx, block_hash) 378 | } 379 | } 380 | 381 | impl sp_offchain::OffchainWorkerApi for Runtime { 382 | fn offchain_worker(header: &::Header) { 383 | Executive::offchain_worker(header) 384 | } 385 | } 386 | 387 | impl sp_consensus_aura::AuraApi for Runtime { 388 | fn slot_duration() -> sp_consensus_aura::SlotDuration { 389 | sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) 390 | } 391 | 392 | fn authorities() -> Vec { 393 | Aura::authorities().into_inner() 394 | } 395 | } 396 | 397 | impl sp_session::SessionKeys for Runtime { 398 | fn generate_session_keys(seed: Option>) -> Vec { 399 | opaque::SessionKeys::generate(seed) 400 | } 401 | 402 | fn decode_session_keys( 403 | encoded: Vec, 404 | ) -> Option, KeyTypeId)>> { 405 | opaque::SessionKeys::decode_into_raw_public_keys(&encoded) 406 | } 407 | } 408 | 409 | impl fg_primitives::GrandpaApi for Runtime { 410 | fn grandpa_authorities() -> GrandpaAuthorityList { 411 | Grandpa::grandpa_authorities() 412 | } 413 | 414 | fn current_set_id() -> fg_primitives::SetId { 415 | Grandpa::current_set_id() 416 | } 417 | 418 | fn submit_report_equivocation_unsigned_extrinsic( 419 | _equivocation_proof: fg_primitives::EquivocationProof< 420 | ::Hash, 421 | NumberFor, 422 | >, 423 | _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, 424 | ) -> Option<()> { 425 | None 426 | } 427 | 428 | fn generate_key_ownership_proof( 429 | _set_id: fg_primitives::SetId, 430 | _authority_id: GrandpaId, 431 | ) -> Option { 432 | // NOTE: this is the only implementation possible since we've 433 | // defined our key owner proof type as a bottom type (i.e. a type 434 | // with no values). 435 | None 436 | } 437 | } 438 | 439 | impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { 440 | fn account_nonce(account: AccountId) -> Index { 441 | System::account_nonce(account) 442 | } 443 | } 444 | 445 | impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { 446 | fn query_info( 447 | uxt: ::Extrinsic, 448 | len: u32, 449 | ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { 450 | TransactionPayment::query_info(uxt, len) 451 | } 452 | fn query_fee_details( 453 | uxt: ::Extrinsic, 454 | len: u32, 455 | ) -> pallet_transaction_payment::FeeDetails { 456 | TransactionPayment::query_fee_details(uxt, len) 457 | } 458 | } 459 | 460 | #[cfg(feature = "runtime-benchmarks")] 461 | impl frame_benchmarking::Benchmark for Runtime { 462 | fn benchmark_metadata(extra: bool) -> ( 463 | Vec, 464 | Vec, 465 | ) { 466 | use frame_benchmarking::{list_benchmark, baseline, Benchmarking, BenchmarkList}; 467 | use frame_support::traits::StorageInfoTrait; 468 | use frame_system_benchmarking::Pallet as SystemBench; 469 | use baseline::Pallet as BaselineBench; 470 | 471 | let mut list = Vec::::new(); 472 | 473 | list_benchmark!(list, extra, frame_benchmarking, BaselineBench::); 474 | list_benchmark!(list, extra, frame_system, SystemBench::); 475 | list_benchmark!(list, extra, pallet_balances, Balances); 476 | list_benchmark!(list, extra, pallet_timestamp, Timestamp); 477 | list_benchmark!(list, extra, pallet_template, TemplateModule); 478 | 479 | let storage_info = AllPalletsWithSystem::storage_info(); 480 | 481 | return (list, storage_info) 482 | } 483 | 484 | fn dispatch_benchmark( 485 | config: frame_benchmarking::BenchmarkConfig 486 | ) -> Result, sp_runtime::RuntimeString> { 487 | use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; 488 | 489 | use frame_system_benchmarking::Pallet as SystemBench; 490 | use baseline::Pallet as BaselineBench; 491 | 492 | impl frame_system_benchmarking::Config for Runtime {} 493 | impl baseline::Config for Runtime {} 494 | 495 | let whitelist: Vec = vec![ 496 | // Block Number 497 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), 498 | // Total Issuance 499 | hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(), 500 | // Execution Phase 501 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), 502 | // Event Count 503 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), 504 | // System Events 505 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), 506 | ]; 507 | 508 | let mut batches = Vec::::new(); 509 | let params = (&config, &whitelist); 510 | 511 | add_benchmark!(params, batches, frame_benchmarking, BaselineBench::); 512 | add_benchmark!(params, batches, frame_system, SystemBench::); 513 | add_benchmark!(params, batches, pallet_balances, Balances); 514 | add_benchmark!(params, batches, pallet_timestamp, Timestamp); 515 | add_benchmark!(params, batches, pallet_template, TemplateModule); 516 | 517 | Ok(batches) 518 | } 519 | } 520 | } 521 | --------------------------------------------------------------------------------