├── .gitignore ├── pallets └── template │ ├── README.md │ ├── src │ ├── benchmarking.rs │ ├── tests.rs │ ├── mock.rs │ ├── weights.rs │ └── lib.rs │ └── Cargo.toml ├── node ├── build.rs ├── src │ ├── main.rs │ ├── chain_spec.rs │ ├── cli.rs │ ├── rpc.rs │ ├── benchmarking.rs │ ├── command.rs │ └── service.rs └── Cargo.toml ├── env-setup ├── rust-toolchain.toml ├── README.md ├── flake.nix └── flake.lock ├── .github ├── actions │ ├── macos-dependencies │ │ └── action.yml │ ├── ubuntu-dependencies │ │ └── action.yml │ └── free-disk-space │ │ └── action.yml └── workflows │ ├── pr-reminder.yml │ ├── release.yml │ └── ci.yml ├── runtime ├── build.rs ├── src │ ├── benchmarks.rs │ ├── genesis_config_presets.rs │ ├── configs │ │ └── mod.rs │ ├── lib.rs │ └── apis.rs └── Cargo.toml ├── Dockerfile ├── LICENSE ├── Cargo.toml ├── docs └── rust-setup.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /pallets/template/README.md: -------------------------------------------------------------------------------- 1 | License: MIT-0 2 | -------------------------------------------------------------------------------- /node/build.rs: -------------------------------------------------------------------------------- 1 | use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; 2 | 3 | fn main() { 4 | generate_cargo_keys(); 5 | 6 | rerun_if_git_head_changed(); 7 | } 8 | -------------------------------------------------------------------------------- /node/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Substrate Node Template CLI library. 2 | #![warn(missing_docs)] 3 | 4 | mod benchmarking; 5 | mod chain_spec; 6 | mod cli; 7 | mod command; 8 | mod rpc; 9 | mod service; 10 | 11 | fn main() -> sc_cli::Result<()> { 12 | command::run() 13 | } 14 | -------------------------------------------------------------------------------- /env-setup/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "stable" 3 | components = [ 4 | "cargo", 5 | "clippy", 6 | "rust-analyzer", 7 | "rust-src", 8 | "rust-std", 9 | "rustc", 10 | "rustc-dev", 11 | "rustfmt", 12 | ] 13 | targets = ["wasm32-unknown-unknown"] 14 | profile = "minimal" 15 | -------------------------------------------------------------------------------- /env-setup/README.md: -------------------------------------------------------------------------------- 1 | # Env setup 2 | 3 | Special files for setting up an environment to work with the template: 4 | 5 | - `rust-toolchain.toml` when working with `rustup`. 6 | - `flake.nix` when working with `nix`. 7 | 8 | These files will be copied by the installer script to the main directory. They are 9 | put into this special directory to not interfere with the normal CI. 10 | -------------------------------------------------------------------------------- /.github/actions/macos-dependencies/action.yml: -------------------------------------------------------------------------------- 1 | name: Install macOS dependencies 2 | description: Installs dependencies required to compile the template on macOS 3 | 4 | runs: 5 | using: "composite" 6 | steps: 7 | - run: | 8 | curl https://sh.rustup.rs -sSf -y | sh 9 | brew install protobuf 10 | rustup target add wasm32-unknown-unknown --toolchain stable-aarch64-apple-darwin 11 | rustup component add rust-src --toolchain stable-aarch64-apple-darwin 12 | shell: sh 13 | -------------------------------------------------------------------------------- /runtime/build.rs: -------------------------------------------------------------------------------- 1 | #[cfg(all(feature = "std", feature = "metadata-hash"))] 2 | fn main() { 3 | substrate_wasm_builder::WasmBuilder::init_with_defaults() 4 | .enable_metadata_hash("UNIT", 12) 5 | .build(); 6 | } 7 | 8 | #[cfg(all(feature = "std", not(feature = "metadata-hash")))] 9 | fn main() { 10 | substrate_wasm_builder::WasmBuilder::build_using_defaults(); 11 | } 12 | 13 | /// The wasm builder is deactivated when compiling 14 | /// this crate for wasm to speed up the compilation. 15 | #[cfg(not(feature = "std"))] 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /.github/actions/ubuntu-dependencies/action.yml: -------------------------------------------------------------------------------- 1 | name: Install Ubuntu dependencies 2 | description: Installs dependencies required to compile the template in Ubuntu 3 | 4 | runs: 5 | using: "composite" 6 | steps: 7 | - name: Rust compilation prerequisites (Ubuntu) 8 | if: contains(matrix.os, 'ubuntu') 9 | run: | 10 | sudo apt update 11 | sudo apt install -y \ 12 | protobuf-compiler 13 | rustup target add wasm32-unknown-unknown 14 | rustup component add rustfmt clippy rust-src 15 | shell: bash 16 | -------------------------------------------------------------------------------- /env-setup/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 4 | flake-utils.url = "github:numtide/flake-utils"; 5 | }; 6 | 7 | outputs = { self, nixpkgs, flake-utils, ... }: flake-utils.lib.eachDefaultSystem (system: 8 | let 9 | pkgs = import nixpkgs { inherit system; }; 10 | in 11 | { 12 | devShells.default = pkgs.mkShell { 13 | packages = with pkgs; [ 14 | rustup 15 | clang 16 | protobuf 17 | ]; 18 | 19 | LIBCLANG_PATH = "${pkgs.libclang.lib}/lib"; 20 | }; 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /.github/actions/free-disk-space/action.yml: -------------------------------------------------------------------------------- 1 | name: Free disk space 2 | description: We've run into out-of-disk error when compiling Rust projects, so we free up some space this way. 3 | 4 | runs: 5 | using: "composite" 6 | steps: 7 | - name: Free Disk Space 8 | uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # 1.3.1 9 | with: 10 | android: true # This alone is a 12 GB save. 11 | # We disable the rest because it caused some problems. (they're enabled by default) 12 | # The Android removal is enough. 13 | dotnet: false 14 | haskell: false 15 | large-packages: false 16 | swap-storage: false 17 | -------------------------------------------------------------------------------- /.github/workflows/pr-reminder.yml: -------------------------------------------------------------------------------- 1 | name: PR Reminder 2 | 3 | permissions: 4 | pull-requests: write 5 | 6 | on: 7 | pull_request: 8 | types: 9 | - opened 10 | 11 | jobs: 12 | pr-reminder: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Comment a reminder on a new PR 16 | uses: actions/github-script@v6 17 | with: 18 | script: | 19 | github.rest.issues.createComment({ 20 | issue_number: context.issue.number, 21 | owner: context.repo.owner, 22 | repo: context.repo.repo, 23 | body: 'Hello, this is an automatic reminder that any code changes should be made to [the source](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain).' 24 | }) 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/paritytech/ci-unified:latest as builder 2 | 3 | WORKDIR /polkadot 4 | COPY . /polkadot 5 | 6 | RUN cargo fetch 7 | RUN cargo build --locked --release 8 | 9 | FROM docker.io/parity/base-bin:latest 10 | 11 | COPY --from=builder /polkadot/target/release/solochain-template-node /usr/local/bin 12 | 13 | USER root 14 | RUN useradd -m -u 1001 -U -s /bin/sh -d /polkadot polkadot && \ 15 | mkdir -p /data /polkadot/.local/share && \ 16 | chown -R polkadot:polkadot /data && \ 17 | ln -s /data /polkadot/.local/share/polkadot && \ 18 | # unclutter and minimize the attack surface 19 | rm -rf /usr/bin /usr/sbin && \ 20 | # check if executable works in this container 21 | /usr/local/bin/solochain-template-node --version 22 | 23 | USER polkadot 24 | 25 | EXPOSE 30333 9933 9944 9615 26 | VOLUME ["/data"] 27 | 28 | ENTRYPOINT ["/usr/local/bin/solochain-template-node"] 29 | -------------------------------------------------------------------------------- /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::v2::*; 8 | use frame_system::RawOrigin; 9 | 10 | #[benchmarks] 11 | mod benchmarks { 12 | use super::*; 13 | 14 | #[benchmark] 15 | fn do_something() { 16 | let value = 100u32; 17 | let caller: T::AccountId = whitelisted_caller(); 18 | #[extrinsic_call] 19 | do_something(RawOrigin::Signed(caller), value); 20 | 21 | assert_eq!(Something::::get(), Some(value)); 22 | } 23 | 24 | #[benchmark] 25 | fn cause_error() { 26 | Something::::put(100u32); 27 | let caller: T::AccountId = whitelisted_caller(); 28 | #[extrinsic_call] 29 | cause_error(RawOrigin::Signed(caller)); 30 | 31 | assert_eq!(Something::::get(), Some(101u32)); 32 | } 33 | 34 | impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test); 35 | } 36 | -------------------------------------------------------------------------------- /pallets/template/src/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::{mock::*, Error, Event, Something}; 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 | // Go past genesis block so events get deposited 8 | System::set_block_number(1); 9 | // Dispatch a signed extrinsic. 10 | assert_ok!(Template::do_something(RuntimeOrigin::signed(1), 42)); 11 | // Read pallet storage and assert an expected result. 12 | assert_eq!(Something::::get(), Some(42)); 13 | // Assert that the correct event was deposited 14 | System::assert_last_event(Event::SomethingStored { something: 42, who: 1 }.into()); 15 | }); 16 | } 17 | 18 | #[test] 19 | fn correct_error_for_none_value() { 20 | new_test_ext().execute_with(|| { 21 | // Ensure the expected error is thrown when no value is present. 22 | assert_noop!(Template::cause_error(RuntimeOrigin::signed(1)), Error::::NoneValue); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /node/src/chain_spec.rs: -------------------------------------------------------------------------------- 1 | use sc_service::ChainType; 2 | use solochain_template_runtime::WASM_BINARY; 3 | 4 | /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. 5 | pub type ChainSpec = sc_service::GenericChainSpec; 6 | 7 | pub fn development_chain_spec() -> Result { 8 | Ok(ChainSpec::builder( 9 | WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?, 10 | None, 11 | ) 12 | .with_name("Development") 13 | .with_id("dev") 14 | .with_chain_type(ChainType::Development) 15 | .with_genesis_config_preset_name(sp_genesis_builder::DEV_RUNTIME_PRESET) 16 | .build()) 17 | } 18 | 19 | pub fn local_chain_spec() -> Result { 20 | Ok(ChainSpec::builder( 21 | WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?, 22 | None, 23 | ) 24 | .with_name("Local Testnet") 25 | .with_id("local_testnet") 26 | .with_chain_type(ChainType::Local) 27 | .with_genesis_config_preset_name(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET) 28 | .build()) 29 | } 30 | -------------------------------------------------------------------------------- /env-setup/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "locked": { 5 | "lastModified": 1678901627, 6 | "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", 7 | "owner": "numtide", 8 | "repo": "flake-utils", 9 | "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "numtide", 14 | "repo": "flake-utils", 15 | "type": "github" 16 | } 17 | }, 18 | "nixpkgs": { 19 | "locked": { 20 | "lastModified": 1679262748, 21 | "narHash": "sha256-DQCrrAFrkxijC6haUzOC5ZoFqpcv/tg2WxnyW3np1Cc=", 22 | "owner": "NixOS", 23 | "repo": "nixpkgs", 24 | "rev": "60c1d71f2ba4c80178ec84523c2ca0801522e0a6", 25 | "type": "github" 26 | }, 27 | "original": { 28 | "owner": "NixOS", 29 | "ref": "nixos-unstable", 30 | "repo": "nixpkgs", 31 | "type": "github" 32 | } 33 | }, 34 | "root": { 35 | "inputs": { 36 | "flake-utils": "flake-utils", 37 | "nixpkgs": "nixpkgs" 38 | } 39 | } 40 | }, 41 | "root": "root", 42 | "version": 7 43 | } 44 | -------------------------------------------------------------------------------- /node/src/cli.rs: -------------------------------------------------------------------------------- 1 | use sc_cli::RunCmd; 2 | 3 | #[derive(Debug, clap::Parser)] 4 | pub struct Cli { 5 | #[command(subcommand)] 6 | pub subcommand: Option, 7 | 8 | #[clap(flatten)] 9 | pub run: RunCmd, 10 | } 11 | 12 | #[derive(Debug, clap::Subcommand)] 13 | #[allow(clippy::large_enum_variant)] 14 | pub enum Subcommand { 15 | /// Key management cli utilities 16 | #[command(subcommand)] 17 | Key(sc_cli::KeySubcommand), 18 | 19 | /// Build a chain specification. 20 | BuildSpec(sc_cli::BuildSpecCmd), 21 | 22 | /// Validate blocks. 23 | CheckBlock(sc_cli::CheckBlockCmd), 24 | 25 | /// Export blocks. 26 | ExportBlocks(sc_cli::ExportBlocksCmd), 27 | 28 | /// Export the state of a given block into a chain spec. 29 | ExportState(sc_cli::ExportStateCmd), 30 | 31 | /// Import blocks. 32 | ImportBlocks(sc_cli::ImportBlocksCmd), 33 | 34 | /// Remove the whole chain. 35 | PurgeChain(sc_cli::PurgeChainCmd), 36 | 37 | /// Revert the chain to a previous state. 38 | Revert(sc_cli::RevertCmd), 39 | 40 | /// Sub-commands concerned with benchmarking. 41 | #[command(subcommand)] 42 | Benchmark(frame_benchmarking_cli::BenchmarkCmd), 43 | 44 | /// Db meta columns information. 45 | ChainInfo(sc_cli::ChainInfoCmd), 46 | } 47 | -------------------------------------------------------------------------------- /pallets/template/src/mock.rs: -------------------------------------------------------------------------------- 1 | use crate as pallet_template; 2 | use frame_support::derive_impl; 3 | use sp_runtime::BuildStorage; 4 | 5 | type Block = frame_system::mocking::MockBlock; 6 | 7 | #[frame_support::runtime] 8 | mod runtime { 9 | // The main runtime 10 | #[runtime::runtime] 11 | // Runtime Types to be generated 12 | #[runtime::derive( 13 | RuntimeCall, 14 | RuntimeEvent, 15 | RuntimeError, 16 | RuntimeOrigin, 17 | RuntimeFreezeReason, 18 | RuntimeHoldReason, 19 | RuntimeSlashReason, 20 | RuntimeLockId, 21 | RuntimeTask, 22 | RuntimeViewFunction 23 | )] 24 | pub struct Test; 25 | 26 | #[runtime::pallet_index(0)] 27 | pub type System = frame_system::Pallet; 28 | 29 | #[runtime::pallet_index(1)] 30 | pub type Template = pallet_template::Pallet; 31 | } 32 | 33 | #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] 34 | impl frame_system::Config for Test { 35 | type Block = Block; 36 | } 37 | 38 | impl pallet_template::Config for Test { 39 | type RuntimeEvent = RuntimeEvent; 40 | type WeightInfo = (); 41 | } 42 | 43 | // Build genesis storage according to the mock runtime. 44 | pub fn new_test_ext() -> sp_io::TestExternalities { 45 | frame_system::GenesisConfig::::default().build_storage().unwrap().into() 46 | } 47 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /pallets/template/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pallet-template" 3 | description = "FRAME pallet template for defining custom runtime logic." 4 | version = "0.1.0" 5 | license = "Unlicense" 6 | authors.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | edition.workspace = true 10 | publish = false 11 | 12 | [package.metadata.docs.rs] 13 | targets = ["x86_64-unknown-linux-gnu"] 14 | 15 | [dependencies] 16 | codec = { features = ["derive"], workspace = true } 17 | frame-benchmarking = { optional = true, workspace = true } 18 | frame-support.workspace = true 19 | frame-system.workspace = true 20 | scale-info = { features = ["derive"], workspace = true } 21 | 22 | [dev-dependencies] 23 | sp-core = { default-features = true, workspace = true } 24 | sp-io = { default-features = true, workspace = true } 25 | sp-runtime = { default-features = true, workspace = true } 26 | 27 | [features] 28 | default = ["std"] 29 | std = [ 30 | "codec/std", 31 | "frame-benchmarking?/std", 32 | "frame-support/std", 33 | "frame-system/std", 34 | "scale-info/std", 35 | ] 36 | runtime-benchmarks = [ 37 | "frame-benchmarking/runtime-benchmarks", 38 | "frame-support/runtime-benchmarks", 39 | "frame-system/runtime-benchmarks", 40 | "sp-runtime/runtime-benchmarks", 41 | ] 42 | try-runtime = [ 43 | "frame-support/try-runtime", 44 | "frame-system/try-runtime", 45 | "sp-runtime/try-runtime", 46 | ] 47 | -------------------------------------------------------------------------------- /runtime/src/benchmarks.rs: -------------------------------------------------------------------------------- 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 | 26 | frame_benchmarking::define_benchmarks!( 27 | [frame_benchmarking, BaselineBench::] 28 | [frame_system, SystemBench::] 29 | [frame_system_extensions, SystemExtensionsBench::] 30 | [pallet_balances, Balances] 31 | [pallet_timestamp, Timestamp] 32 | [pallet_sudo, Sudo] 33 | [pallet_template, Template] 34 | ); 35 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | permissions: 4 | contents: write 5 | packages: write 6 | 7 | on: 8 | release: 9 | types: [released] 10 | 11 | jobs: 12 | release-docker: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Set up Docker Buildx 16 | uses: docker/setup-buildx-action@v3 17 | 18 | - name: Login to GitHub Container Registry 19 | uses: docker/login-action@v3 20 | with: 21 | registry: ghcr.io 22 | username: ${{ github.actor }} 23 | password: ${{ secrets.GITHUB_TOKEN }} 24 | 25 | # We've run into out-of-disk error when compiling Polkadot in the next step, so we free up some space this way. 26 | - name: Free Disk Space (Ubuntu) 27 | uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # 1.3.1 28 | with: 29 | android: true # This alone is a 12 GB save. 30 | # We disable the rest because it caused some problems. (they're enabled by default) 31 | # The Android removal is enough. 32 | dotnet: false 33 | haskell: false 34 | large-packages: false 35 | swap-storage: false 36 | 37 | - name: Build and push 38 | uses: docker/build-push-action@v6 39 | with: 40 | push: true 41 | tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }} 42 | 43 | release-binaries: 44 | runs-on: ubuntu-latest 45 | steps: 46 | - uses: actions/checkout@v4 47 | 48 | - name: Rust compilation prerequisites 49 | run: | 50 | sudo apt update 51 | sudo apt install -y \ 52 | protobuf-compiler 53 | rustup target add wasm32-unknown-unknown 54 | rustup component add rust-src 55 | 56 | - name: Build the template 57 | run: cargo build --locked --release 58 | timeout-minutes: 90 59 | 60 | - name: Upload the binaries 61 | uses: softprops/action-gh-release@v2 62 | with: 63 | files: | 64 | target/release/solochain-template-node 65 | target/release/wbuild/solochain-template-runtime/solochain_template_runtime.compact.compressed.wasm 66 | -------------------------------------------------------------------------------- /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 jsonrpsee::RpcModule; 11 | use sc_transaction_pool_api::TransactionPool; 12 | use solochain_template_runtime::{opaque::Block, AccountId, Balance, Nonce}; 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 | } 24 | 25 | /// Instantiate all full RPC extensions. 26 | pub fn create_full( 27 | deps: FullDeps, 28 | ) -> Result, Box> 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, TransactionPaymentApiServer}; 39 | use substrate_frame_rpc_system::{System, SystemApiServer}; 40 | 41 | let mut module = RpcModule::new(()); 42 | let FullDeps { client, pool } = deps; 43 | 44 | module.merge(System::new(client.clone(), pool).into_rpc())?; 45 | module.merge(TransactionPayment::new(client).into_rpc())?; 46 | 47 | // Extend this RPC with a custom API by using the following syntax. 48 | // `YourRpcStruct` should have a reference to a client, which is needed 49 | // to call into the runtime. 50 | // `module.merge(YourRpcTrait::into_rpc(YourRpcStruct::new(ReferenceToClient, ...)))?;` 51 | 52 | // You probably want to enable the `rpc v2 chainSpec` API as well 53 | // 54 | // let chain_name = chain_spec.name().to_string(); 55 | // let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); 56 | // let properties = chain_spec.properties(); 57 | // module.merge(ChainSpec::new(chain_name, genesis_hash, properties).into_rpc())?; 58 | 59 | Ok(module) 60 | } 61 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | - master 9 | 10 | concurrency: 11 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 12 | cancel-in-progress: true 13 | 14 | jobs: 15 | build: 16 | runs-on: ${{ matrix.os }} 17 | strategy: 18 | matrix: 19 | os: [ubuntu-latest, macos-latest] 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - if: contains(matrix.os, 'ubuntu') 24 | uses: ./.github/actions/free-disk-space 25 | - if: contains(matrix.os, 'ubuntu') 26 | uses: ./.github/actions/ubuntu-dependencies 27 | - if: contains(matrix.os, 'macos') 28 | uses: ./.github/actions/macos-dependencies 29 | 30 | - name: Build the template 31 | run: cargo build 32 | timeout-minutes: 90 33 | 34 | - name: Run clippy 35 | run: | 36 | SKIP_WASM_BUILD=1 cargo clippy --all-targets --locked --workspace --quiet 37 | SKIP_WASM_BUILD=1 cargo clippy --all-targets --all-features --locked --workspace --quiet 38 | timeout-minutes: 30 39 | 40 | - name: Run the tests 41 | run: SKIP_WASM_BUILD=1 cargo test 42 | timeout-minutes: 15 43 | 44 | - name: Build the docs 45 | run: SKIP_WASM_BUILD=1 cargo doc --workspace --no-deps 46 | timeout-minutes: 15 47 | 48 | run-node: 49 | runs-on: ${{ matrix.os }} 50 | strategy: 51 | matrix: 52 | os: [ubuntu-latest, macos-latest] 53 | steps: 54 | - uses: actions/checkout@v4 55 | 56 | - if: contains(matrix.os, 'ubuntu') 57 | uses: ./.github/actions/free-disk-space 58 | - if: contains(matrix.os, 'ubuntu') 59 | uses: ./.github/actions/ubuntu-dependencies 60 | - if: contains(matrix.os, 'macos') 61 | uses: ./.github/actions/macos-dependencies 62 | 63 | - name: Build the node individually in release mode 64 | run: cargo build --package solochain-template-node --release 65 | timeout-minutes: 90 66 | 67 | - name: Make sure the node is producing blocks 68 | run: | 69 | ./target/release/solochain-template-node --dev 2>&1 | tee out.txt & 70 | until curl -s '127.0.0.1:9944'; do sleep 5; done 71 | until cat out.txt | grep -s "Imported #2"; do sleep 5; done 72 | shell: bash 73 | timeout-minutes: 5 74 | 75 | build-docker: 76 | runs-on: ubuntu-latest 77 | steps: 78 | - uses: actions/checkout@v4 79 | 80 | - uses: ./.github/actions/free-disk-space 81 | 82 | - name: Build the Dockerfile 83 | run: docker build . -t polkadot-sdk-solochain-template 84 | timeout-minutes: 90 85 | -------------------------------------------------------------------------------- /pallets/template/src/weights.rs: -------------------------------------------------------------------------------- 1 | 2 | //! Autogenerated weights for pallet_template 3 | //! 4 | //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev 5 | //! DATE: 2023-04-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` 6 | //! WORST CASE MAP SIZE: `1000000` 7 | //! HOSTNAME: `Alexs-MacBook-Pro-2.local`, CPU: `` 8 | //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 9 | 10 | // Executed Command: 11 | // ../../target/release/node-template 12 | // benchmark 13 | // pallet 14 | // --chain 15 | // dev 16 | // --pallet 17 | // pallet_template 18 | // --extrinsic 19 | // * 20 | // --steps=50 21 | // --repeat=20 22 | // --wasm-execution=compiled 23 | // --output 24 | // pallets/template/src/weights.rs 25 | // --template 26 | // ../../.maintain/frame-weight-template.hbs 27 | 28 | #![cfg_attr(rustfmt, rustfmt_skip)] 29 | #![allow(unused_parens)] 30 | #![allow(unused_imports)] 31 | 32 | use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; 33 | use core::marker::PhantomData; 34 | 35 | /// Weight functions needed for pallet_template. 36 | pub trait WeightInfo { 37 | fn do_something() -> Weight; 38 | fn cause_error() -> Weight; 39 | } 40 | 41 | /// Weights for pallet_template using the Substrate node and recommended hardware. 42 | pub struct SubstrateWeight(PhantomData); 43 | impl WeightInfo for SubstrateWeight { 44 | /// Storage: Template Something (r:0 w:1) 45 | /// Proof: Template Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) 46 | fn do_something() -> Weight { 47 | // Proof Size summary in bytes: 48 | // Measured: `0` 49 | // Estimated: `0` 50 | // Minimum execution time: 8_000_000 picoseconds. 51 | Weight::from_parts(9_000_000, 0) 52 | .saturating_add(T::DbWeight::get().writes(1_u64)) 53 | } 54 | /// Storage: Template Something (r:1 w:1) 55 | /// Proof: Template Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) 56 | fn cause_error() -> Weight { 57 | // Proof Size summary in bytes: 58 | // Measured: `32` 59 | // Estimated: `1489` 60 | // Minimum execution time: 6_000_000 picoseconds. 61 | Weight::from_parts(6_000_000, 1489) 62 | .saturating_add(T::DbWeight::get().reads(1_u64)) 63 | .saturating_add(T::DbWeight::get().writes(1_u64)) 64 | } 65 | } 66 | 67 | // For backwards compatibility and tests 68 | impl WeightInfo for () { 69 | /// Storage: Template Something (r:0 w:1) 70 | /// Proof: Template Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) 71 | fn do_something() -> Weight { 72 | // Proof Size summary in bytes: 73 | // Measured: `0` 74 | // Estimated: `0` 75 | // Minimum execution time: 8_000_000 picoseconds. 76 | Weight::from_parts(9_000_000, 0) 77 | .saturating_add(RocksDbWeight::get().writes(1_u64)) 78 | } 79 | /// Storage: Template Something (r:1 w:1) 80 | /// Proof: Template Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) 81 | fn cause_error() -> Weight { 82 | // Proof Size summary in bytes: 83 | // Measured: `32` 84 | // Estimated: `1489` 85 | // Minimum execution time: 6_000_000 picoseconds. 86 | Weight::from_parts(6_000_000, 1489) 87 | .saturating_add(RocksDbWeight::get().reads(1_u64)) 88 | .saturating_add(RocksDbWeight::get().writes(1_u64)) 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /runtime/src/genesis_config_presets.rs: -------------------------------------------------------------------------------- 1 | // This file is part of Substrate. 2 | 3 | // Copyright (C) Parity Technologies (UK) Ltd. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | use crate::{AccountId, BalancesConfig, RuntimeGenesisConfig, SudoConfig}; 19 | use alloc::{vec, vec::Vec}; 20 | use frame_support::build_struct_json_patch; 21 | use serde_json::Value; 22 | use sp_consensus_aura::sr25519::AuthorityId as AuraId; 23 | use sp_consensus_grandpa::AuthorityId as GrandpaId; 24 | use sp_genesis_builder::{self, PresetId}; 25 | use sp_keyring::Sr25519Keyring; 26 | 27 | // Returns the genesis config presets populated with given parameters. 28 | fn testnet_genesis( 29 | initial_authorities: Vec<(AuraId, GrandpaId)>, 30 | endowed_accounts: Vec, 31 | root: AccountId, 32 | ) -> Value { 33 | build_struct_json_patch!(RuntimeGenesisConfig { 34 | balances: BalancesConfig { 35 | balances: endowed_accounts 36 | .iter() 37 | .cloned() 38 | .map(|k| (k, 1u128 << 60)) 39 | .collect::>(), 40 | }, 41 | aura: pallet_aura::GenesisConfig { 42 | authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect::>(), 43 | }, 44 | grandpa: pallet_grandpa::GenesisConfig { 45 | authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect::>(), 46 | }, 47 | sudo: SudoConfig { key: Some(root) }, 48 | }) 49 | } 50 | 51 | /// Return the development genesis config. 52 | pub fn development_config_genesis() -> Value { 53 | testnet_genesis( 54 | vec![( 55 | sp_keyring::Sr25519Keyring::Alice.public().into(), 56 | sp_keyring::Ed25519Keyring::Alice.public().into(), 57 | )], 58 | vec![ 59 | Sr25519Keyring::Alice.to_account_id(), 60 | Sr25519Keyring::Bob.to_account_id(), 61 | Sr25519Keyring::AliceStash.to_account_id(), 62 | Sr25519Keyring::BobStash.to_account_id(), 63 | ], 64 | sp_keyring::Sr25519Keyring::Alice.to_account_id(), 65 | ) 66 | } 67 | 68 | /// Return the local genesis config preset. 69 | pub fn local_config_genesis() -> Value { 70 | testnet_genesis( 71 | vec![ 72 | ( 73 | sp_keyring::Sr25519Keyring::Alice.public().into(), 74 | sp_keyring::Ed25519Keyring::Alice.public().into(), 75 | ), 76 | ( 77 | sp_keyring::Sr25519Keyring::Bob.public().into(), 78 | sp_keyring::Ed25519Keyring::Bob.public().into(), 79 | ), 80 | ], 81 | Sr25519Keyring::iter() 82 | .filter(|v| v != &Sr25519Keyring::One && v != &Sr25519Keyring::Two) 83 | .map(|v| v.to_account_id()) 84 | .collect::>(), 85 | Sr25519Keyring::Alice.to_account_id(), 86 | ) 87 | } 88 | 89 | /// Provides the JSON representation of predefined genesis config for given `id`. 90 | pub fn get_preset(id: &PresetId) -> Option> { 91 | let patch = match id.as_ref() { 92 | sp_genesis_builder::DEV_RUNTIME_PRESET => development_config_genesis(), 93 | sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET => local_config_genesis(), 94 | _ => return None, 95 | }; 96 | Some( 97 | serde_json::to_string(&patch) 98 | .expect("serialization to json is expected to work. qed.") 99 | .into_bytes(), 100 | ) 101 | } 102 | 103 | /// List of supported presets. 104 | pub fn preset_names() -> Vec { 105 | vec![ 106 | PresetId::from(sp_genesis_builder::DEV_RUNTIME_PRESET), 107 | PresetId::from(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET), 108 | ] 109 | } 110 | -------------------------------------------------------------------------------- /node/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "solochain-template-node" 3 | description = "A solochain node template built with Substrate, part of Polkadot Sdk." 4 | version = "0.1.0" 5 | license = "Unlicense" 6 | authors.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | edition.workspace = true 10 | publish = false 11 | 12 | build = "build.rs" 13 | 14 | [package.metadata.docs.rs] 15 | targets = ["x86_64-unknown-linux-gnu"] 16 | 17 | [dependencies] 18 | clap = { features = ["derive"], workspace = true } 19 | frame-benchmarking-cli.default-features = true 20 | frame-benchmarking-cli.workspace = true 21 | frame-metadata-hash-extension.default-features = true 22 | frame-metadata-hash-extension.workspace = true 23 | frame-system.default-features = true 24 | frame-system.workspace = true 25 | futures = { features = ["thread-pool"], workspace = true } 26 | jsonrpsee = { features = ["server"], workspace = true } 27 | pallet-transaction-payment-rpc.default-features = true 28 | pallet-transaction-payment-rpc.workspace = true 29 | pallet-transaction-payment.default-features = true 30 | pallet-transaction-payment.workspace = true 31 | sc-basic-authorship.default-features = true 32 | sc-basic-authorship.workspace = true 33 | sc-cli.default-features = true 34 | sc-cli.workspace = true 35 | sc-client-api.default-features = true 36 | sc-client-api.workspace = true 37 | sc-consensus-aura.default-features = true 38 | sc-consensus-aura.workspace = true 39 | sc-consensus-grandpa.default-features = true 40 | sc-consensus-grandpa.workspace = true 41 | sc-consensus.default-features = true 42 | sc-consensus.workspace = true 43 | sc-executor.default-features = true 44 | sc-executor.workspace = true 45 | sc-network.default-features = true 46 | sc-network.workspace = true 47 | sc-offchain.default-features = true 48 | sc-offchain.workspace = true 49 | sc-service.default-features = true 50 | sc-service.workspace = true 51 | sc-telemetry.default-features = true 52 | sc-telemetry.workspace = true 53 | sc-transaction-pool-api.default-features = true 54 | sc-transaction-pool-api.workspace = true 55 | sc-transaction-pool.default-features = true 56 | sc-transaction-pool.workspace = true 57 | solochain-template-runtime.workspace = true 58 | sp-api.default-features = true 59 | sp-api.workspace = true 60 | sp-block-builder.default-features = true 61 | sp-block-builder.workspace = true 62 | sp-blockchain.default-features = true 63 | sp-blockchain.workspace = true 64 | sp-consensus-aura.default-features = true 65 | sp-consensus-aura.workspace = true 66 | sp-core.default-features = true 67 | sp-core.workspace = true 68 | sp-genesis-builder.default-features = true 69 | sp-genesis-builder.workspace = true 70 | sp-inherents.default-features = true 71 | sp-inherents.workspace = true 72 | sp-io.default-features = true 73 | sp-io.workspace = true 74 | sp-keyring.default-features = true 75 | sp-keyring.workspace = true 76 | sp-runtime.default-features = true 77 | sp-runtime.workspace = true 78 | sp-timestamp.default-features = true 79 | sp-timestamp.workspace = true 80 | substrate-frame-rpc-system.default-features = true 81 | substrate-frame-rpc-system.workspace = true 82 | 83 | [build-dependencies] 84 | substrate-build-script-utils.default-features = true 85 | substrate-build-script-utils.workspace = true 86 | 87 | [features] 88 | default = ["std"] 89 | std = ["solochain-template-runtime/std"] 90 | # Dependencies that are only required if runtime benchmarking should be build. 91 | runtime-benchmarks = [ 92 | "frame-benchmarking-cli/runtime-benchmarks", 93 | "frame-system/runtime-benchmarks", 94 | "pallet-transaction-payment/runtime-benchmarks", 95 | "sc-service/runtime-benchmarks", 96 | "solochain-template-runtime/runtime-benchmarks", 97 | "sp-runtime/runtime-benchmarks", 98 | ] 99 | # Enable features that allow the runtime to be tried and debugged. Name might be subject to change 100 | # in the near future. 101 | try-runtime = [ 102 | "frame-system/try-runtime", 103 | "pallet-transaction-payment/try-runtime", 104 | "solochain-template-runtime/try-runtime", 105 | "sp-runtime/try-runtime", 106 | ] 107 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace.package] 2 | license = "MIT-0" 3 | authors = ["Parity Technologies "] 4 | homepage = "https://paritytech.github.io/polkadot-sdk/" 5 | repository = "https://github.com/paritytech/polkadot-sdk-solochain-template.git" 6 | edition = "2021" 7 | 8 | [workspace] 9 | members = [ 10 | "node", 11 | "pallets/template", 12 | "runtime", 13 | ] 14 | resolver = "2" 15 | 16 | [workspace.dependencies] 17 | solochain-template-runtime = { path = "./runtime", default-features = false } 18 | pallet-template = { path = "./pallets/template", default-features = false } 19 | clap = { version = "4.5.13" } 20 | frame-benchmarking-cli = { version = "47.0.0", default-features = false } 21 | frame-metadata-hash-extension = { version = "0.8.0", default-features = false } 22 | frame-system = { version = "40.1.0", default-features = false } 23 | futures = { version = "0.3.31" } 24 | jsonrpsee = { version = "0.24.3" } 25 | pallet-transaction-payment = { version = "40.0.0", default-features = false } 26 | pallet-transaction-payment-rpc = { version = "43.0.0", default-features = false } 27 | sc-basic-authorship = { version = "0.49.0", default-features = false } 28 | sc-cli = { version = "0.51.0", default-features = false } 29 | sc-client-api = { version = "39.0.0", default-features = false } 30 | sc-consensus = { version = "0.48.0", default-features = false } 31 | sc-consensus-aura = { version = "0.49.0", default-features = false } 32 | sc-consensus-grandpa = { version = "0.34.0", default-features = false } 33 | sc-executor = { version = "0.42.0", default-features = false } 34 | sc-network = { version = "0.49.1", default-features = false } 35 | sc-offchain = { version = "44.0.0", default-features = false } 36 | sc-service = { version = "0.50.0", default-features = false } 37 | sc-telemetry = { version = "28.1.0", default-features = false } 38 | sc-transaction-pool = { version = "39.0.0", default-features = false } 39 | sc-transaction-pool-api = { version = "39.0.0", default-features = false } 40 | sp-api = { version = "36.0.1", default-features = false } 41 | sp-block-builder = { version = "36.0.0", default-features = false } 42 | sp-blockchain = { version = "39.0.0", default-features = false } 43 | sp-consensus-aura = { version = "0.42.0", default-features = false } 44 | sp-core = { version = "36.1.0", default-features = false } 45 | sp-genesis-builder = { version = "0.17.0", default-features = false } 46 | sp-inherents = { version = "36.0.0", default-features = false } 47 | sp-io = { version = "40.0.1", default-features = false } 48 | sp-keyring = { version = "41.0.0", default-features = false } 49 | sp-runtime = { version = "41.1.0", default-features = false } 50 | sp-timestamp = { version = "36.0.0", default-features = false } 51 | substrate-frame-rpc-system = { version = "43.0.0", default-features = false } 52 | substrate-build-script-utils = { version = "11.0.0", default-features = false } 53 | codec = { version = "3.7.4", default-features = false, package = "parity-scale-codec" } 54 | frame-benchmarking = { version = "40.0.0", default-features = false } 55 | frame-executive = { version = "40.0.0", default-features = false } 56 | frame-support = { version = "40.1.0", default-features = false } 57 | frame-system-benchmarking = { version = "40.0.0", default-features = false } 58 | frame-system-rpc-runtime-api = { version = "36.0.0", default-features = false } 59 | frame-try-runtime = { version = "0.46.0", default-features = false } 60 | pallet-aura = { version = "39.0.0", default-features = false } 61 | pallet-balances = { version = "41.1.0", default-features = false } 62 | pallet-grandpa = { version = "40.0.0", default-features = false } 63 | pallet-sudo = { version = "40.0.0", default-features = false } 64 | pallet-timestamp = { version = "39.0.0", default-features = false } 65 | pallet-transaction-payment-rpc-runtime-api = { version = "40.0.0", default-features = false } 66 | scale-info = { version = "2.11.6", default-features = false } 67 | serde_json = { version = "1.0.132", default-features = false } 68 | sp-consensus-grandpa = { version = "23.1.0", default-features = false } 69 | sp-offchain = { version = "36.0.0", default-features = false } 70 | sp-session = { version = "38.1.0", default-features = false } 71 | sp-storage = { version = "22.0.0", default-features = false } 72 | sp-transaction-pool = { version = "36.0.0", default-features = false } 73 | sp-version = { version = "39.0.0", default-features = false } 74 | substrate-wasm-builder = { version = "26.0.1", default-features = false } 75 | 76 | [profile.release] 77 | opt-level = 3 78 | panic = "unwind" 79 | 80 | [profile.production] 81 | codegen-units = 1 82 | inherits = "release" 83 | lto = true 84 | 85 | -------------------------------------------------------------------------------- /runtime/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "solochain-template-runtime" 3 | description = "A solochain runtime template built with Substrate, part of Polkadot Sdk." 4 | version = "0.1.0" 5 | license = "Unlicense" 6 | authors.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | edition.workspace = true 10 | publish = false 11 | 12 | [package.metadata.docs.rs] 13 | targets = ["x86_64-unknown-linux-gnu"] 14 | 15 | [dependencies] 16 | codec = { features = ["derive"], workspace = true } 17 | frame-benchmarking = { optional = true, workspace = true } 18 | frame-executive.workspace = true 19 | frame-metadata-hash-extension.workspace = true 20 | frame-support = { features = ["experimental"], workspace = true } 21 | frame-system-benchmarking = { optional = true, workspace = true } 22 | frame-system-rpc-runtime-api.workspace = true 23 | frame-system.workspace = true 24 | frame-try-runtime = { optional = true, workspace = true } 25 | pallet-aura.workspace = true 26 | pallet-balances.workspace = true 27 | pallet-grandpa.workspace = true 28 | pallet-sudo.workspace = true 29 | pallet-template.workspace = true 30 | pallet-timestamp.workspace = true 31 | pallet-transaction-payment-rpc-runtime-api.workspace = true 32 | pallet-transaction-payment.workspace = true 33 | scale-info = { features = ["derive", "serde"], workspace = true } 34 | serde_json = { workspace = true, default-features = false, features = ["alloc"] } 35 | sp-api.workspace = true 36 | sp-block-builder.workspace = true 37 | sp-consensus-aura = { features = ["serde"], workspace = true } 38 | sp-consensus-grandpa = { features = ["serde"], workspace = true } 39 | sp-core = { features = ["serde"], workspace = true } 40 | sp-genesis-builder.workspace = true 41 | sp-inherents.workspace = true 42 | sp-keyring.workspace = true 43 | sp-offchain.workspace = true 44 | sp-runtime = { features = ["serde"], workspace = true } 45 | sp-session.workspace = true 46 | sp-storage.workspace = true 47 | sp-transaction-pool.workspace = true 48 | sp-version = { features = ["serde"], workspace = true } 49 | 50 | [build-dependencies] 51 | substrate-wasm-builder = { optional = true, workspace = true, default-features = true } 52 | 53 | [features] 54 | default = ["std"] 55 | std = [ 56 | "codec/std", 57 | "frame-benchmarking?/std", 58 | "frame-executive/std", 59 | "frame-metadata-hash-extension/std", 60 | "frame-support/std", 61 | "frame-system-benchmarking?/std", 62 | "frame-system-rpc-runtime-api/std", 63 | "frame-system/std", 64 | "frame-try-runtime?/std", 65 | "pallet-aura/std", 66 | "pallet-balances/std", 67 | "pallet-grandpa/std", 68 | "pallet-sudo/std", 69 | "pallet-template/std", 70 | "pallet-timestamp/std", 71 | "pallet-transaction-payment-rpc-runtime-api/std", 72 | "pallet-transaction-payment/std", 73 | "scale-info/std", 74 | "serde_json/std", 75 | "sp-api/std", 76 | "sp-block-builder/std", 77 | "sp-consensus-aura/std", 78 | "sp-consensus-grandpa/std", 79 | "sp-core/std", 80 | "sp-genesis-builder/std", 81 | "sp-inherents/std", 82 | "sp-keyring/std", 83 | "sp-offchain/std", 84 | "sp-runtime/std", 85 | "sp-session/std", 86 | "sp-storage/std", 87 | "sp-transaction-pool/std", 88 | "sp-version/std", 89 | "substrate-wasm-builder", 90 | ] 91 | 92 | runtime-benchmarks = [ 93 | "frame-benchmarking/runtime-benchmarks", 94 | "frame-support/runtime-benchmarks", 95 | "frame-system-benchmarking/runtime-benchmarks", 96 | "frame-system/runtime-benchmarks", 97 | "pallet-balances/runtime-benchmarks", 98 | "pallet-grandpa/runtime-benchmarks", 99 | "pallet-sudo/runtime-benchmarks", 100 | "pallet-template/runtime-benchmarks", 101 | "pallet-timestamp/runtime-benchmarks", 102 | "pallet-transaction-payment/runtime-benchmarks", 103 | "sp-runtime/runtime-benchmarks", 104 | ] 105 | 106 | try-runtime = [ 107 | "frame-executive/try-runtime", 108 | "frame-support/try-runtime", 109 | "frame-system/try-runtime", 110 | "frame-try-runtime/try-runtime", 111 | "pallet-aura/try-runtime", 112 | "pallet-balances/try-runtime", 113 | "pallet-grandpa/try-runtime", 114 | "pallet-sudo/try-runtime", 115 | "pallet-template/try-runtime", 116 | "pallet-timestamp/try-runtime", 117 | "pallet-transaction-payment/try-runtime", 118 | "sp-runtime/try-runtime", 119 | ] 120 | 121 | # Enable the metadata hash generation. 122 | # 123 | # This is hidden behind a feature because it increases the compile time. 124 | # The wasm binary needs to be compiled twice, once to fetch the metadata, 125 | # generate the metadata hash and then a second time with the 126 | # `RUNTIME_METADATA_HASH` environment variable set for the `CheckMetadataHash` 127 | # extension. 128 | metadata-hash = ["substrate-wasm-builder/metadata-hash"] 129 | 130 | # A convenience feature for enabling things when doing a build 131 | # for an on-chain release. 132 | on-chain-release-build = ["metadata-hash", "sp-api/disable-logging"] 133 | -------------------------------------------------------------------------------- /node/src/benchmarking.rs: -------------------------------------------------------------------------------- 1 | //! Setup code for [`super::command`] which would otherwise bloat that module. 2 | //! 3 | //! Should only be used for benchmarking as it may break in other contexts. 4 | 5 | use crate::service::FullClient; 6 | 7 | use runtime::{AccountId, Balance, BalancesCall, SystemCall}; 8 | use sc_cli::Result; 9 | use sc_client_api::BlockBackend; 10 | use solochain_template_runtime as runtime; 11 | use sp_core::{Encode, Pair}; 12 | use sp_inherents::{InherentData, InherentDataProvider}; 13 | use sp_keyring::Sr25519Keyring; 14 | use sp_runtime::{OpaqueExtrinsic, SaturatedConversion}; 15 | 16 | use std::{sync::Arc, time::Duration}; 17 | 18 | /// Generates extrinsics for the `benchmark overhead` command. 19 | /// 20 | /// Note: Should only be used for benchmarking. 21 | pub struct RemarkBuilder { 22 | client: Arc, 23 | } 24 | 25 | impl RemarkBuilder { 26 | /// Creates a new [`Self`] from the given client. 27 | pub fn new(client: Arc) -> Self { 28 | Self { client } 29 | } 30 | } 31 | 32 | impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder { 33 | fn pallet(&self) -> &str { 34 | "system" 35 | } 36 | 37 | fn extrinsic(&self) -> &str { 38 | "remark" 39 | } 40 | 41 | fn build(&self, nonce: u32) -> std::result::Result { 42 | let acc = Sr25519Keyring::Bob.pair(); 43 | let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( 44 | self.client.as_ref(), 45 | acc, 46 | SystemCall::remark { remark: vec![] }.into(), 47 | nonce, 48 | ) 49 | .into(); 50 | 51 | Ok(extrinsic) 52 | } 53 | } 54 | 55 | /// Generates `Balances::TransferKeepAlive` extrinsics for the benchmarks. 56 | /// 57 | /// Note: Should only be used for benchmarking. 58 | pub struct TransferKeepAliveBuilder { 59 | client: Arc, 60 | dest: AccountId, 61 | value: Balance, 62 | } 63 | 64 | impl TransferKeepAliveBuilder { 65 | /// Creates a new [`Self`] from the given client. 66 | pub fn new(client: Arc, dest: AccountId, value: Balance) -> Self { 67 | Self { client, dest, value } 68 | } 69 | } 70 | 71 | impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { 72 | fn pallet(&self) -> &str { 73 | "balances" 74 | } 75 | 76 | fn extrinsic(&self) -> &str { 77 | "transfer_keep_alive" 78 | } 79 | 80 | fn build(&self, nonce: u32) -> std::result::Result { 81 | let acc = Sr25519Keyring::Bob.pair(); 82 | let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( 83 | self.client.as_ref(), 84 | acc, 85 | BalancesCall::transfer_keep_alive { dest: self.dest.clone().into(), value: self.value } 86 | .into(), 87 | nonce, 88 | ) 89 | .into(); 90 | 91 | Ok(extrinsic) 92 | } 93 | } 94 | 95 | /// Create a transaction using the given `call`. 96 | /// 97 | /// Note: Should only be used for benchmarking. 98 | pub fn create_benchmark_extrinsic( 99 | client: &FullClient, 100 | sender: sp_core::sr25519::Pair, 101 | call: runtime::RuntimeCall, 102 | nonce: u32, 103 | ) -> runtime::UncheckedExtrinsic { 104 | let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); 105 | let best_hash = client.chain_info().best_hash; 106 | let best_block = client.chain_info().best_number; 107 | 108 | let period = runtime::configs::BlockHashCount::get() 109 | .checked_next_power_of_two() 110 | .map(|c| c / 2) 111 | .unwrap_or(2) as u64; 112 | let tx_ext: runtime::TxExtension = ( 113 | frame_system::CheckNonZeroSender::::new(), 114 | frame_system::CheckSpecVersion::::new(), 115 | frame_system::CheckTxVersion::::new(), 116 | frame_system::CheckGenesis::::new(), 117 | frame_system::CheckEra::::from(sp_runtime::generic::Era::mortal( 118 | period, 119 | best_block.saturated_into(), 120 | )), 121 | frame_system::CheckNonce::::from(nonce), 122 | frame_system::CheckWeight::::new(), 123 | pallet_transaction_payment::ChargeTransactionPayment::::from(0), 124 | frame_metadata_hash_extension::CheckMetadataHash::::new(false), 125 | frame_system::WeightReclaim::::new(), 126 | ); 127 | 128 | let raw_payload = runtime::SignedPayload::from_raw( 129 | call.clone(), 130 | tx_ext.clone(), 131 | ( 132 | (), 133 | runtime::VERSION.spec_version, 134 | runtime::VERSION.transaction_version, 135 | genesis_hash, 136 | best_hash, 137 | (), 138 | (), 139 | (), 140 | None, 141 | (), 142 | ), 143 | ); 144 | let signature = raw_payload.using_encoded(|e| sender.sign(e)); 145 | 146 | runtime::UncheckedExtrinsic::new_signed( 147 | call, 148 | sp_runtime::AccountId32::from(sender.public()).into(), 149 | runtime::Signature::Sr25519(signature), 150 | tx_ext, 151 | ) 152 | } 153 | 154 | /// Generates inherent data for the `benchmark overhead` command. 155 | /// 156 | /// Note: Should only be used for benchmarking. 157 | pub fn inherent_benchmark_data() -> Result { 158 | let mut inherent_data = InherentData::new(); 159 | let d = Duration::from_millis(0); 160 | let timestamp = sp_timestamp::InherentDataProvider::new(d.into()); 161 | 162 | futures::executor::block_on(timestamp.provide_inherent_data(&mut inherent_data)) 163 | .map_err(|e| format!("creating inherent data: {:?}", e))?; 164 | Ok(inherent_data) 165 | } 166 | -------------------------------------------------------------------------------- /runtime/src/configs/mod.rs: -------------------------------------------------------------------------------- 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 | 26 | // Substrate and Polkadot dependencies 27 | use frame_support::{ 28 | derive_impl, parameter_types, 29 | traits::{ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, VariantCountOf}, 30 | weights::{ 31 | constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, 32 | IdentityFee, Weight, 33 | }, 34 | }; 35 | use frame_system::limits::{BlockLength, BlockWeights}; 36 | use pallet_transaction_payment::{ConstFeeMultiplier, FungibleAdapter, Multiplier}; 37 | use sp_consensus_aura::sr25519::AuthorityId as AuraId; 38 | use sp_runtime::{traits::One, Perbill}; 39 | use sp_version::RuntimeVersion; 40 | 41 | // Local module imports 42 | use super::{ 43 | AccountId, Aura, Balance, Balances, Block, BlockNumber, Hash, Nonce, PalletInfo, Runtime, 44 | RuntimeCall, RuntimeEvent, RuntimeFreezeReason, RuntimeHoldReason, RuntimeOrigin, RuntimeTask, 45 | System, EXISTENTIAL_DEPOSIT, SLOT_DURATION, VERSION, 46 | }; 47 | 48 | const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); 49 | 50 | parameter_types! { 51 | pub const BlockHashCount: BlockNumber = 2400; 52 | pub const Version: RuntimeVersion = VERSION; 53 | 54 | /// We allow for 2 seconds of compute with a 6 second average block time. 55 | pub RuntimeBlockWeights: BlockWeights = BlockWeights::with_sensible_defaults( 56 | Weight::from_parts(2u64 * WEIGHT_REF_TIME_PER_SECOND, u64::MAX), 57 | NORMAL_DISPATCH_RATIO, 58 | ); 59 | pub RuntimeBlockLength: BlockLength = BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); 60 | pub const SS58Prefix: u8 = 42; 61 | } 62 | 63 | /// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from 64 | /// [`SoloChainDefaultConfig`](`struct@frame_system::config_preludes::SolochainDefaultConfig`), 65 | /// but overridden as needed. 66 | #[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)] 67 | impl frame_system::Config for Runtime { 68 | /// The block type for the runtime. 69 | type Block = Block; 70 | /// Block & extrinsics weights: base values and limits. 71 | type BlockWeights = RuntimeBlockWeights; 72 | /// The maximum length of a block (in bytes). 73 | type BlockLength = RuntimeBlockLength; 74 | /// The identifier used to distinguish between accounts. 75 | type AccountId = AccountId; 76 | /// The type for storing how many extrinsics an account has signed. 77 | type Nonce = Nonce; 78 | /// The type for hashing blocks and tries. 79 | type Hash = Hash; 80 | /// Maximum number of block number to block hash mappings to keep (oldest pruned first). 81 | type BlockHashCount = BlockHashCount; 82 | /// The weight of database operations that the runtime can invoke. 83 | type DbWeight = RocksDbWeight; 84 | /// Version of the runtime. 85 | type Version = Version; 86 | /// The data to be stored in an account. 87 | type AccountData = pallet_balances::AccountData; 88 | /// This is used as an identifier of the chain. 42 is the generic substrate prefix. 89 | type SS58Prefix = SS58Prefix; 90 | type MaxConsumers = frame_support::traits::ConstU32<16>; 91 | } 92 | 93 | impl pallet_aura::Config for Runtime { 94 | type AuthorityId = AuraId; 95 | type DisabledValidators = (); 96 | type MaxAuthorities = ConstU32<32>; 97 | type AllowMultipleBlocksPerSlot = ConstBool; 98 | type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; 99 | } 100 | 101 | impl pallet_grandpa::Config for Runtime { 102 | type RuntimeEvent = RuntimeEvent; 103 | 104 | type WeightInfo = (); 105 | type MaxAuthorities = ConstU32<32>; 106 | type MaxNominators = ConstU32<0>; 107 | type MaxSetIdSessionEntries = ConstU64<0>; 108 | 109 | type KeyOwnerProof = sp_core::Void; 110 | type EquivocationReportSystem = (); 111 | } 112 | 113 | impl pallet_timestamp::Config for Runtime { 114 | /// A timestamp: milliseconds since the unix epoch. 115 | type Moment = u64; 116 | type OnTimestampSet = Aura; 117 | type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; 118 | type WeightInfo = (); 119 | } 120 | 121 | impl pallet_balances::Config for Runtime { 122 | type MaxLocks = ConstU32<50>; 123 | type MaxReserves = (); 124 | type ReserveIdentifier = [u8; 8]; 125 | /// The type for recording an account's balance. 126 | type Balance = Balance; 127 | /// The ubiquitous event type. 128 | type RuntimeEvent = RuntimeEvent; 129 | type DustRemoval = (); 130 | type ExistentialDeposit = ConstU128; 131 | type AccountStore = System; 132 | type WeightInfo = pallet_balances::weights::SubstrateWeight; 133 | type FreezeIdentifier = RuntimeFreezeReason; 134 | type MaxFreezes = VariantCountOf; 135 | type RuntimeHoldReason = RuntimeHoldReason; 136 | type RuntimeFreezeReason = RuntimeFreezeReason; 137 | type DoneSlashHandler = (); 138 | } 139 | 140 | parameter_types! { 141 | pub FeeMultiplier: Multiplier = Multiplier::one(); 142 | } 143 | 144 | impl pallet_transaction_payment::Config for Runtime { 145 | type RuntimeEvent = RuntimeEvent; 146 | type OnChargeTransaction = FungibleAdapter; 147 | type OperationalFeeMultiplier = ConstU8<5>; 148 | type WeightToFee = IdentityFee; 149 | type LengthToFee = IdentityFee; 150 | type FeeMultiplierUpdate = ConstFeeMultiplier; 151 | type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; 152 | } 153 | 154 | impl pallet_sudo::Config for Runtime { 155 | type RuntimeEvent = RuntimeEvent; 156 | type RuntimeCall = RuntimeCall; 157 | type WeightInfo = pallet_sudo::weights::SubstrateWeight; 158 | } 159 | 160 | /// Configure the pallet-template in pallets/template. 161 | impl pallet_template::Config for Runtime { 162 | type RuntimeEvent = RuntimeEvent; 163 | type WeightInfo = pallet_template::weights::SubstrateWeight; 164 | } 165 | -------------------------------------------------------------------------------- /node/src/command.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder}, 3 | chain_spec, 4 | cli::{Cli, Subcommand}, 5 | service, 6 | }; 7 | use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory, SUBSTRATE_REFERENCE_HARDWARE}; 8 | use sc_cli::SubstrateCli; 9 | use sc_service::PartialComponents; 10 | use solochain_template_runtime::{Block, EXISTENTIAL_DEPOSIT}; 11 | use sp_keyring::Sr25519Keyring; 12 | 13 | impl SubstrateCli for Cli { 14 | fn impl_name() -> String { 15 | "Substrate Node".into() 16 | } 17 | 18 | fn impl_version() -> String { 19 | env!("SUBSTRATE_CLI_IMPL_VERSION").into() 20 | } 21 | 22 | fn description() -> String { 23 | env!("CARGO_PKG_DESCRIPTION").into() 24 | } 25 | 26 | fn author() -> String { 27 | env!("CARGO_PKG_AUTHORS").into() 28 | } 29 | 30 | fn support_url() -> String { 31 | "support.anonymous.an".into() 32 | } 33 | 34 | fn copyright_start_year() -> i32 { 35 | 2017 36 | } 37 | 38 | fn load_spec(&self, id: &str) -> Result, String> { 39 | Ok(match id { 40 | "dev" => Box::new(chain_spec::development_chain_spec()?), 41 | "" | "local" => Box::new(chain_spec::local_chain_spec()?), 42 | path => 43 | Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), 44 | }) 45 | } 46 | } 47 | 48 | /// Parse and run command line arguments 49 | pub fn run() -> sc_cli::Result<()> { 50 | let cli = Cli::from_args(); 51 | 52 | match &cli.subcommand { 53 | Some(Subcommand::Key(cmd)) => cmd.run(&cli), 54 | Some(Subcommand::BuildSpec(cmd)) => { 55 | let runner = cli.create_runner(cmd)?; 56 | runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) 57 | }, 58 | Some(Subcommand::CheckBlock(cmd)) => { 59 | let runner = cli.create_runner(cmd)?; 60 | runner.async_run(|config| { 61 | let PartialComponents { client, task_manager, import_queue, .. } = 62 | service::new_partial(&config)?; 63 | Ok((cmd.run(client, import_queue), task_manager)) 64 | }) 65 | }, 66 | Some(Subcommand::ExportBlocks(cmd)) => { 67 | let runner = cli.create_runner(cmd)?; 68 | runner.async_run(|config| { 69 | let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; 70 | Ok((cmd.run(client, config.database), task_manager)) 71 | }) 72 | }, 73 | Some(Subcommand::ExportState(cmd)) => { 74 | let runner = cli.create_runner(cmd)?; 75 | runner.async_run(|config| { 76 | let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; 77 | Ok((cmd.run(client, config.chain_spec), task_manager)) 78 | }) 79 | }, 80 | Some(Subcommand::ImportBlocks(cmd)) => { 81 | let runner = cli.create_runner(cmd)?; 82 | runner.async_run(|config| { 83 | let PartialComponents { client, task_manager, import_queue, .. } = 84 | service::new_partial(&config)?; 85 | Ok((cmd.run(client, import_queue), task_manager)) 86 | }) 87 | }, 88 | Some(Subcommand::PurgeChain(cmd)) => { 89 | let runner = cli.create_runner(cmd)?; 90 | runner.sync_run(|config| cmd.run(config.database)) 91 | }, 92 | Some(Subcommand::Revert(cmd)) => { 93 | let runner = cli.create_runner(cmd)?; 94 | runner.async_run(|config| { 95 | let PartialComponents { client, task_manager, backend, .. } = 96 | service::new_partial(&config)?; 97 | let aux_revert = Box::new(|client, _, blocks| { 98 | sc_consensus_grandpa::revert(client, blocks)?; 99 | Ok(()) 100 | }); 101 | Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) 102 | }) 103 | }, 104 | Some(Subcommand::Benchmark(cmd)) => { 105 | let runner = cli.create_runner(cmd)?; 106 | 107 | runner.sync_run(|config| { 108 | // This switch needs to be in the client, since the client decides 109 | // which sub-commands it wants to support. 110 | match cmd { 111 | BenchmarkCmd::Pallet(cmd) => { 112 | if !cfg!(feature = "runtime-benchmarks") { 113 | return Err( 114 | "Runtime benchmarking wasn't enabled when building the node. \ 115 | You can enable it with `--features runtime-benchmarks`." 116 | .into(), 117 | ); 118 | } 119 | 120 | cmd.run_with_spec::, ()>(Some( 121 | config.chain_spec, 122 | )) 123 | }, 124 | BenchmarkCmd::Block(cmd) => { 125 | let PartialComponents { client, .. } = service::new_partial(&config)?; 126 | cmd.run(client) 127 | }, 128 | #[cfg(not(feature = "runtime-benchmarks"))] 129 | BenchmarkCmd::Storage(_) => Err( 130 | "Storage benchmarking can be enabled with `--features runtime-benchmarks`." 131 | .into(), 132 | ), 133 | #[cfg(feature = "runtime-benchmarks")] 134 | BenchmarkCmd::Storage(cmd) => { 135 | let PartialComponents { client, backend, .. } = 136 | service::new_partial(&config)?; 137 | let db = backend.expose_db(); 138 | let storage = backend.expose_storage(); 139 | 140 | cmd.run(config, client, db, storage) 141 | }, 142 | BenchmarkCmd::Overhead(cmd) => { 143 | let PartialComponents { client, .. } = service::new_partial(&config)?; 144 | let ext_builder = RemarkBuilder::new(client.clone()); 145 | 146 | cmd.run( 147 | config.chain_spec.name().into(), 148 | client, 149 | inherent_benchmark_data()?, 150 | Vec::new(), 151 | &ext_builder, 152 | false, 153 | ) 154 | }, 155 | BenchmarkCmd::Extrinsic(cmd) => { 156 | let PartialComponents { client, .. } = service::new_partial(&config)?; 157 | // Register the *Remark* and *TKA* builders. 158 | let ext_factory = ExtrinsicFactory(vec![ 159 | Box::new(RemarkBuilder::new(client.clone())), 160 | Box::new(TransferKeepAliveBuilder::new( 161 | client.clone(), 162 | Sr25519Keyring::Alice.to_account_id(), 163 | EXISTENTIAL_DEPOSIT, 164 | )), 165 | ]); 166 | 167 | cmd.run(client, inherent_benchmark_data()?, Vec::new(), &ext_factory) 168 | }, 169 | BenchmarkCmd::Machine(cmd) => 170 | cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()), 171 | } 172 | }) 173 | }, 174 | Some(Subcommand::ChainInfo(cmd)) => { 175 | let runner = cli.create_runner(cmd)?; 176 | runner.sync_run(|config| cmd.run::(&config)) 177 | }, 178 | None => { 179 | let runner = cli.create_runner(&cli.run)?; 180 | runner.run_node_until_exit(|config| async move { 181 | match config.network.network_backend.unwrap_or_default() { 182 | sc_network::config::NetworkBackendType::Libp2p => service::new_full::< 183 | sc_network::NetworkWorker< 184 | solochain_template_runtime::opaque::Block, 185 | ::Hash, 186 | >, 187 | >(config) 188 | .map_err(sc_cli::Error::Service), 189 | sc_network::config::NetworkBackendType::Litep2p => 190 | service::new_full::(config) 191 | .map_err(sc_cli::Error::Service), 192 | } 193 | }) 194 | }, 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /runtime/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | 3 | #[cfg(feature = "std")] 4 | include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); 5 | 6 | pub mod apis; 7 | #[cfg(feature = "runtime-benchmarks")] 8 | mod benchmarks; 9 | pub mod configs; 10 | 11 | extern crate alloc; 12 | use alloc::vec::Vec; 13 | use sp_runtime::{ 14 | generic, impl_opaque_keys, 15 | traits::{BlakeTwo256, IdentifyAccount, Verify}, 16 | MultiAddress, MultiSignature, 17 | }; 18 | #[cfg(feature = "std")] 19 | use sp_version::NativeVersion; 20 | use sp_version::RuntimeVersion; 21 | 22 | pub use frame_system::Call as SystemCall; 23 | pub use pallet_balances::Call as BalancesCall; 24 | pub use pallet_timestamp::Call as TimestampCall; 25 | #[cfg(any(feature = "std", test))] 26 | pub use sp_runtime::BuildStorage; 27 | 28 | pub mod genesis_config_presets; 29 | 30 | /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know 31 | /// the specifics of the runtime. They can then be made to be agnostic over specific formats 32 | /// of data like extrinsics, allowing for them to continue syncing the network through upgrades 33 | /// to even the core data structures. 34 | pub mod opaque { 35 | use super::*; 36 | use sp_runtime::{ 37 | generic, 38 | traits::{BlakeTwo256, Hash as HashT}, 39 | }; 40 | 41 | pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; 42 | 43 | /// Opaque block header type. 44 | pub type Header = generic::Header; 45 | /// Opaque block type. 46 | pub type Block = generic::Block; 47 | /// Opaque block identifier type. 48 | pub type BlockId = generic::BlockId; 49 | /// Opaque block hash type. 50 | pub type Hash = ::Output; 51 | } 52 | 53 | impl_opaque_keys! { 54 | pub struct SessionKeys { 55 | pub aura: Aura, 56 | pub grandpa: Grandpa, 57 | } 58 | } 59 | 60 | // To learn more about runtime versioning, see: 61 | // https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning 62 | #[sp_version::runtime_version] 63 | pub const VERSION: RuntimeVersion = RuntimeVersion { 64 | spec_name: alloc::borrow::Cow::Borrowed("solochain-template-runtime"), 65 | impl_name: alloc::borrow::Cow::Borrowed("solochain-template-runtime"), 66 | authoring_version: 1, 67 | // The version of the runtime specification. A full node will not attempt to use its native 68 | // runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, 69 | // `spec_version`, and `authoring_version` are the same between Wasm and native. 70 | // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use 71 | // the compatible custom types. 72 | spec_version: 100, 73 | impl_version: 1, 74 | apis: apis::RUNTIME_API_VERSIONS, 75 | transaction_version: 1, 76 | system_version: 1, 77 | }; 78 | 79 | mod block_times { 80 | /// This determines the average expected block time that we are targeting. Blocks will be 81 | /// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by 82 | /// `pallet_timestamp` which is in turn picked up by `pallet_aura` to implement `fn 83 | /// slot_duration()`. 84 | /// 85 | /// Change this to adjust the block time. 86 | pub const MILLI_SECS_PER_BLOCK: u64 = 6000; 87 | 88 | // NOTE: Currently it is not possible to change the slot duration after the chain has started. 89 | // Attempting to do so will brick block production. 90 | pub const SLOT_DURATION: u64 = MILLI_SECS_PER_BLOCK; 91 | } 92 | pub use block_times::*; 93 | 94 | // Time is measured by number of blocks. 95 | pub const MINUTES: BlockNumber = 60_000 / (MILLI_SECS_PER_BLOCK as BlockNumber); 96 | pub const HOURS: BlockNumber = MINUTES * 60; 97 | pub const DAYS: BlockNumber = HOURS * 24; 98 | 99 | pub const BLOCK_HASH_COUNT: BlockNumber = 2400; 100 | 101 | // Unit = the base number of indivisible units for balances 102 | pub const UNIT: Balance = 1_000_000_000_000; 103 | pub const MILLI_UNIT: Balance = 1_000_000_000; 104 | pub const MICRO_UNIT: Balance = 1_000_000; 105 | 106 | /// Existential deposit. 107 | pub const EXISTENTIAL_DEPOSIT: Balance = MILLI_UNIT; 108 | 109 | /// The version information used to identify this runtime when compiled natively. 110 | #[cfg(feature = "std")] 111 | pub fn native_version() -> NativeVersion { 112 | NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } 113 | } 114 | 115 | /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. 116 | pub type Signature = MultiSignature; 117 | 118 | /// Some way of identifying an account on the chain. We intentionally make it equivalent 119 | /// to the public key of our transaction signing scheme. 120 | pub type AccountId = <::Signer as IdentifyAccount>::AccountId; 121 | 122 | /// Balance of an account. 123 | pub type Balance = u128; 124 | 125 | /// Index of a transaction in the chain. 126 | pub type Nonce = u32; 127 | 128 | /// A hash of some data used by the chain. 129 | pub type Hash = sp_core::H256; 130 | 131 | /// An index to a block. 132 | pub type BlockNumber = u32; 133 | 134 | /// The address format for describing accounts. 135 | pub type Address = MultiAddress; 136 | 137 | /// Block header type as expected by this runtime. 138 | pub type Header = generic::Header; 139 | 140 | /// Block type as expected by this runtime. 141 | pub type Block = generic::Block; 142 | 143 | /// A Block signed with a Justification 144 | pub type SignedBlock = generic::SignedBlock; 145 | 146 | /// BlockId type as expected by this runtime. 147 | pub type BlockId = generic::BlockId; 148 | 149 | /// The `TransactionExtension` to the basic transaction logic. 150 | pub type TxExtension = ( 151 | frame_system::CheckNonZeroSender, 152 | frame_system::CheckSpecVersion, 153 | frame_system::CheckTxVersion, 154 | frame_system::CheckGenesis, 155 | frame_system::CheckEra, 156 | frame_system::CheckNonce, 157 | frame_system::CheckWeight, 158 | pallet_transaction_payment::ChargeTransactionPayment, 159 | frame_metadata_hash_extension::CheckMetadataHash, 160 | frame_system::WeightReclaim, 161 | ); 162 | 163 | /// Unchecked extrinsic type as expected by this runtime. 164 | pub type UncheckedExtrinsic = 165 | generic::UncheckedExtrinsic; 166 | 167 | /// The payload being signed in transactions. 168 | pub type SignedPayload = generic::SignedPayload; 169 | 170 | /// All migrations of the runtime, aside from the ones declared in the pallets. 171 | /// 172 | /// This can be a tuple of types, each implementing `OnRuntimeUpgrade`. 173 | #[allow(unused_parens)] 174 | type Migrations = (); 175 | 176 | /// Executive: handles dispatch to the various modules. 177 | pub type Executive = frame_executive::Executive< 178 | Runtime, 179 | Block, 180 | frame_system::ChainContext, 181 | Runtime, 182 | AllPalletsWithSystem, 183 | Migrations, 184 | >; 185 | 186 | // Create the runtime by composing the FRAME pallets that were previously configured. 187 | #[frame_support::runtime] 188 | mod runtime { 189 | #[runtime::runtime] 190 | #[runtime::derive( 191 | RuntimeCall, 192 | RuntimeEvent, 193 | RuntimeError, 194 | RuntimeOrigin, 195 | RuntimeFreezeReason, 196 | RuntimeHoldReason, 197 | RuntimeSlashReason, 198 | RuntimeLockId, 199 | RuntimeTask, 200 | RuntimeViewFunction 201 | )] 202 | pub struct Runtime; 203 | 204 | #[runtime::pallet_index(0)] 205 | pub type System = frame_system; 206 | 207 | #[runtime::pallet_index(1)] 208 | pub type Timestamp = pallet_timestamp; 209 | 210 | #[runtime::pallet_index(2)] 211 | pub type Aura = pallet_aura; 212 | 213 | #[runtime::pallet_index(3)] 214 | pub type Grandpa = pallet_grandpa; 215 | 216 | #[runtime::pallet_index(4)] 217 | pub type Balances = pallet_balances; 218 | 219 | #[runtime::pallet_index(5)] 220 | pub type TransactionPayment = pallet_transaction_payment; 221 | 222 | #[runtime::pallet_index(6)] 223 | pub type Sudo = pallet_sudo; 224 | 225 | // Include the custom logic from the pallet-template in the runtime. 226 | #[runtime::pallet_index(7)] 227 | pub type Template = pallet_template; 228 | } 229 | -------------------------------------------------------------------------------- /docs/rust-setup.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | This guide is for reference only, please check the latest information on getting started with Substrate [here](https://docs.substrate.io/main-docs/install/). 4 | 5 | This page will guide you through the **2 steps** needed to prepare a computer for **Substrate** development. Since 6 | Substrate is built with [the Rust programming language](https://www.rust-lang.org/), the first thing you will need to do 7 | is prepare the computer for Rust development - these steps will vary based on the computer's operating system. Once Rust 8 | is configured, you will use its toolchains to interact with Rust projects; the commands for Rust's toolchains will be 9 | the same for all supported, Unix-based operating systems. 10 | 11 | ## Build dependencies 12 | 13 | Substrate development is easiest on Unix-based operating systems like macOS or Linux. The examples in the [Substrate 14 | Docs](https://docs.substrate.io) use Unix-style terminals to demonstrate how to interact with Substrate from the command 15 | line. 16 | 17 | ### Ubuntu/Debian 18 | 19 | Use a terminal shell to execute the following commands: 20 | 21 | ```bash 22 | sudo apt update 23 | # May prompt for location information 24 | sudo apt install -y git clang curl libssl-dev llvm libudev-dev 25 | ``` 26 | 27 | ### Arch Linux 28 | 29 | Run these commands from a terminal: 30 | 31 | ```bash 32 | pacman -Syu --needed --noconfirm curl git clang 33 | ``` 34 | 35 | ### Fedora 36 | 37 | Run these commands from a terminal: 38 | 39 | ```bash 40 | sudo dnf update 41 | sudo dnf install clang curl git openssl-devel 42 | ``` 43 | 44 | ### OpenSUSE 45 | 46 | Run these commands from a terminal: 47 | 48 | ```bash 49 | sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel 50 | ``` 51 | 52 | ### macOS 53 | 54 | > **Apple M1 ARM** If you have an Apple M1 ARM system on a chip, make sure that you have Apple Rosetta 2 installed 55 | > through `softwareupdate --install-rosetta`. This is only needed to run the `protoc` tool during the build. The build 56 | > itself and the target binaries would remain native. 57 | 58 | Open the Terminal application and execute the following commands: 59 | 60 | ```bash 61 | # Install Homebrew if necessary https://brew.sh/ 62 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" 63 | 64 | # Make sure Homebrew is up-to-date, install openssl 65 | brew update 66 | brew install openssl 67 | ``` 68 | 69 | ### Windows 70 | 71 | **_PLEASE NOTE:_** Native Windows development of Substrate is _not_ very well supported! It is _highly_ 72 | recommended to use [Windows Subsystem Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10) 73 | (WSL) and follow the instructions for [Ubuntu/Debian](#ubuntudebian). 74 | Please refer to the separate 75 | [guide for native Windows development](https://docs.substrate.io/main-docs/install/windows/). 76 | 77 | ## Rust developer environment 78 | 79 | This guide uses installer and the `rustup` tool to manage the Rust toolchain. First install and 80 | configure `rustup`: 81 | 82 | ```bash 83 | # Install 84 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 85 | # Configure 86 | source ~/.cargo/env 87 | ``` 88 | 89 | Configure the Rust toolchain to default to the latest stable version, add nightly and the nightly wasm target: 90 | 91 | ```bash 92 | rustup default stable 93 | rustup update 94 | rustup update nightly 95 | rustup target add wasm32-unknown-unknown --toolchain nightly 96 | ``` 97 | 98 | ## Test your set-up 99 | 100 | Now the best way to ensure that you have successfully prepared a computer for Substrate development is to follow the 101 | steps in [our first Substrate tutorial](https://docs.substrate.io/tutorials/v3/create-your-first-substrate-chain/). 102 | 103 | ## Troubleshooting Substrate builds 104 | 105 | Sometimes you can't get the Substrate node template to compile out of the box. Here are some tips to help you work 106 | through that. 107 | 108 | ### Rust configuration check 109 | 110 | To see what Rust toolchain you are presently using, run: 111 | 112 | ```bash 113 | rustup show 114 | ``` 115 | 116 | This will show something like this (Ubuntu example) output: 117 | 118 | ```text 119 | Default host: x86_64-unknown-linux-gnu 120 | rustup home: /home/user/.rustup 121 | 122 | installed toolchains 123 | -------------------- 124 | 125 | stable-x86_64-unknown-linux-gnu (default) 126 | nightly-2020-10-06-x86_64-unknown-linux-gnu 127 | nightly-x86_64-unknown-linux-gnu 128 | 129 | installed targets for active toolchain 130 | -------------------------------------- 131 | 132 | wasm32-unknown-unknown 133 | x86_64-unknown-linux-gnu 134 | 135 | active toolchain 136 | ---------------- 137 | 138 | stable-x86_64-unknown-linux-gnu (default) 139 | rustc 1.50.0 (cb75ad5db 2021-02-10) 140 | ``` 141 | 142 | As you can see above, the default toolchain is stable, and the `nightly-x86_64-unknown-linux-gnu` toolchain as well as 143 | its `wasm32-unknown-unknown` target is installed. You also see that `nightly-2020-10-06-x86_64-unknown-linux-gnu` is 144 | installed, but is not used unless explicitly defined as illustrated in the [specify your nightly 145 | version](#specifying-nightly-version) section. 146 | 147 | ### WebAssembly compilation 148 | 149 | Substrate uses [WebAssembly](https://webassembly.org) (Wasm) to produce portable blockchain runtimes. You will need to 150 | configure your Rust compiler to use [`nightly` builds](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html) to 151 | allow you to compile Substrate runtime code to the Wasm target. 152 | 153 | > There are upstream issues in Rust that need to be resolved before all of Substrate can use the stable Rust toolchain. 154 | > [This is our tracking issue](https://github.com/paritytech/substrate/issues/1252) if you're curious as to why and how 155 | > this will be resolved. 156 | 157 | #### Latest nightly for Substrate `master` 158 | 159 | Developers who are building Substrate _itself_ should always use the latest bug-free versions of Rust stable and 160 | nightly. This is because the Substrate codebase follows the tip of Rust nightly, which means that changes in Substrate 161 | often depend on upstream changes in the Rust nightly compiler. To ensure your Rust compiler is always up to date, you 162 | should run: 163 | 164 | ```bash 165 | rustup update 166 | rustup update nightly 167 | rustup target add wasm32-unknown-unknown --toolchain nightly 168 | ``` 169 | 170 | > NOTE: It may be necessary to occasionally rerun `rustup update` if a change in the upstream Substrate codebase depends 171 | > on a new feature of the Rust compiler. When you do this, both your nightly and stable toolchains will be pulled to the 172 | > most recent release, and for nightly, it is generally _not_ expected to compile WASM without error (although it very 173 | > often does). Be sure to [specify your nightly version](#specifying-nightly-version) if you get WASM build errors from 174 | > `rustup` and [downgrade nightly as needed](#downgrading-rust-nightly). 175 | 176 | #### Rust nightly toolchain 177 | 178 | If you want to guarantee that your build works on your computer as you update Rust and other dependencies, you should 179 | use a specific Rust nightly version that is known to be compatible with the version of Substrate they are using; this 180 | version will vary from project to project and different projects may use different mechanisms to communicate this 181 | version to developers. For instance, the Polkadot client specifies this information in its [release 182 | notes](https://github.com/paritytech/polkadot-sdk/releases). 183 | 184 | ```bash 185 | # Specify the specific nightly toolchain in the date below: 186 | rustup install nightly- 187 | ``` 188 | 189 | #### Wasm toolchain 190 | 191 | Now, configure the nightly version to work with the Wasm compilation target: 192 | 193 | ```bash 194 | rustup target add wasm32-unknown-unknown --toolchain nightly- 195 | ``` 196 | 197 | ### Specifying nightly version 198 | 199 | Use the `WASM_BUILD_TOOLCHAIN` environment variable to specify the Rust nightly version a Substrate project should use 200 | for Wasm compilation: 201 | 202 | ```bash 203 | WASM_BUILD_TOOLCHAIN=nightly- cargo build --release 204 | ``` 205 | 206 | > Note that this only builds _the runtime_ with the specified nightly. The rest of project will be compiled with **your 207 | > default toolchain**, i.e. the latest installed stable toolchain. 208 | 209 | ### Downgrading Rust nightly 210 | 211 | If your computer is configured to use the latest Rust nightly and you would like to downgrade to a specific nightly 212 | version, follow these steps: 213 | 214 | ```bash 215 | rustup uninstall nightly 216 | rustup install nightly- 217 | rustup target add wasm32-unknown-unknown --toolchain nightly- 218 | ``` 219 | -------------------------------------------------------------------------------- /pallets/template/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # Template Pallet 2 | //! 3 | //! A pallet with minimal functionality to help developers understand the essential components of 4 | //! writing a FRAME pallet. It is typically used in beginner tutorials or in Substrate template 5 | //! nodes as a starting point for creating a new pallet and **not meant to be used in production**. 6 | //! 7 | //! ## Overview 8 | //! 9 | //! This template pallet contains basic examples of: 10 | //! - declaring a storage item that stores a single `u32` value 11 | //! - declaring and using events 12 | //! - declaring and using errors 13 | //! - a dispatchable function that allows a user to set a new value to storage and emits an event 14 | //! upon success 15 | //! - another dispatchable function that causes a custom error to be thrown 16 | //! 17 | //! Each pallet section is annotated with an attribute using the `#[pallet::...]` procedural macro. 18 | //! This macro generates the necessary code for a pallet to be aggregated into a FRAME runtime. 19 | //! 20 | //! Learn more about FRAME macros [here](https://docs.substrate.io/reference/frame-macros/). 21 | //! 22 | //! ### Pallet Sections 23 | //! 24 | //! The pallet sections in this template are: 25 | //! 26 | //! - A **configuration trait** that defines the types and parameters which the pallet depends on 27 | //! (denoted by the `#[pallet::config]` attribute). See: [`Config`]. 28 | //! - A **means to store pallet-specific data** (denoted by the `#[pallet::storage]` attribute). 29 | //! See: [`storage_types`]. 30 | //! - A **declaration of the events** this pallet emits (denoted by the `#[pallet::event]` 31 | //! attribute). See: [`Event`]. 32 | //! - A **declaration of the errors** that this pallet can throw (denoted by the `#[pallet::error]` 33 | //! attribute). See: [`Error`]. 34 | //! - A **set of dispatchable functions** that define the pallet's functionality (denoted by the 35 | //! `#[pallet::call]` attribute). See: [`dispatchables`]. 36 | //! 37 | //! Run `cargo doc --package pallet-template --open` to view this pallet's documentation. 38 | 39 | // We make sure this pallet uses `no_std` for compiling to Wasm. 40 | #![cfg_attr(not(feature = "std"), no_std)] 41 | 42 | // Re-export pallet items so that they can be accessed from the crate namespace. 43 | pub use pallet::*; 44 | 45 | // FRAME pallets require their own "mock runtimes" to be able to run unit tests. This module 46 | // contains a mock runtime specific for testing this pallet's functionality. 47 | #[cfg(test)] 48 | mod mock; 49 | 50 | // This module contains the unit tests for this pallet. 51 | // Learn about pallet unit testing here: https://docs.substrate.io/test/unit-testing/ 52 | #[cfg(test)] 53 | mod tests; 54 | 55 | // Every callable function or "dispatchable" a pallet exposes must have weight values that correctly 56 | // estimate a dispatchable's execution time. The benchmarking module is used to calculate weights 57 | // for each dispatchable and generates this pallet's weight.rs file. Learn more about benchmarking here: https://docs.substrate.io/test/benchmark/ 58 | #[cfg(feature = "runtime-benchmarks")] 59 | mod benchmarking; 60 | pub mod weights; 61 | pub use weights::*; 62 | 63 | // All pallet logic is defined in its own module and must be annotated by the `pallet` attribute. 64 | #[frame_support::pallet] 65 | pub mod pallet { 66 | // Import various useful types required by all FRAME pallets. 67 | use super::*; 68 | use frame_support::pallet_prelude::*; 69 | use frame_system::pallet_prelude::*; 70 | 71 | // The `Pallet` struct serves as a placeholder to implement traits, methods and dispatchables 72 | // (`Call`s) in this pallet. 73 | #[pallet::pallet] 74 | pub struct Pallet(_); 75 | 76 | /// The pallet's configuration trait. 77 | /// 78 | /// All our types and constants a pallet depends on must be declared here. 79 | /// These types are defined generically and made concrete when the pallet is declared in the 80 | /// `runtime/src/lib.rs` file of your chain. 81 | #[pallet::config] 82 | pub trait Config: frame_system::Config { 83 | /// The overarching runtime event type. 84 | type RuntimeEvent: From> + IsType<::RuntimeEvent>; 85 | /// A type representing the weights required by the dispatchables of this pallet. 86 | type WeightInfo: WeightInfo; 87 | } 88 | 89 | /// A storage item for this pallet. 90 | /// 91 | /// In this template, we are declaring a storage item called `Something` that stores a single 92 | /// `u32` value. Learn more about runtime storage here: 93 | #[pallet::storage] 94 | pub type Something = StorageValue<_, u32>; 95 | 96 | /// Events that functions in this pallet can emit. 97 | /// 98 | /// Events are a simple means of indicating to the outside world (such as dApps, chain explorers 99 | /// or other users) that some notable update in the runtime has occurred. In a FRAME pallet, the 100 | /// documentation for each event field and its parameters is added to a node's metadata so it 101 | /// can be used by external interfaces or tools. 102 | /// 103 | /// The `generate_deposit` macro generates a function on `Pallet` called `deposit_event` which 104 | /// will convert the event type of your pallet into `RuntimeEvent` (declared in the pallet's 105 | /// [`Config`] trait) and deposit it using [`frame_system::Pallet::deposit_event`]. 106 | #[pallet::event] 107 | #[pallet::generate_deposit(pub(super) fn deposit_event)] 108 | pub enum Event { 109 | /// A user has successfully set a new value. 110 | SomethingStored { 111 | /// The new value set. 112 | something: u32, 113 | /// The account who set the new value. 114 | who: T::AccountId, 115 | }, 116 | } 117 | 118 | /// Errors that can be returned by this pallet. 119 | /// 120 | /// Errors tell users that something went wrong so it's important that their naming is 121 | /// informative. Similar to events, error documentation is added to a node's metadata so it's 122 | /// equally important that they have helpful documentation associated with them. 123 | /// 124 | /// This type of runtime error can be up to 4 bytes in size should you want to return additional 125 | /// information. 126 | #[pallet::error] 127 | pub enum Error { 128 | /// The value retrieved was `None` as no value was previously set. 129 | NoneValue, 130 | /// There was an attempt to increment the value in storage over `u32::MAX`. 131 | StorageOverflow, 132 | } 133 | 134 | /// The pallet's dispatchable functions ([`Call`]s). 135 | /// 136 | /// Dispatchable functions allows users to interact with the pallet and invoke state changes. 137 | /// These functions materialize as "extrinsics", which are often compared to transactions. 138 | /// They must always return a `DispatchResult` and be annotated with a weight and call index. 139 | /// 140 | /// The [`call_index`] macro is used to explicitly 141 | /// define an index for calls in the [`Call`] enum. This is useful for pallets that may 142 | /// introduce new dispatchables over time. If the order of a dispatchable changes, its index 143 | /// will also change which will break backwards compatibility. 144 | /// 145 | /// The [`weight`] macro is used to assign a weight to each call. 146 | #[pallet::call] 147 | impl Pallet { 148 | /// An example dispatchable that takes a single u32 value as a parameter, writes the value 149 | /// to storage and emits an event. 150 | /// 151 | /// It checks that the _origin_ for this call is _Signed_ and returns a dispatch 152 | /// error if it isn't. Learn more about origins here: 153 | #[pallet::call_index(0)] 154 | #[pallet::weight(T::WeightInfo::do_something())] 155 | pub fn do_something(origin: OriginFor, something: u32) -> DispatchResult { 156 | // Check that the extrinsic was signed and get the signer. 157 | let who = ensure_signed(origin)?; 158 | 159 | // Update storage. 160 | Something::::put(something); 161 | 162 | // Emit an event. 163 | Self::deposit_event(Event::SomethingStored { something, who }); 164 | 165 | // Return a successful `DispatchResult` 166 | Ok(()) 167 | } 168 | 169 | /// An example dispatchable that may throw a custom error. 170 | /// 171 | /// It checks that the caller is a signed origin and reads the current value from the 172 | /// `Something` storage item. If a current value exists, it is incremented by 1 and then 173 | /// written back to storage. 174 | /// 175 | /// ## Errors 176 | /// 177 | /// The function will return an error under the following conditions: 178 | /// 179 | /// - If no value has been set ([`Error::NoneValue`]) 180 | /// - If incrementing the value in storage causes an arithmetic overflow 181 | /// ([`Error::StorageOverflow`]) 182 | #[pallet::call_index(1)] 183 | #[pallet::weight(T::WeightInfo::cause_error())] 184 | pub fn cause_error(origin: OriginFor) -> DispatchResult { 185 | let _who = ensure_signed(origin)?; 186 | 187 | // Read a value from storage. 188 | match Something::::get() { 189 | // Return an error if the value has not been set. 190 | None => Err(Error::::NoneValue.into()), 191 | Some(old) => { 192 | // Increment the value read from storage. This will cause an error in the event 193 | // of overflow. 194 | let new = old.checked_add(1).ok_or(Error::::StorageOverflow)?; 195 | // Update the value in storage with the incremented result. 196 | Something::::put(new); 197 | Ok(()) 198 | }, 199 | } 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Substrate Node Template 2 | 3 | A fresh [Substrate](https://substrate.io/) node, ready for hacking :rocket: 4 | 5 | A standalone version of this template is available for each release of Polkadot 6 | in the [Substrate Developer Hub Parachain 7 | Template](https://github.com/substrate-developer-hub/substrate-node-template/) 8 | repository. The parachain template is generated directly at each Polkadot 9 | release branch from the [Solochain Template in 10 | Substrate](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain) 11 | upstream 12 | 13 | It is usually best to use the stand-alone version to start a new project. All 14 | bugs, suggestions, and feature requests should be made upstream in the 15 | [Substrate](https://github.com/paritytech/polkadot-sdk/tree/master/substrate) 16 | repository. 17 | 18 | ## Getting Started 19 | 20 | Depending on your operating system and Rust version, there might be additional 21 | packages required to compile this template. Check the 22 | [Install](https://docs.substrate.io/install/) instructions for your platform for 23 | the most common dependencies. Alternatively, you can use one of the [alternative 24 | installation](#alternatives-installations) options. 25 | 26 | Fetch solochain template code: 27 | 28 | ```sh 29 | git clone https://github.com/paritytech/polkadot-sdk-solochain-template.git solochain-template 30 | 31 | cd solochain-template 32 | ``` 33 | 34 | ### Build 35 | 36 | 🔨 Use the following command to build the node without launching it: 37 | 38 | ```sh 39 | cargo build --release 40 | ``` 41 | 42 | ### Embedded Docs 43 | 44 | After you build the project, you can use the following command to explore its 45 | parameters and subcommands: 46 | 47 | ```sh 48 | ./target/release/solochain-template-node -h 49 | ``` 50 | 51 | You can generate and view the [Rust 52 | Docs](https://doc.rust-lang.org/cargo/commands/cargo-doc.html) for this template 53 | with this command: 54 | 55 | ```sh 56 | cargo +nightly doc --open 57 | ``` 58 | 59 | ### Single-Node Development Chain 60 | 61 | The following command starts a single-node development chain that doesn't 62 | persist state: 63 | 64 | ```sh 65 | ./target/release/solochain-template-node --dev 66 | ``` 67 | 68 | To purge the development chain's state, run the following command: 69 | 70 | ```sh 71 | ./target/release/solochain-template-node purge-chain --dev 72 | ``` 73 | 74 | To start the development chain with detailed logging, run the following command: 75 | 76 | ```sh 77 | RUST_BACKTRACE=1 ./target/release/solochain-template-node -ldebug --dev 78 | ``` 79 | 80 | Development chains: 81 | 82 | - Maintain state in a `tmp` folder while the node is running. 83 | - Use the **Alice** and **Bob** accounts as default validator authorities. 84 | - Use the **Alice** account as the default `sudo` account. 85 | - Are preconfigured with a genesis state (`/node/src/chain_spec.rs`) that 86 | includes several pre-funded development accounts. 87 | 88 | 89 | To persist chain state between runs, specify a base path by running a command 90 | similar to the following: 91 | 92 | ```sh 93 | // Create a folder to use as the db base path 94 | $ mkdir my-chain-state 95 | 96 | // Use of that folder to store the chain state 97 | $ ./target/release/solochain-template-node --dev --base-path ./my-chain-state/ 98 | 99 | // Check the folder structure created inside the base path after running the chain 100 | $ ls ./my-chain-state 101 | chains 102 | $ ls ./my-chain-state/chains/ 103 | dev 104 | $ ls ./my-chain-state/chains/dev 105 | db keystore network 106 | ``` 107 | 108 | ### Connect with Polkadot-JS Apps Front-End 109 | 110 | After you start the node template locally, you can interact with it using the 111 | hosted version of the [Polkadot/Substrate 112 | Portal](https://polkadot.js.org/apps/#/explorer?rpc=ws://localhost:9944) 113 | front-end by connecting to the local node endpoint. A hosted version is also 114 | available on [IPFS](https://dotapps.io/). You can 115 | also find the source code and instructions for hosting your own instance in the 116 | [`polkadot-js/apps`](https://github.com/polkadot-js/apps) repository. 117 | 118 | ### Multi-Node Local Testnet 119 | 120 | If you want to see the multi-node consensus algorithm in action, see [Simulate a 121 | network](https://docs.substrate.io/tutorials/build-a-blockchain/simulate-network/). 122 | 123 | ## Template Structure 124 | 125 | A Substrate project such as this consists of a number of components that are 126 | spread across a few directories. 127 | 128 | ### Node 129 | 130 | A blockchain node is an application that allows users to participate in a 131 | blockchain network. Substrate-based blockchain nodes expose a number of 132 | capabilities: 133 | 134 | - Networking: Substrate nodes use the [`libp2p`](https://libp2p.io/) networking 135 | stack to allow the nodes in the network to communicate with one another. 136 | - Consensus: Blockchains must have a way to come to 137 | [consensus](https://docs.substrate.io/fundamentals/consensus/) on the state of 138 | the network. Substrate makes it possible to supply custom consensus engines 139 | and also ships with several consensus mechanisms that have been built on top 140 | of [Web3 Foundation 141 | research](https://research.web3.foundation/Polkadot/protocols/NPoS). 142 | - RPC Server: A remote procedure call (RPC) server is used to interact with 143 | Substrate nodes. 144 | 145 | There are several files in the `node` directory. Take special note of the 146 | following: 147 | 148 | - [`chain_spec.rs`](./node/src/chain_spec.rs): A [chain 149 | specification](https://docs.substrate.io/build/chain-spec/) is a source code 150 | file that defines a Substrate chain's initial (genesis) state. Chain 151 | specifications are useful for development and testing, and critical when 152 | architecting the launch of a production chain. Take note of the 153 | `development_config` and `testnet_genesis` functions. These functions are 154 | used to define the genesis state for the local development chain 155 | configuration. These functions identify some [well-known 156 | accounts](https://docs.substrate.io/reference/command-line-tools/subkey/) and 157 | use them to configure the blockchain's initial state. 158 | - [`service.rs`](./node/src/service.rs): This file defines the node 159 | implementation. Take note of the libraries that this file imports and the 160 | names of the functions it invokes. In particular, there are references to 161 | consensus-related topics, such as the [block finalization and 162 | forks](https://docs.substrate.io/fundamentals/consensus/#finalization-and-forks) 163 | and other [consensus 164 | mechanisms](https://docs.substrate.io/fundamentals/consensus/#default-consensus-models) 165 | such as Aura for block authoring and GRANDPA for finality. 166 | 167 | 168 | ### Runtime 169 | 170 | In Substrate, the terms "runtime" and "state transition function" are analogous. 171 | Both terms refer to the core logic of the blockchain that is responsible for 172 | validating blocks and executing the state changes they define. The Substrate 173 | project in this repository uses 174 | [FRAME](https://docs.substrate.io/learn/runtime-development/#frame) to construct 175 | a blockchain runtime. FRAME allows runtime developers to declare domain-specific 176 | logic in modules called "pallets". At the heart of FRAME is a helpful [macro 177 | language](https://docs.substrate.io/reference/frame-macros/) that makes it easy 178 | to create pallets and flexibly compose them to create blockchains that can 179 | address [a variety of needs](https://substrate.io/ecosystem/projects/). 180 | 181 | Review the [FRAME runtime implementation](./runtime/src/lib.rs) included in this 182 | template and note the following: 183 | 184 | - This file configures several pallets to include in the runtime. Each pallet 185 | configuration is defined by a code block that begins with `impl 186 | $PALLET_NAME::Config for Runtime`. 187 | - The pallets are composed into a single runtime by way of the 188 | [#[runtime]](https://paritytech.github.io/polkadot-sdk/master/frame_support/attr.runtime.html) 189 | macro, which is part of the [core FRAME pallet 190 | library](https://docs.substrate.io/reference/frame-pallets/#system-pallets). 191 | 192 | ### Pallets 193 | 194 | The runtime in this project is constructed using many FRAME pallets that ship 195 | with [the Substrate 196 | repository](https://github.com/paritytech/polkadot-sdk/tree/master/substrate/frame) and a 197 | template pallet that is [defined in the 198 | `pallets`](./pallets/template/src/lib.rs) directory. 199 | 200 | A FRAME pallet is comprised of a number of blockchain primitives, including: 201 | 202 | - Storage: FRAME defines a rich set of powerful [storage 203 | abstractions](https://docs.substrate.io/build/runtime-storage/) that makes it 204 | easy to use Substrate's efficient key-value database to manage the evolving 205 | state of a blockchain. 206 | - Dispatchables: FRAME pallets define special types of functions that can be 207 | invoked (dispatched) from outside of the runtime in order to update its state. 208 | - Events: Substrate uses 209 | [events](https://docs.substrate.io/build/events-and-errors/) to notify users 210 | of significant state changes. 211 | - Errors: When a dispatchable fails, it returns an error. 212 | 213 | Each pallet has its own `Config` trait which serves as a configuration interface 214 | to generically define the types and parameters it depends on. 215 | 216 | ## Alternatives Installations 217 | 218 | Instead of installing dependencies and building this source directly, consider 219 | the following alternatives. 220 | 221 | ### Nix 222 | 223 | Install [nix](https://nixos.org/) and 224 | [nix-direnv](https://github.com/nix-community/nix-direnv) for a fully 225 | plug-and-play experience for setting up the development environment. To get all 226 | the correct dependencies, activate direnv `direnv allow`. 227 | 228 | ### Docker 229 | 230 | Please follow the [Substrate Docker instructions 231 | here](https://github.com/paritytech/polkadot-sdk/blob/master/substrate/docker/README.md) to 232 | build the Docker container with the Substrate Node Template binary. 233 | -------------------------------------------------------------------------------- /runtime/src/apis.rs: -------------------------------------------------------------------------------- 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 | 26 | // External crates imports 27 | use alloc::vec::Vec; 28 | use frame_support::{ 29 | genesis_builder_helper::{build_state, get_preset}, 30 | weights::Weight, 31 | }; 32 | use pallet_grandpa::AuthorityId as GrandpaId; 33 | use sp_api::impl_runtime_apis; 34 | use sp_consensus_aura::sr25519::AuthorityId as AuraId; 35 | use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; 36 | use sp_runtime::{ 37 | traits::{Block as BlockT, NumberFor}, 38 | transaction_validity::{TransactionSource, TransactionValidity}, 39 | ApplyExtrinsicResult, 40 | }; 41 | use sp_version::RuntimeVersion; 42 | 43 | // Local module imports 44 | use super::{ 45 | AccountId, Aura, Balance, Block, Executive, Grandpa, InherentDataExt, Nonce, Runtime, 46 | RuntimeCall, RuntimeGenesisConfig, SessionKeys, System, TransactionPayment, VERSION, 47 | }; 48 | 49 | impl_runtime_apis! { 50 | impl sp_api::Core for Runtime { 51 | fn version() -> RuntimeVersion { 52 | VERSION 53 | } 54 | 55 | fn execute_block(block: Block) { 56 | Executive::execute_block(block); 57 | } 58 | 59 | fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { 60 | Executive::initialize_block(header) 61 | } 62 | } 63 | 64 | impl sp_api::Metadata for Runtime { 65 | fn metadata() -> OpaqueMetadata { 66 | OpaqueMetadata::new(Runtime::metadata().into()) 67 | } 68 | 69 | fn metadata_at_version(version: u32) -> Option { 70 | Runtime::metadata_at_version(version) 71 | } 72 | 73 | fn metadata_versions() -> Vec { 74 | Runtime::metadata_versions() 75 | } 76 | } 77 | 78 | impl frame_support::view_functions::runtime_api::RuntimeViewFunction for Runtime { 79 | fn execute_view_function(id: frame_support::view_functions::ViewFunctionId, input: Vec) -> Result, frame_support::view_functions::ViewFunctionDispatchError> { 80 | Runtime::execute_view_function(id, input) 81 | } 82 | } 83 | 84 | impl sp_block_builder::BlockBuilder for Runtime { 85 | fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { 86 | Executive::apply_extrinsic(extrinsic) 87 | } 88 | 89 | fn finalize_block() -> ::Header { 90 | Executive::finalize_block() 91 | } 92 | 93 | fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { 94 | data.create_extrinsics() 95 | } 96 | 97 | fn check_inherents( 98 | block: Block, 99 | data: sp_inherents::InherentData, 100 | ) -> sp_inherents::CheckInherentsResult { 101 | data.check_extrinsics(&block) 102 | } 103 | } 104 | 105 | impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { 106 | fn validate_transaction( 107 | source: TransactionSource, 108 | tx: ::Extrinsic, 109 | block_hash: ::Hash, 110 | ) -> TransactionValidity { 111 | Executive::validate_transaction(source, tx, block_hash) 112 | } 113 | } 114 | 115 | impl sp_offchain::OffchainWorkerApi for Runtime { 116 | fn offchain_worker(header: &::Header) { 117 | Executive::offchain_worker(header) 118 | } 119 | } 120 | 121 | impl sp_consensus_aura::AuraApi for Runtime { 122 | fn slot_duration() -> sp_consensus_aura::SlotDuration { 123 | sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) 124 | } 125 | 126 | fn authorities() -> Vec { 127 | pallet_aura::Authorities::::get().into_inner() 128 | } 129 | } 130 | 131 | impl sp_session::SessionKeys for Runtime { 132 | fn generate_session_keys(seed: Option>) -> Vec { 133 | SessionKeys::generate(seed) 134 | } 135 | 136 | fn decode_session_keys( 137 | encoded: Vec, 138 | ) -> Option, KeyTypeId)>> { 139 | SessionKeys::decode_into_raw_public_keys(&encoded) 140 | } 141 | } 142 | 143 | impl sp_consensus_grandpa::GrandpaApi for Runtime { 144 | fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList { 145 | Grandpa::grandpa_authorities() 146 | } 147 | 148 | fn current_set_id() -> sp_consensus_grandpa::SetId { 149 | Grandpa::current_set_id() 150 | } 151 | 152 | fn submit_report_equivocation_unsigned_extrinsic( 153 | _equivocation_proof: sp_consensus_grandpa::EquivocationProof< 154 | ::Hash, 155 | NumberFor, 156 | >, 157 | _key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof, 158 | ) -> Option<()> { 159 | None 160 | } 161 | 162 | fn generate_key_ownership_proof( 163 | _set_id: sp_consensus_grandpa::SetId, 164 | _authority_id: GrandpaId, 165 | ) -> Option { 166 | // NOTE: this is the only implementation possible since we've 167 | // defined our key owner proof type as a bottom type (i.e. a type 168 | // with no values). 169 | None 170 | } 171 | } 172 | 173 | impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { 174 | fn account_nonce(account: AccountId) -> Nonce { 175 | System::account_nonce(account) 176 | } 177 | } 178 | 179 | impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { 180 | fn query_info( 181 | uxt: ::Extrinsic, 182 | len: u32, 183 | ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { 184 | TransactionPayment::query_info(uxt, len) 185 | } 186 | fn query_fee_details( 187 | uxt: ::Extrinsic, 188 | len: u32, 189 | ) -> pallet_transaction_payment::FeeDetails { 190 | TransactionPayment::query_fee_details(uxt, len) 191 | } 192 | fn query_weight_to_fee(weight: Weight) -> Balance { 193 | TransactionPayment::weight_to_fee(weight) 194 | } 195 | fn query_length_to_fee(length: u32) -> Balance { 196 | TransactionPayment::length_to_fee(length) 197 | } 198 | } 199 | 200 | impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi 201 | for Runtime 202 | { 203 | fn query_call_info( 204 | call: RuntimeCall, 205 | len: u32, 206 | ) -> pallet_transaction_payment::RuntimeDispatchInfo { 207 | TransactionPayment::query_call_info(call, len) 208 | } 209 | fn query_call_fee_details( 210 | call: RuntimeCall, 211 | len: u32, 212 | ) -> pallet_transaction_payment::FeeDetails { 213 | TransactionPayment::query_call_fee_details(call, len) 214 | } 215 | fn query_weight_to_fee(weight: Weight) -> Balance { 216 | TransactionPayment::weight_to_fee(weight) 217 | } 218 | fn query_length_to_fee(length: u32) -> Balance { 219 | TransactionPayment::length_to_fee(length) 220 | } 221 | } 222 | 223 | #[cfg(feature = "runtime-benchmarks")] 224 | impl frame_benchmarking::Benchmark for Runtime { 225 | fn benchmark_metadata(extra: bool) -> ( 226 | Vec, 227 | Vec, 228 | ) { 229 | use frame_benchmarking::{baseline, BenchmarkList}; 230 | use frame_support::traits::StorageInfoTrait; 231 | use frame_system_benchmarking::Pallet as SystemBench; 232 | use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; 233 | use baseline::Pallet as BaselineBench; 234 | use super::*; 235 | 236 | let mut list = Vec::::new(); 237 | list_benchmarks!(list, extra); 238 | 239 | let storage_info = AllPalletsWithSystem::storage_info(); 240 | 241 | (list, storage_info) 242 | } 243 | 244 | #[allow(non_local_definitions)] 245 | fn dispatch_benchmark( 246 | config: frame_benchmarking::BenchmarkConfig 247 | ) -> Result, alloc::string::String> { 248 | use frame_benchmarking::{baseline, BenchmarkBatch}; 249 | use sp_storage::TrackedStorageKey; 250 | use frame_system_benchmarking::Pallet as SystemBench; 251 | use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; 252 | use baseline::Pallet as BaselineBench; 253 | use super::*; 254 | 255 | impl frame_system_benchmarking::Config for Runtime {} 256 | impl baseline::Config for Runtime {} 257 | 258 | use frame_support::traits::WhitelistedStorageKeys; 259 | let whitelist: Vec = AllPalletsWithSystem::whitelisted_storage_keys(); 260 | 261 | let mut batches = Vec::::new(); 262 | let params = (&config, &whitelist); 263 | add_benchmarks!(params, batches); 264 | 265 | Ok(batches) 266 | } 267 | } 268 | 269 | #[cfg(feature = "try-runtime")] 270 | impl frame_try_runtime::TryRuntime for Runtime { 271 | fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { 272 | // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to 273 | // have a backtrace here. If any of the pre/post migration checks fail, we shall stop 274 | // right here and right now. 275 | let weight = Executive::try_runtime_upgrade(checks).unwrap(); 276 | (weight, super::configs::RuntimeBlockWeights::get().max_block) 277 | } 278 | 279 | fn execute_block( 280 | block: Block, 281 | state_root_check: bool, 282 | signature_check: bool, 283 | select: frame_try_runtime::TryStateSelect 284 | ) -> Weight { 285 | // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to 286 | // have a backtrace here. 287 | Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed") 288 | } 289 | } 290 | 291 | impl sp_genesis_builder::GenesisBuilder for Runtime { 292 | fn build_state(config: Vec) -> sp_genesis_builder::Result { 293 | build_state::(config) 294 | } 295 | 296 | fn get_preset(id: &Option) -> Option> { 297 | get_preset::(id, crate::genesis_config_presets::get_preset) 298 | } 299 | 300 | fn preset_names() -> Vec { 301 | crate::genesis_config_presets::preset_names() 302 | } 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /node/src/service.rs: -------------------------------------------------------------------------------- 1 | //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. 2 | 3 | use futures::FutureExt; 4 | use sc_client_api::{Backend, BlockBackend}; 5 | use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; 6 | use sc_consensus_grandpa::SharedVoterState; 7 | use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncConfig}; 8 | use sc_telemetry::{Telemetry, TelemetryWorker}; 9 | use sc_transaction_pool_api::OffchainTransactionPoolFactory; 10 | use solochain_template_runtime::{self, apis::RuntimeApi, opaque::Block}; 11 | use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; 12 | use std::{sync::Arc, time::Duration}; 13 | 14 | pub(crate) type FullClient = sc_service::TFullClient< 15 | Block, 16 | RuntimeApi, 17 | sc_executor::WasmExecutor, 18 | >; 19 | type FullBackend = sc_service::TFullBackend; 20 | type FullSelectChain = sc_consensus::LongestChain; 21 | 22 | /// The minimum period of blocks on which justifications will be 23 | /// imported and generated. 24 | const GRANDPA_JUSTIFICATION_PERIOD: u32 = 512; 25 | 26 | pub type Service = sc_service::PartialComponents< 27 | FullClient, 28 | FullBackend, 29 | FullSelectChain, 30 | sc_consensus::DefaultImportQueue, 31 | sc_transaction_pool::TransactionPoolHandle, 32 | ( 33 | sc_consensus_grandpa::GrandpaBlockImport, 34 | sc_consensus_grandpa::LinkHalf, 35 | Option, 36 | ), 37 | >; 38 | 39 | pub fn new_partial(config: &Configuration) -> Result { 40 | let telemetry = config 41 | .telemetry_endpoints 42 | .clone() 43 | .filter(|x| !x.is_empty()) 44 | .map(|endpoints| -> Result<_, sc_telemetry::Error> { 45 | let worker = TelemetryWorker::new(16)?; 46 | let telemetry = worker.handle().new_telemetry(endpoints); 47 | Ok((worker, telemetry)) 48 | }) 49 | .transpose()?; 50 | 51 | let executor = sc_service::new_wasm_executor::(&config.executor); 52 | let (client, backend, keystore_container, task_manager) = 53 | sc_service::new_full_parts::( 54 | config, 55 | telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), 56 | executor, 57 | )?; 58 | let client = Arc::new(client); 59 | 60 | let telemetry = telemetry.map(|(worker, telemetry)| { 61 | task_manager.spawn_handle().spawn("telemetry", None, worker.run()); 62 | telemetry 63 | }); 64 | 65 | let select_chain = sc_consensus::LongestChain::new(backend.clone()); 66 | 67 | let transaction_pool = Arc::from( 68 | sc_transaction_pool::Builder::new( 69 | task_manager.spawn_essential_handle(), 70 | client.clone(), 71 | config.role.is_authority().into(), 72 | ) 73 | .with_options(config.transaction_pool.clone()) 74 | .with_prometheus(config.prometheus_registry()) 75 | .build(), 76 | ); 77 | 78 | let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( 79 | client.clone(), 80 | GRANDPA_JUSTIFICATION_PERIOD, 81 | &client, 82 | select_chain.clone(), 83 | telemetry.as_ref().map(|x| x.handle()), 84 | )?; 85 | 86 | let cidp_client = client.clone(); 87 | let import_queue = 88 | sc_consensus_aura::import_queue::(ImportQueueParams { 89 | block_import: grandpa_block_import.clone(), 90 | justification_import: Some(Box::new(grandpa_block_import.clone())), 91 | client: client.clone(), 92 | create_inherent_data_providers: move |parent_hash, _| { 93 | let cidp_client = cidp_client.clone(); 94 | async move { 95 | let slot_duration = sc_consensus_aura::standalone::slot_duration_at( 96 | &*cidp_client, 97 | parent_hash, 98 | )?; 99 | let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); 100 | 101 | let slot = 102 | sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( 103 | *timestamp, 104 | slot_duration, 105 | ); 106 | 107 | Ok((slot, timestamp)) 108 | } 109 | }, 110 | spawner: &task_manager.spawn_essential_handle(), 111 | registry: config.prometheus_registry(), 112 | check_for_equivocation: Default::default(), 113 | telemetry: telemetry.as_ref().map(|x| x.handle()), 114 | compatibility_mode: Default::default(), 115 | })?; 116 | 117 | Ok(sc_service::PartialComponents { 118 | client, 119 | backend, 120 | task_manager, 121 | import_queue, 122 | keystore_container, 123 | select_chain, 124 | transaction_pool, 125 | other: (grandpa_block_import, grandpa_link, telemetry), 126 | }) 127 | } 128 | 129 | /// Builds a new service for a full client. 130 | pub fn new_full< 131 | N: sc_network::NetworkBackend::Hash>, 132 | >( 133 | config: Configuration, 134 | ) -> Result { 135 | let sc_service::PartialComponents { 136 | client, 137 | backend, 138 | mut task_manager, 139 | import_queue, 140 | keystore_container, 141 | select_chain, 142 | transaction_pool, 143 | other: (block_import, grandpa_link, mut telemetry), 144 | } = new_partial(&config)?; 145 | 146 | let mut net_config = sc_network::config::FullNetworkConfiguration::< 147 | Block, 148 | ::Hash, 149 | N, 150 | >::new(&config.network, config.prometheus_registry().cloned()); 151 | let metrics = N::register_notification_metrics(config.prometheus_registry()); 152 | 153 | let peer_store_handle = net_config.peer_store_handle(); 154 | let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name( 155 | &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), 156 | &config.chain_spec, 157 | ); 158 | let (grandpa_protocol_config, grandpa_notification_service) = 159 | sc_consensus_grandpa::grandpa_peers_set_config::<_, N>( 160 | grandpa_protocol_name.clone(), 161 | metrics.clone(), 162 | peer_store_handle, 163 | ); 164 | net_config.add_notification_protocol(grandpa_protocol_config); 165 | 166 | let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( 167 | backend.clone(), 168 | grandpa_link.shared_authority_set().clone(), 169 | Vec::default(), 170 | )); 171 | 172 | let (network, system_rpc_tx, tx_handler_controller, sync_service) = 173 | sc_service::build_network(sc_service::BuildNetworkParams { 174 | config: &config, 175 | net_config, 176 | client: client.clone(), 177 | transaction_pool: transaction_pool.clone(), 178 | spawn_handle: task_manager.spawn_handle(), 179 | import_queue, 180 | block_announce_validator_builder: None, 181 | warp_sync_config: Some(WarpSyncConfig::WithProvider(warp_sync)), 182 | block_relay: None, 183 | metrics, 184 | })?; 185 | 186 | if config.offchain_worker.enabled { 187 | let offchain_workers = 188 | sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { 189 | runtime_api_provider: client.clone(), 190 | is_validator: config.role.is_authority(), 191 | keystore: Some(keystore_container.keystore()), 192 | offchain_db: backend.offchain_storage(), 193 | transaction_pool: Some(OffchainTransactionPoolFactory::new( 194 | transaction_pool.clone(), 195 | )), 196 | network_provider: Arc::new(network.clone()), 197 | enable_http_requests: true, 198 | custom_extensions: |_| vec![], 199 | })?; 200 | task_manager.spawn_handle().spawn( 201 | "offchain-workers-runner", 202 | "offchain-worker", 203 | offchain_workers.run(client.clone(), task_manager.spawn_handle()).boxed(), 204 | ); 205 | } 206 | 207 | let role = config.role; 208 | let force_authoring = config.force_authoring; 209 | let backoff_authoring_blocks: Option<()> = None; 210 | let name = config.network.node_name.clone(); 211 | let enable_grandpa = !config.disable_grandpa; 212 | let prometheus_registry = config.prometheus_registry().cloned(); 213 | 214 | let rpc_extensions_builder = { 215 | let client = client.clone(); 216 | let pool = transaction_pool.clone(); 217 | 218 | Box::new(move |_| { 219 | let deps = crate::rpc::FullDeps { client: client.clone(), pool: pool.clone() }; 220 | crate::rpc::create_full(deps).map_err(Into::into) 221 | }) 222 | }; 223 | 224 | let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { 225 | network: Arc::new(network.clone()), 226 | client: client.clone(), 227 | keystore: keystore_container.keystore(), 228 | task_manager: &mut task_manager, 229 | transaction_pool: transaction_pool.clone(), 230 | rpc_builder: rpc_extensions_builder, 231 | backend, 232 | system_rpc_tx, 233 | tx_handler_controller, 234 | sync_service: sync_service.clone(), 235 | config, 236 | telemetry: telemetry.as_mut(), 237 | })?; 238 | 239 | if role.is_authority() { 240 | let proposer_factory = sc_basic_authorship::ProposerFactory::new( 241 | task_manager.spawn_handle(), 242 | client.clone(), 243 | transaction_pool.clone(), 244 | prometheus_registry.as_ref(), 245 | telemetry.as_ref().map(|x| x.handle()), 246 | ); 247 | 248 | let slot_duration = sc_consensus_aura::slot_duration(&*client)?; 249 | 250 | let aura = sc_consensus_aura::start_aura::( 251 | StartAuraParams { 252 | slot_duration, 253 | client, 254 | select_chain, 255 | block_import, 256 | proposer_factory, 257 | create_inherent_data_providers: move |_, ()| async move { 258 | let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); 259 | 260 | let slot = 261 | sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( 262 | *timestamp, 263 | slot_duration, 264 | ); 265 | 266 | Ok((slot, timestamp)) 267 | }, 268 | force_authoring, 269 | backoff_authoring_blocks, 270 | keystore: keystore_container.keystore(), 271 | sync_oracle: sync_service.clone(), 272 | justification_sync_link: sync_service.clone(), 273 | block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), 274 | max_block_proposal_slot_portion: None, 275 | telemetry: telemetry.as_ref().map(|x| x.handle()), 276 | compatibility_mode: Default::default(), 277 | }, 278 | )?; 279 | 280 | // the AURA authoring task is considered essential, i.e. if it 281 | // fails we take down the service with it. 282 | task_manager 283 | .spawn_essential_handle() 284 | .spawn_blocking("aura", Some("block-authoring"), aura); 285 | } 286 | 287 | if enable_grandpa { 288 | // if the node isn't actively participating in consensus then it doesn't 289 | // need a keystore, regardless of which protocol we use below. 290 | let keystore = if role.is_authority() { Some(keystore_container.keystore()) } else { None }; 291 | 292 | let grandpa_config = sc_consensus_grandpa::Config { 293 | // FIXME #1578 make this available through chainspec 294 | gossip_duration: Duration::from_millis(333), 295 | justification_generation_period: GRANDPA_JUSTIFICATION_PERIOD, 296 | name: Some(name), 297 | observer_enabled: false, 298 | keystore, 299 | local_role: role, 300 | telemetry: telemetry.as_ref().map(|x| x.handle()), 301 | protocol_name: grandpa_protocol_name, 302 | }; 303 | 304 | // start the full GRANDPA voter 305 | // NOTE: non-authorities could run the GRANDPA observer protocol, but at 306 | // this point the full voter should provide better guarantees of block 307 | // and vote data availability than the observer. The observer has not 308 | // been tested extensively yet and having most nodes in a network run it 309 | // could lead to finality stalls. 310 | let grandpa_config = sc_consensus_grandpa::GrandpaParams { 311 | config: grandpa_config, 312 | link: grandpa_link, 313 | network, 314 | sync: Arc::new(sync_service), 315 | notification_service: grandpa_notification_service, 316 | voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(), 317 | prometheus_registry, 318 | shared_voter_state: SharedVoterState::empty(), 319 | telemetry: telemetry.as_ref().map(|x| x.handle()), 320 | offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool), 321 | }; 322 | 323 | // the GRANDPA voter task is considered infallible, i.e. 324 | // if it fails we take down the service with it. 325 | task_manager.spawn_essential_handle().spawn_blocking( 326 | "grandpa-voter", 327 | None, 328 | sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?, 329 | ); 330 | } 331 | 332 | Ok(task_manager) 333 | } 334 | --------------------------------------------------------------------------------