From 73eb8d6efa41729c1ad4d4ac49331a04d61cecd3 Mon Sep 17 00:00:00 2001 From: ajaykumargdr Date: Wed, 17 Jan 2024 18:41:52 +0530 Subject: [PATCH 1/5] chore: Add guessing random number substrate custom blockchain code --- .../Cargo.toml | 8 + .../Containerfile | 31 + .../LICENSE | 16 + .../README.md | 164 +++++ .../node/Cargo.toml | 80 +++ .../node/build.rs | 7 + .../node/src/benchmarking.rs | 161 +++++ .../node/src/chain_spec.rs | 158 +++++ .../node/src/cli.rs | 54 ++ .../node/src/command.rs | 212 +++++++ .../node/src/lib.rs | 3 + .../node/src/main.rs | 14 + .../node/src/rpc.rs | 57 ++ .../node/src/service.rs | 331 ++++++++++ .../pallets/template/Cargo.toml | 39 ++ .../pallets/template/README.md | 1 + .../pallets/template/src/lib.rs | 118 ++++ .../runtime/Cargo.toml | 115 ++++ .../runtime/build.rs | 10 + .../runtime/src/lib.rs | 569 ++++++++++++++++++ .../rust-toolchain.toml | 14 + .../rustfmt.toml | 23 + .../scripts/init.sh | 12 + .../shell.nix | 35 ++ 24 files changed, 2232 insertions(+) create mode 100644 guessing-random-number-substrate-custom-blockchain/Cargo.toml create mode 100644 guessing-random-number-substrate-custom-blockchain/Containerfile create mode 100644 guessing-random-number-substrate-custom-blockchain/LICENSE create mode 100644 guessing-random-number-substrate-custom-blockchain/README.md create mode 100644 guessing-random-number-substrate-custom-blockchain/node/Cargo.toml create mode 100644 guessing-random-number-substrate-custom-blockchain/node/build.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/benchmarking.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/chain_spec.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/cli.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/command.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/lib.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/main.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/rpc.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/service.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/pallets/template/Cargo.toml create mode 100644 guessing-random-number-substrate-custom-blockchain/pallets/template/README.md create mode 100644 guessing-random-number-substrate-custom-blockchain/pallets/template/src/lib.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/runtime/Cargo.toml create mode 100644 guessing-random-number-substrate-custom-blockchain/runtime/build.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/runtime/src/lib.rs create mode 100644 guessing-random-number-substrate-custom-blockchain/rust-toolchain.toml create mode 100644 guessing-random-number-substrate-custom-blockchain/rustfmt.toml create mode 100755 guessing-random-number-substrate-custom-blockchain/scripts/init.sh create mode 100644 guessing-random-number-substrate-custom-blockchain/shell.nix diff --git a/guessing-random-number-substrate-custom-blockchain/Cargo.toml b/guessing-random-number-substrate-custom-blockchain/Cargo.toml new file mode 100644 index 0000000..538fd8d --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/Cargo.toml @@ -0,0 +1,8 @@ +[workspace] +members = [ + "node", + "pallets/template", + "runtime", +] +[profile.release] +panic = "unwind" diff --git a/guessing-random-number-substrate-custom-blockchain/Containerfile b/guessing-random-number-substrate-custom-blockchain/Containerfile new file mode 100644 index 0000000..01a4a54 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/Containerfile @@ -0,0 +1,31 @@ +FROM docker.io/library/ubuntu:22.04 + +# show backtraces +ENV RUST_BACKTRACE 1 + +# install tools and dependencies +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + ca-certificates && \ +# apt cleanup + apt-get autoremove -y && \ + apt-get clean && \ + find /var/lib/apt/lists/ -type f -not -name lock -delete; \ +# add user and link ~/.local/share/polkadot to /data + useradd -m -u 1000 -U -s /bin/sh -d /polkadot polkadot && \ + mkdir -p /data /polkadot/.local/share && \ + chown -R polkadot:polkadot /data && \ + ln -s /data /polkadot/.local/share/node-template + +USER polkadot + +# copy the compiled binary to the container +COPY --chown=polkadot:polkadot --chmod=774 node-template /usr/bin/node-template + +# check if executable works in this container +RUN /usr/bin/node-template --version + +# ws_port +EXPOSE 9930 9333 9944 30333 30334 + +CMD ["/usr/bin/node-template"] diff --git a/guessing-random-number-substrate-custom-blockchain/LICENSE b/guessing-random-number-substrate-custom-blockchain/LICENSE new file mode 100644 index 0000000..ffa0b3f --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/LICENSE @@ -0,0 +1,16 @@ +MIT No Attribution + +Copyright Parity Technologies (UK) Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/guessing-random-number-substrate-custom-blockchain/README.md b/guessing-random-number-substrate-custom-blockchain/README.md new file mode 100644 index 0000000..337faca --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/README.md @@ -0,0 +1,164 @@ +# Substrate Node Template + +A fresh [Substrate](https://substrate.io/) node, ready for hacking :rocket: + +A standalone version of this template is available for each release of Polkadot in the [Substrate Developer Hub Parachain Template](https://github.com/substrate-developer-hub/substrate-parachain-template/) repository. +The parachain template is generated directly at each Polkadot release branch from the [Node Template in Substrate](https://github.com/paritytech/substrate/tree/master/bin/node-template) upstream + +It is usually best to use the stand-alone version to start a new project. +All bugs, suggestions, and feature requests should be made upstream in the [Substrate](https://github.com/paritytech/substrate/tree/master/bin/node-template) repository. + +## Getting Started + +Depending on your operating system and Rust version, there might be additional packages required to compile this template. +Check the [Install](https://docs.substrate.io/install/) instructions for your platform for the most common dependencies. +Alternatively, you can use one of the [alternative installation](#alternatives-installations) options. + +### Build + +Use the following command to build the node without launching it: + +```sh +cargo build --release +``` + +### Embedded Docs + +After you build the project, you can use the following command to explore its parameters and subcommands: + +```sh +./target/release/node-template -h +``` + +You can generate and view the [Rust Docs](https://doc.rust-lang.org/cargo/commands/cargo-doc.html) for this template with this command: + +```sh +cargo +nightly doc --open +``` + +### Single-Node Development Chain + +The following command starts a single-node development chain that doesn't persist state: + +```sh +./target/release/node-template --dev +``` + +To purge the development chain's state, run the following command: + +```sh +./target/release/node-template purge-chain --dev +``` + +To start the development chain with detailed logging, run the following command: + +```sh +RUST_BACKTRACE=1 ./target/release/node-template -ldebug --dev +``` + +Development chains: + +- Maintain state in a `tmp` folder while the node is running. +- Use the **Alice** and **Bob** accounts as default validator authorities. +- Use the **Alice** account as the default `sudo` account. +- Are preconfigured with a genesis state (`/node/src/chain_spec.rs`) that includes several prefunded development accounts. + + +To persist chain state between runs, specify a base path by running a command similar to the following: + +```sh +// Create a folder to use as the db base path +$ mkdir my-chain-state + +// Use of that folder to store the chain state +$ ./target/release/node-template --dev --base-path ./my-chain-state/ + +// Check the folder structure created inside the base path after running the chain +$ ls ./my-chain-state +chains +$ ls ./my-chain-state/chains/ +dev +$ ls ./my-chain-state/chains/dev +db keystore network +``` + +### Connect with Polkadot-JS Apps Front-End + +After you start the node template locally, you can interact with it using the hosted version of the [Polkadot/Substrate Portal](https://polkadot.js.org/apps/#/explorer?rpc=ws://localhost:9944) front-end by connecting to the local node endpoint. +A hosted version is also available on [IPFS (redirect) here](https://dotapps.io/) or [IPNS (direct) here](ipns://dotapps.io/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/explorer). +You can also find the source code and instructions for hosting your own instance on the [polkadot-js/apps](https://github.com/polkadot-js/apps) repository. + +### Multi-Node Local Testnet + +If you want to see the multi-node consensus algorithm in action, see [Simulate a network](https://docs.substrate.io/tutorials/build-a-blockchain/simulate-network/). + +## Template Structure + +A Substrate project such as this consists of a number of components that are spread across a few directories. + +### Node + +A blockchain node is an application that allows users to participate in a blockchain network. +Substrate-based blockchain nodes expose a number of capabilities: + +- Networking: Substrate nodes use the [`libp2p`](https://libp2p.io/) networking stack to allow the + nodes in the network to communicate with one another. +- Consensus: Blockchains must have a way to come to [consensus](https://docs.substrate.io/fundamentals/consensus/) on the state of the network. + Substrate makes it possible to supply custom consensus engines and also ships with several consensus mechanisms that have been built on top of [Web3 Foundation research](https://research.web3.foundation/en/latest/polkadot/NPoS/index.html). +- RPC Server: A remote procedure call (RPC) server is used to interact with Substrate nodes. + +There are several files in the `node` directory. +Take special note of the following: + +- [`chain_spec.rs`](./node/src/chain_spec.rs): A [chain specification](https://docs.substrate.io/build/chain-spec/) is a source code file that defines a Substrate chain's initial (genesis) state. + Chain specifications are useful for development and testing, and critical when architecting the launch of a production chain. + Take note of the `development_config` and `testnet_genesis` functions,. + These functions are used to define the genesis state for the local development chain configuration. + These functions identify some [well-known accounts](https://docs.substrate.io/reference/command-line-tools/subkey/) and use them to configure the blockchain's initial state. +- [`service.rs`](./node/src/service.rs): This file defines the node implementation. + Take note of the libraries that this file imports and the names of the functions it invokes. + In particular, there are references to consensus-related topics, such as the [block finalization and forks](https://docs.substrate.io/fundamentals/consensus/#finalization-and-forks) and other [consensus mechanisms](https://docs.substrate.io/fundamentals/consensus/#default-consensus-models) such as Aura for block authoring and GRANDPA for finality. + + + +### Runtime + +In Substrate, the terms "runtime" and "state transition function" are analogous. +Both terms refer to the core logic of the blockchain that is responsible for validating blocks and executing the state changes they define. +The Substrate project in this repository uses [FRAME](https://docs.substrate.io/learn/runtime-development/#frame) to construct a blockchain runtime. +FRAME allows runtime developers to declare domain-specific logic in modules called "pallets". +At the heart of FRAME is a helpful [macro language](https://docs.substrate.io/reference/frame-macros/) that makes it easy to create pallets and flexibly compose them to create blockchains that can address [a variety of needs](https://substrate.io/ecosystem/projects/). + +Review the [FRAME runtime implementation](./runtime/src/lib.rs) included in this template and note the following: + +- This file configures several pallets to include in the runtime. + Each pallet configuration is defined by a code block that begins with `impl $PALLET_NAME::Config for Runtime`. +- The pallets are composed into a single runtime by way of the [`construct_runtime!`](https://paritytech.github.io/substrate/master/frame_support/macro.construct_runtime.html) macro, which is part of the [core FRAME pallet library](https://docs.substrate.io/reference/frame-pallets/#system-pallets). + +### Pallets + +The runtime in this project is constructed using many FRAME pallets that ship with [the Substrate repository](https://github.com/paritytech/substrate/tree/master/frame) and a template pallet that is [defined in the `pallets`](./pallets/template/src/lib.rs) directory. + +A FRAME pallet is comprised of a number of blockchain primitives, including: + +- Storage: FRAME defines a rich set of powerful [storage abstractions](https://docs.substrate.io/build/runtime-storage/) that makes it easy to use Substrate's efficient key-value database to manage the evolving state of a blockchain. +- Dispatchables: FRAME pallets define special types of functions that can be invoked (dispatched) from outside of the runtime in order to update its state. +- Events: Substrate uses [events](https://docs.substrate.io/build/events-and-errors/) to notify users of significant state changes. +- Errors: When a dispatchable fails, it returns an error. + +Each pallet has its own `Config` trait which serves as a configuration interface to generically define the types and parameters it depends on. + +## Alternatives Installations + +Instead of installing dependencies and building this source directly, consider the following alternatives. + +### Nix + +Install [nix](https://nixos.org/) and +[nix-direnv](https://github.com/nix-community/nix-direnv) for a fully plug-and-play +experience for setting up the development environment. +To get all the correct dependencies, activate direnv `direnv allow`. + +### Docker + +Please follow the [Substrate Docker instructions here](https://github.com/paritytech/substrate/blob/master/docker/README.md) to build the Docker container with the Substrate Node Template binary. diff --git a/guessing-random-number-substrate-custom-blockchain/node/Cargo.toml b/guessing-random-number-substrate-custom-blockchain/node/Cargo.toml new file mode 100644 index 0000000..01ff221 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/node/Cargo.toml @@ -0,0 +1,80 @@ +[package] +name = "node-template" +version = "4.0.0-dev" +description = "A fresh FRAME-based Substrate node, ready for hacking." +authors = ["Substrate DevHub "] +homepage = "https://substrate.io/" +edition = "2021" +license = "MIT-0" +publish = false +repository = "https://github.com/substrate-developer-hub/substrate-node-template/" +build = "build.rs" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[[bin]] +name = "node-template" + +[dependencies] +clap = { version = "4.4.2", features = ["derive"] } +futures = { version = "0.3.21", features = ["thread-pool"]} + +sc-cli = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-core = { version = "21.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-executor = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-network = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-service = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-telemetry = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-transaction-pool = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-transaction-pool-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-offchain = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-statement-store = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-consensus-aura = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-consensus-aura = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-consensus = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-consensus-grandpa = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-consensus-grandpa = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-client-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-runtime = { version = "24.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-io = { version = "23.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-timestamp = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-inherents = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-keyring = { version = "24.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-system = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +# These dependencies are used for the node template's RPCs +jsonrpsee = { version = "0.16.2", features = ["server"] } +sp-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-rpc-api = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-block-builder = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sc-basic-authorship = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +substrate-frame-rpc-system = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +pallet-transaction-payment-rpc = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +# These dependencies are used for runtime benchmarking +frame-benchmarking = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-benchmarking-cli = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +# Local Dependencies +node-template-runtime = { version = "4.0.0-dev", path = "../runtime" } + +# CLI-specific dependencies +try-runtime-cli = { version = "0.10.0-dev", optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +[build-dependencies] +substrate-build-script-utils = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +[features] +default = [] +# Dependencies that are only required if runtime benchmarking should be build. +runtime-benchmarks = [ + "node-template-runtime/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-benchmarking-cli/runtime-benchmarks", +] +# Enable features that allow the runtime to be tried and debugged. Name might be subject to change +# in the near future. +try-runtime = ["node-template-runtime/try-runtime", "try-runtime-cli/try-runtime"] diff --git a/guessing-random-number-substrate-custom-blockchain/node/build.rs b/guessing-random-number-substrate-custom-blockchain/node/build.rs new file mode 100644 index 0000000..e3bfe31 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/node/build.rs @@ -0,0 +1,7 @@ +use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; + +fn main() { + generate_cargo_keys(); + + rerun_if_git_head_changed(); +} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/benchmarking.rs b/guessing-random-number-substrate-custom-blockchain/node/src/benchmarking.rs new file mode 100644 index 0000000..6e29ad1 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/node/src/benchmarking.rs @@ -0,0 +1,161 @@ +//! Setup code for [`super::command`] which would otherwise bloat that module. +//! +//! Should only be used for benchmarking as it may break in other contexts. + +use crate::service::FullClient; + +use node_template_runtime as runtime; +use runtime::{AccountId, Balance, BalancesCall, SystemCall}; +use sc_cli::Result; +use sc_client_api::BlockBackend; +use sp_core::{Encode, Pair}; +use sp_inherents::{InherentData, InherentDataProvider}; +use sp_keyring::Sr25519Keyring; +use sp_runtime::{OpaqueExtrinsic, SaturatedConversion}; + +use std::{sync::Arc, time::Duration}; + +/// Generates extrinsics for the `benchmark overhead` command. +/// +/// Note: Should only be used for benchmarking. +pub struct RemarkBuilder { + client: Arc, +} + +impl RemarkBuilder { + /// Creates a new [`Self`] from the given client. + pub fn new(client: Arc) -> Self { + Self { client } + } +} + +impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder { + fn pallet(&self) -> &str { + "system" + } + + fn extrinsic(&self) -> &str { + "remark" + } + + fn build(&self, nonce: u32) -> std::result::Result { + let acc = Sr25519Keyring::Bob.pair(); + let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( + self.client.as_ref(), + acc, + SystemCall::remark { remark: vec![] }.into(), + nonce, + ) + .into(); + + Ok(extrinsic) + } +} + +/// Generates `Balances::TransferKeepAlive` extrinsics for the benchmarks. +/// +/// Note: Should only be used for benchmarking. +pub struct TransferKeepAliveBuilder { + client: Arc, + dest: AccountId, + value: Balance, +} + +impl TransferKeepAliveBuilder { + /// Creates a new [`Self`] from the given client. + pub fn new(client: Arc, dest: AccountId, value: Balance) -> Self { + Self { client, dest, value } + } +} + +impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { + fn pallet(&self) -> &str { + "balances" + } + + fn extrinsic(&self) -> &str { + "transfer_keep_alive" + } + + fn build(&self, nonce: u32) -> std::result::Result { + let acc = Sr25519Keyring::Bob.pair(); + let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( + self.client.as_ref(), + acc, + BalancesCall::transfer_keep_alive { dest: self.dest.clone().into(), value: self.value } + .into(), + nonce, + ) + .into(); + + Ok(extrinsic) + } +} + +/// Create a transaction using the given `call`. +/// +/// Note: Should only be used for benchmarking. +pub fn create_benchmark_extrinsic( + client: &FullClient, + sender: sp_core::sr25519::Pair, + call: runtime::RuntimeCall, + nonce: u32, +) -> runtime::UncheckedExtrinsic { + let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); + let best_hash = client.chain_info().best_hash; + let best_block = client.chain_info().best_number; + + let period = runtime::BlockHashCount::get() + .checked_next_power_of_two() + .map(|c| c / 2) + .unwrap_or(2) as u64; + let extra: runtime::SignedExtra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(sp_runtime::generic::Era::mortal( + period, + best_block.saturated_into(), + )), + frame_system::CheckNonce::::from(nonce), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + ); + + let raw_payload = runtime::SignedPayload::from_raw( + call.clone(), + extra.clone(), + ( + (), + runtime::VERSION.spec_version, + runtime::VERSION.transaction_version, + genesis_hash, + best_hash, + (), + (), + (), + ), + ); + let signature = raw_payload.using_encoded(|e| sender.sign(e)); + + runtime::UncheckedExtrinsic::new_signed( + call, + sp_runtime::AccountId32::from(sender.public()).into(), + runtime::Signature::Sr25519(signature), + extra, + ) +} + +/// Generates inherent data for the `benchmark overhead` command. +/// +/// Note: Should only be used for benchmarking. +pub fn inherent_benchmark_data() -> Result { + let mut inherent_data = InherentData::new(); + let d = Duration::from_millis(0); + let timestamp = sp_timestamp::InherentDataProvider::new(d.into()); + + futures::executor::block_on(timestamp.provide_inherent_data(&mut inherent_data)) + .map_err(|e| format!("creating inherent data: {:?}", e))?; + Ok(inherent_data) +} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/chain_spec.rs b/guessing-random-number-substrate-custom-blockchain/node/src/chain_spec.rs new file mode 100644 index 0000000..2cd2d07 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/node/src/chain_spec.rs @@ -0,0 +1,158 @@ +use node_template_runtime::{ + AccountId, AuraConfig, BalancesConfig, GrandpaConfig, RuntimeGenesisConfig, Signature, + SudoConfig, SystemConfig, WASM_BINARY, +}; +use sc_service::ChainType; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_consensus_grandpa::AuthorityId as GrandpaId; +use sp_core::{sr25519, Pair, Public}; +use sp_runtime::traits::{IdentifyAccount, Verify}; + +// The URL for the telemetry server. +// const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; + +/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. +pub type ChainSpec = sc_service::GenericChainSpec; + +/// Generate a crypto pair from seed. +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +type AccountPublic = ::Signer; + +/// Generate an account ID from seed. +pub fn get_account_id_from_seed(seed: &str) -> AccountId +where + AccountPublic: From<::Public>, +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} + +/// Generate an Aura authority key. +pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { + (get_from_seed::(s), get_from_seed::(s)) +} + +pub fn development_config() -> Result { + let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; + + Ok(ChainSpec::from_genesis( + // Name + "Development", + // ID + "dev", + ChainType::Development, + move || { + testnet_genesis( + wasm_binary, + // Initial PoA authorities + vec![authority_keys_from_seed("Alice")], + // Sudo account + get_account_id_from_seed::("Alice"), + // Pre-funded accounts + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + ], + true, + ) + }, + // Bootnodes + vec![], + // Telemetry + None, + // Protocol ID + None, + None, + // Properties + None, + // Extensions + None, + )) +} + +pub fn local_testnet_config() -> Result { + let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; + + Ok(ChainSpec::from_genesis( + // Name + "Local Testnet", + // ID + "local_testnet", + ChainType::Local, + move || { + testnet_genesis( + wasm_binary, + // Initial PoA authorities + vec![authority_keys_from_seed("Alice"), authority_keys_from_seed("Bob")], + // Sudo account + get_account_id_from_seed::("Alice"), + // Pre-funded accounts + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ], + true, + ) + }, + // Bootnodes + vec![], + // Telemetry + None, + // Protocol ID + None, + // Properties + None, + None, + // Extensions + None, + )) +} + +/// Configure initial storage state for FRAME modules. +fn testnet_genesis( + wasm_binary: &[u8], + initial_authorities: Vec<(AuraId, GrandpaId)>, + root_key: AccountId, + endowed_accounts: Vec, + _enable_println: bool, +) -> RuntimeGenesisConfig { + RuntimeGenesisConfig { + system: SystemConfig { + // Add Wasm runtime to storage. + code: wasm_binary.to_vec(), + ..Default::default() + }, + balances: BalancesConfig { + // Configure endowed accounts with initial balance of 1 << 60. + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + }, + aura: AuraConfig { + authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), + }, + grandpa: GrandpaConfig { + authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), + ..Default::default() + }, + sudo: SudoConfig { + // Assign network admin rights. + key: Some(root_key), + }, + transaction_payment: Default::default(), + } +} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/cli.rs b/guessing-random-number-substrate-custom-blockchain/node/src/cli.rs new file mode 100644 index 0000000..15ceaa0 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/node/src/cli.rs @@ -0,0 +1,54 @@ +use sc_cli::RunCmd; + +#[derive(Debug, clap::Parser)] +pub struct Cli { + #[command(subcommand)] + pub subcommand: Option, + + #[clap(flatten)] + pub run: RunCmd, +} + +#[derive(Debug, clap::Subcommand)] +#[allow(clippy::large_enum_variant)] +pub enum Subcommand { + /// Key management cli utilities + #[command(subcommand)] + Key(sc_cli::KeySubcommand), + + /// Build a chain specification. + BuildSpec(sc_cli::BuildSpecCmd), + + /// Validate blocks. + CheckBlock(sc_cli::CheckBlockCmd), + + /// Export blocks. + ExportBlocks(sc_cli::ExportBlocksCmd), + + /// Export the state of a given block into a chain spec. + ExportState(sc_cli::ExportStateCmd), + + /// Import blocks. + ImportBlocks(sc_cli::ImportBlocksCmd), + + /// Remove the whole chain. + PurgeChain(sc_cli::PurgeChainCmd), + + /// Revert the chain to a previous state. + Revert(sc_cli::RevertCmd), + + /// Sub-commands concerned with benchmarking. + #[command(subcommand)] + Benchmark(frame_benchmarking_cli::BenchmarkCmd), + + /// Try some command against runtime state. + #[cfg(feature = "try-runtime")] + TryRuntime(try_runtime_cli::TryRuntimeCmd), + + /// Try some command against runtime state. Note: `try-runtime` feature must be enabled. + #[cfg(not(feature = "try-runtime"))] + TryRuntime, + + /// Db meta columns information. + ChainInfo(sc_cli::ChainInfoCmd), +} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/command.rs b/guessing-random-number-substrate-custom-blockchain/node/src/command.rs new file mode 100644 index 0000000..8fc697b --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/node/src/command.rs @@ -0,0 +1,212 @@ +use crate::{ + benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder}, + chain_spec, + cli::{Cli, Subcommand}, + service, +}; +use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory, SUBSTRATE_REFERENCE_HARDWARE}; +use node_template_runtime::{Block, EXISTENTIAL_DEPOSIT}; +use sc_cli::SubstrateCli; +use sc_service::PartialComponents; +use sp_keyring::Sr25519Keyring; + +#[cfg(feature = "try-runtime")] +use try_runtime_cli::block_building_info::timestamp_with_aura_info; + +impl SubstrateCli for Cli { + fn impl_name() -> String { + "Substrate Node".into() + } + + fn impl_version() -> String { + env!("SUBSTRATE_CLI_IMPL_VERSION").into() + } + + fn description() -> String { + env!("CARGO_PKG_DESCRIPTION").into() + } + + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } + + fn support_url() -> String { + "support.anonymous.an".into() + } + + fn copyright_start_year() -> i32 { + 2017 + } + + fn load_spec(&self, id: &str) -> Result, String> { + Ok(match id { + "dev" => Box::new(chain_spec::development_config()?), + "" | "local" => Box::new(chain_spec::local_testnet_config()?), + path => + Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), + }) + } +} + +/// Parse and run command line arguments +pub fn run() -> sc_cli::Result<()> { + let cli = Cli::from_args(); + + match &cli.subcommand { + Some(Subcommand::Key(cmd)) => cmd.run(&cli), + Some(Subcommand::BuildSpec(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) + }, + Some(Subcommand::CheckBlock(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { client, task_manager, import_queue, .. } = + service::new_partial(&config)?; + Ok((cmd.run(client, import_queue), task_manager)) + }) + }, + Some(Subcommand::ExportBlocks(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; + Ok((cmd.run(client, config.database), task_manager)) + }) + }, + Some(Subcommand::ExportState(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; + Ok((cmd.run(client, config.chain_spec), task_manager)) + }) + }, + Some(Subcommand::ImportBlocks(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { client, task_manager, import_queue, .. } = + service::new_partial(&config)?; + Ok((cmd.run(client, import_queue), task_manager)) + }) + }, + Some(Subcommand::PurgeChain(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.database)) + }, + Some(Subcommand::Revert(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { client, task_manager, backend, .. } = + service::new_partial(&config)?; + let aux_revert = Box::new(|client, _, blocks| { + sc_consensus_grandpa::revert(client, blocks)?; + Ok(()) + }); + Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) + }) + }, + Some(Subcommand::Benchmark(cmd)) => { + let runner = cli.create_runner(cmd)?; + + runner.sync_run(|config| { + // This switch needs to be in the client, since the client decides + // which sub-commands it wants to support. + match cmd { + BenchmarkCmd::Pallet(cmd) => { + if !cfg!(feature = "runtime-benchmarks") { + return Err( + "Runtime benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + .into(), + ) + } + + cmd.run::(config) + }, + BenchmarkCmd::Block(cmd) => { + let PartialComponents { client, .. } = service::new_partial(&config)?; + cmd.run(client) + }, + #[cfg(not(feature = "runtime-benchmarks"))] + BenchmarkCmd::Storage(_) => Err( + "Storage benchmarking can be enabled with `--features runtime-benchmarks`." + .into(), + ), + #[cfg(feature = "runtime-benchmarks")] + BenchmarkCmd::Storage(cmd) => { + let PartialComponents { client, backend, .. } = + service::new_partial(&config)?; + let db = backend.expose_db(); + let storage = backend.expose_storage(); + + cmd.run(config, client, db, storage) + }, + BenchmarkCmd::Overhead(cmd) => { + let PartialComponents { client, .. } = service::new_partial(&config)?; + let ext_builder = RemarkBuilder::new(client.clone()); + + cmd.run( + config, + client, + inherent_benchmark_data()?, + Vec::new(), + &ext_builder, + ) + }, + BenchmarkCmd::Extrinsic(cmd) => { + let PartialComponents { client, .. } = service::new_partial(&config)?; + // Register the *Remark* and *TKA* builders. + let ext_factory = ExtrinsicFactory(vec![ + Box::new(RemarkBuilder::new(client.clone())), + Box::new(TransferKeepAliveBuilder::new( + client.clone(), + Sr25519Keyring::Alice.to_account_id(), + EXISTENTIAL_DEPOSIT, + )), + ]); + + cmd.run(client, inherent_benchmark_data()?, Vec::new(), &ext_factory) + }, + BenchmarkCmd::Machine(cmd) => + cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()), + } + }) + }, + #[cfg(feature = "try-runtime")] + Some(Subcommand::TryRuntime(cmd)) => { + use crate::service::ExecutorDispatch; + use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, NativeExecutionDispatch}; + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + // we don't need any of the components of new_partial, just a runtime, or a task + // manager to do `async_run`. + let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); + let task_manager = + sc_service::TaskManager::new(config.tokio_handle.clone(), registry) + .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; + let info_provider = timestamp_with_aura_info(6000); + + Ok(( + cmd.run::::ExtendHostFunctions, + >, _>(Some(info_provider)), + task_manager, + )) + }) + }, + #[cfg(not(feature = "try-runtime"))] + Some(Subcommand::TryRuntime) => Err("TryRuntime wasn't enabled when building the node. \ + You can enable it with `--features try-runtime`." + .into()), + Some(Subcommand::ChainInfo(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run::(&config)) + }, + None => { + let runner = cli.create_runner(&cli.run)?; + runner.run_node_until_exit(|config| async move { + service::new_full(config).map_err(sc_cli::Error::Service) + }) + }, + } +} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/lib.rs b/guessing-random-number-substrate-custom-blockchain/node/src/lib.rs new file mode 100644 index 0000000..f117b8a --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/node/src/lib.rs @@ -0,0 +1,3 @@ +pub mod chain_spec; +pub mod rpc; +pub mod service; diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/main.rs b/guessing-random-number-substrate-custom-blockchain/node/src/main.rs new file mode 100644 index 0000000..426cbab --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/node/src/main.rs @@ -0,0 +1,14 @@ +//! Substrate Node Template CLI library. +#![warn(missing_docs)] + +mod chain_spec; +#[macro_use] +mod service; +mod benchmarking; +mod cli; +mod command; +mod rpc; + +fn main() -> sc_cli::Result<()> { + command::run() +} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/rpc.rs b/guessing-random-number-substrate-custom-blockchain/node/src/rpc.rs new file mode 100644 index 0000000..f4f1540 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/node/src/rpc.rs @@ -0,0 +1,57 @@ +//! A collection of node-specific RPC methods. +//! Substrate provides the `sc-rpc` crate, which defines the core RPC layer +//! used by Substrate nodes. This file extends those RPC definitions with +//! capabilities that are specific to this project's runtime configuration. + +#![warn(missing_docs)] + +use std::sync::Arc; + +use jsonrpsee::RpcModule; +use node_template_runtime::{opaque::Block, AccountId, Balance, Nonce}; +use sc_transaction_pool_api::TransactionPool; +use sp_api::ProvideRuntimeApi; +use sp_block_builder::BlockBuilder; +use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; + +pub use sc_rpc_api::DenyUnsafe; + +/// Full client dependencies. +pub struct FullDeps { + /// The client instance to use. + pub client: Arc, + /// Transaction pool instance. + pub pool: Arc

, + /// Whether to deny unsafe calls + pub deny_unsafe: DenyUnsafe, +} + +/// Instantiate all full RPC extensions. +pub fn create_full( + deps: FullDeps, +) -> Result, Box> +where + C: ProvideRuntimeApi, + C: HeaderBackend + HeaderMetadata + 'static, + C: Send + Sync + 'static, + C::Api: substrate_frame_rpc_system::AccountNonceApi, + C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, + C::Api: BlockBuilder, + P: TransactionPool + 'static, +{ + use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; + use substrate_frame_rpc_system::{System, SystemApiServer}; + + let mut module = RpcModule::new(()); + let FullDeps { client, pool, deny_unsafe } = deps; + + module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; + module.merge(TransactionPayment::new(client).into_rpc())?; + + // Extend this RPC with a custom API by using the following syntax. + // `YourRpcStruct` should have a reference to a client, which is needed + // to call into the runtime. + // `module.merge(YourRpcTrait::into_rpc(YourRpcStruct::new(ReferenceToClient, ...)))?;` + + Ok(module) +} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/service.rs b/guessing-random-number-substrate-custom-blockchain/node/src/service.rs new file mode 100644 index 0000000..355e24c --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/node/src/service.rs @@ -0,0 +1,331 @@ +//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. + +use futures::FutureExt; +use node_template_runtime::{self, opaque::Block, RuntimeApi}; +use sc_client_api::{Backend, BlockBackend}; +use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; +use sc_consensus_grandpa::SharedVoterState; +pub use sc_executor::NativeElseWasmExecutor; +use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncParams}; +use sc_telemetry::{Telemetry, TelemetryWorker}; +use sc_transaction_pool_api::OffchainTransactionPoolFactory; +use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; +use std::{sync::Arc, time::Duration}; + +// Our native executor instance. +pub struct ExecutorDispatch; + +impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { + /// Only enable the benchmarking host functions when we actually want to benchmark. + #[cfg(feature = "runtime-benchmarks")] + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + /// Otherwise we only use the default Substrate host functions. + #[cfg(not(feature = "runtime-benchmarks"))] + type ExtendHostFunctions = (); + + fn dispatch(method: &str, data: &[u8]) -> Option> { + node_template_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + node_template_runtime::native_version() + } +} + +pub(crate) type FullClient = + sc_service::TFullClient>; +type FullBackend = sc_service::TFullBackend; +type FullSelectChain = sc_consensus::LongestChain; + +#[allow(clippy::type_complexity)] +pub fn new_partial( + config: &Configuration, +) -> Result< + sc_service::PartialComponents< + FullClient, + FullBackend, + FullSelectChain, + sc_consensus::DefaultImportQueue, + sc_transaction_pool::FullPool, + ( + sc_consensus_grandpa::GrandpaBlockImport< + FullBackend, + Block, + FullClient, + FullSelectChain, + >, + sc_consensus_grandpa::LinkHalf, + Option, + ), + >, + ServiceError, +> { + let telemetry = config + .telemetry_endpoints + .clone() + .filter(|x| !x.is_empty()) + .map(|endpoints| -> Result<_, sc_telemetry::Error> { + let worker = TelemetryWorker::new(16)?; + let telemetry = worker.handle().new_telemetry(endpoints); + Ok((worker, telemetry)) + }) + .transpose()?; + + let executor = sc_service::new_native_or_wasm_executor(config); + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; + let client = Arc::new(client); + + let telemetry = telemetry.map(|(worker, telemetry)| { + task_manager.spawn_handle().spawn("telemetry", None, worker.run()); + telemetry + }); + + let select_chain = sc_consensus::LongestChain::new(backend.clone()); + + let transaction_pool = sc_transaction_pool::BasicPool::new_full( + config.transaction_pool.clone(), + config.role.is_authority().into(), + config.prometheus_registry(), + task_manager.spawn_essential_handle(), + client.clone(), + ); + + let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( + client.clone(), + &client, + select_chain.clone(), + telemetry.as_ref().map(|x| x.handle()), + )?; + + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; + + let import_queue = + sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: grandpa_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import.clone())), + client: client.clone(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + }, + spawner: &task_manager.spawn_essential_handle(), + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), + })?; + + Ok(sc_service::PartialComponents { + client, + backend, + task_manager, + import_queue, + keystore_container, + select_chain, + transaction_pool, + other: (grandpa_block_import, grandpa_link, telemetry), + }) +} + +/// Builds a new service for a full client. +pub fn new_full(config: Configuration) -> Result { + let sc_service::PartialComponents { + client, + backend, + mut task_manager, + import_queue, + keystore_container, + select_chain, + transaction_pool, + other: (block_import, grandpa_link, mut telemetry), + } = new_partial(&config)?; + + let mut net_config = sc_network::config::FullNetworkConfiguration::new(&config.network); + + let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name( + &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), + &config.chain_spec, + ); + net_config.add_notification_protocol(sc_consensus_grandpa::grandpa_peers_set_config( + grandpa_protocol_name.clone(), + )); + + let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( + backend.clone(), + grandpa_link.shared_authority_set().clone(), + Vec::default(), + )); + + let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + net_config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + block_announce_validator_builder: None, + warp_sync_params: Some(WarpSyncParams::WithProvider(warp_sync)), + })?; + + if config.offchain_worker.enabled { + task_manager.spawn_handle().spawn( + "offchain-workers-runner", + "offchain-worker", + sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { + runtime_api_provider: client.clone(), + is_validator: config.role.is_authority(), + keystore: Some(keystore_container.keystore()), + offchain_db: backend.offchain_storage(), + transaction_pool: Some(OffchainTransactionPoolFactory::new( + transaction_pool.clone(), + )), + network_provider: network.clone(), + enable_http_requests: true, + custom_extensions: |_| vec![], + }) + .run(client.clone(), task_manager.spawn_handle()) + .boxed(), + ); + } + + let role = config.role.clone(); + let force_authoring = config.force_authoring; + let backoff_authoring_blocks: Option<()> = None; + let name = config.network.node_name.clone(); + let enable_grandpa = !config.disable_grandpa; + let prometheus_registry = config.prometheus_registry().cloned(); + + let rpc_extensions_builder = { + let client = client.clone(); + let pool = transaction_pool.clone(); + + Box::new(move |deny_unsafe, _| { + let deps = + crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; + crate::rpc::create_full(deps).map_err(Into::into) + }) + }; + + let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { + network: network.clone(), + client: client.clone(), + keystore: keystore_container.keystore(), + task_manager: &mut task_manager, + transaction_pool: transaction_pool.clone(), + rpc_builder: rpc_extensions_builder, + backend, + system_rpc_tx, + tx_handler_controller, + sync_service: sync_service.clone(), + config, + telemetry: telemetry.as_mut(), + })?; + + if role.is_authority() { + let proposer_factory = sc_basic_authorship::ProposerFactory::new( + task_manager.spawn_handle(), + client.clone(), + transaction_pool.clone(), + prometheus_registry.as_ref(), + telemetry.as_ref().map(|x| x.handle()), + ); + + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; + + let aura = sc_consensus_aura::start_aura::( + StartAuraParams { + slot_duration, + client, + select_chain, + block_import, + proposer_factory, + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + }, + force_authoring, + backoff_authoring_blocks, + keystore: keystore_container.keystore(), + sync_oracle: sync_service.clone(), + justification_sync_link: sync_service.clone(), + block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + max_block_proposal_slot_portion: None, + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), + }, + )?; + + // the AURA authoring task is considered essential, i.e. if it + // fails we take down the service with it. + task_manager + .spawn_essential_handle() + .spawn_blocking("aura", Some("block-authoring"), aura); + } + + if enable_grandpa { + // if the node isn't actively participating in consensus then it doesn't + // need a keystore, regardless of which protocol we use below. + let keystore = if role.is_authority() { Some(keystore_container.keystore()) } else { None }; + + let grandpa_config = sc_consensus_grandpa::Config { + // FIXME #1578 make this available through chainspec + gossip_duration: Duration::from_millis(333), + justification_period: 512, + name: Some(name), + observer_enabled: false, + keystore, + local_role: role, + telemetry: telemetry.as_ref().map(|x| x.handle()), + protocol_name: grandpa_protocol_name, + }; + + // start the full GRANDPA voter + // NOTE: non-authorities could run the GRANDPA observer protocol, but at + // this point the full voter should provide better guarantees of block + // and vote data availability than the observer. The observer has not + // been tested extensively yet and having most nodes in a network run it + // could lead to finality stalls. + let grandpa_config = sc_consensus_grandpa::GrandpaParams { + config: grandpa_config, + link: grandpa_link, + network, + sync: Arc::new(sync_service), + voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(), + prometheus_registry, + shared_voter_state: SharedVoterState::empty(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool), + }; + + // the GRANDPA voter task is considered infallible, i.e. + // if it fails we take down the service with it. + task_manager.spawn_essential_handle().spawn_blocking( + "grandpa-voter", + None, + sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?, + ); + } + + network_starter.start_network(); + Ok(task_manager) +} diff --git a/guessing-random-number-substrate-custom-blockchain/pallets/template/Cargo.toml b/guessing-random-number-substrate-custom-blockchain/pallets/template/Cargo.toml new file mode 100644 index 0000000..0f01e33 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/pallets/template/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "pallet-template" +version = "4.0.0-dev" +description = "FRAME pallet template for defining custom runtime logic." +authors = ["Substrate DevHub "] +homepage = "https://substrate.io" +edition = "2021" +license = "MIT-0" +publish = false +repository = "https://github.com/substrate-developer-hub/substrate-node-template/" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +[dev-dependencies] +sp-core = { version = "21.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-io = { version = "23.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-runtime = { version = "24.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", +] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] +try-runtime = ["frame-support/try-runtime"] diff --git a/guessing-random-number-substrate-custom-blockchain/pallets/template/README.md b/guessing-random-number-substrate-custom-blockchain/pallets/template/README.md new file mode 100644 index 0000000..d0d5953 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/pallets/template/README.md @@ -0,0 +1 @@ +License: MIT-0 \ No newline at end of file diff --git a/guessing-random-number-substrate-custom-blockchain/pallets/template/src/lib.rs b/guessing-random-number-substrate-custom-blockchain/pallets/template/src/lib.rs new file mode 100644 index 0000000..fb94828 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/pallets/template/src/lib.rs @@ -0,0 +1,118 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; + +#[frame_support::pallet] +pub mod pallet { + + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + // pub use frame_support::traits::Randomness; + + #[pallet::pallet] + // #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + /// Configure the pallet by specifying the parameters and types on which it depends. + #[pallet::config] + pub trait Config: frame_system::Config { + /// Because this pallet emits events, it depends on the runtime's definition of an event. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::storage] + pub(super) type TargetNumber = StorageValue<_, u32, ValueQuery>; + + #[pallet::storage] + pub(super) type Guesses = StorageMap<_, Blake2_128Concat, u32, (T::AccountId, u32)>; + + // Pallets use events to inform users when important changes are made. + // Event documentation should end with an array that provides descriptive names for parameters. + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + TargetNotSet, + + ExactNumber { who: T::AccountId, number: u32 }, + + TargetNumberChanged, + + TargetNumberRemoved, + + GuessedNumber { who: T::AccountId, number: u32 }, + } + + // Errors inform users that something went wrong. + #[pallet::error] + pub enum Error { + TargetNotSet, + + PredecessorNumber, + + SuccessorNumber, + + TooManyTurns, + } + + // Dispatchable functions allow users to interact with the pallet and invoke state changes. + // These functions materialize as "extrinsics", which are often compared to transactions. + // Dispatchable functions must be annotated with a weight and must return a DispatchResult. + + #[pallet::call] + impl Pallet { + #[pallet::weight(0)] + #[pallet::call_index(1)] + pub fn set_target(origin: OriginFor, number: u32) -> DispatchResult { + // Check that the extrinsic was root. + // This function will return an error if the extrinsic is not signed. + ensure_root(origin)?; + Self::deposit_event(Event::TargetNumberChanged); + TargetNumber::::put(number); + + Ok(()) + } + + #[pallet::weight(0)] + #[pallet::call_index(2)] + pub fn check_with(origin: OriginFor, number: u32) -> DispatchResult { + if !TargetNumber::::exists() { + return Err(Error::::TargetNotSet.into()) + } + + // Check that the extrinsic was signed and get the signer. + // This function will return an error if the extrinsic is not signed. + let sender = ensure_signed(origin)?; + + let target = TargetNumber::::get(); + + Self::deposit_event(Event::GuessedNumber { who: sender.clone(), number }); + + if number == target { + Self::deposit_event(Event::ExactNumber { who: sender, number }); + TargetNumber::::kill(); + Self::deposit_event(Event::TargetNumberRemoved); + } else if number < target { + return Err(Error::::PredecessorNumber.into()) + } else { + return Err(Error::::SuccessorNumber.into()) + } + + return Ok(()); + } + + #[pallet::weight(0)] + #[pallet::call_index(3)] + pub fn remove_target(origin: OriginFor) -> DispatchResult { + // Check that the extrinsic was root. + // This function will return an error if the extrinsic is not signed. + ensure_root(origin)?; + ensure!(TargetNumber::::exists(), Error::::TargetNotSet); + + TargetNumber::::kill(); + + Self::deposit_event(Event::TargetNumberRemoved); + Ok(()) + } + } +} diff --git a/guessing-random-number-substrate-custom-blockchain/runtime/Cargo.toml b/guessing-random-number-substrate-custom-blockchain/runtime/Cargo.toml new file mode 100644 index 0000000..5525da8 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/runtime/Cargo.toml @@ -0,0 +1,115 @@ +[package] +name = "node-template-runtime" +version = "4.0.0-dev" +description = "A fresh FRAME-based Substrate node, ready for hacking." +authors = ["Substrate DevHub "] +homepage = "https://substrate.io/" +edition = "2021" +license = "MIT-0" +publish = false +repository = "https://github.com/substrate-developer-hub/substrate-node-template/" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } + +pallet-aura = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +pallet-balances = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +pallet-grandpa = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +pallet-sudo = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-try-runtime = { version = "0.10.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", optional = true , branch = "polkadot-v1.0.0" } +pallet-timestamp = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-executive = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-block-builder = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-consensus-aura = { version = "0.10.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-consensus-grandpa = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-core = { version = "21.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-inherents = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-offchain = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-session = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-std = { version = "8.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-transaction-pool = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-version = { version = "22.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +# Used for the node template's RPCs +frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +# Used for runtime benchmarking +frame-benchmarking = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", optional = true , branch = "polkadot-v1.0.0" } +frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", optional = true , branch = "polkadot-v1.0.0" } + +# Local Dependencies +pallet-template = { version = "4.0.0-dev", default-features = false, path = "../pallets/template" } + +[build-dependencies] +substrate-wasm-builder = { version = "5.0.0-dev", git = "https://github.com/paritytech/substrate.git", optional = true , branch = "polkadot-v1.0.0" } + +[features] +default = ["std"] +std = [ + "frame-try-runtime?/std", + "frame-system-benchmarking?/std", + "frame-benchmarking?/std", + "codec/std", + "scale-info/std", + "frame-executive/std", + "frame-support/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "frame-try-runtime/std", + "pallet-aura/std", + "pallet-balances/std", + "pallet-grandpa/std", + "pallet-sudo/std", + "pallet-template/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-consensus-grandpa/std", + "sp-core/std", + "sp-inherents/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "substrate-wasm-builder", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-grandpa/runtime-benchmarks", + "pallet-sudo/runtime-benchmarks", + "pallet-template/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +try-runtime = [ + "frame-try-runtime/try-runtime", + "frame-executive/try-runtime", + "frame-system/try-runtime", + "frame-support/try-runtime", + "pallet-aura/try-runtime", + "pallet-balances/try-runtime", + "pallet-grandpa/try-runtime", + "pallet-sudo/try-runtime", + "pallet-template/try-runtime", + "pallet-timestamp/try-runtime", + "pallet-transaction-payment/try-runtime", +] diff --git a/guessing-random-number-substrate-custom-blockchain/runtime/build.rs b/guessing-random-number-substrate-custom-blockchain/runtime/build.rs new file mode 100644 index 0000000..c03d618 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/runtime/build.rs @@ -0,0 +1,10 @@ +fn main() { + #[cfg(feature = "std")] + { + substrate_wasm_builder::WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build(); + } +} diff --git a/guessing-random-number-substrate-custom-blockchain/runtime/src/lib.rs b/guessing-random-number-substrate-custom-blockchain/runtime/src/lib.rs new file mode 100644 index 0000000..15ae259 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/runtime/src/lib.rs @@ -0,0 +1,569 @@ +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +use pallet_grandpa::AuthorityId as GrandpaId; +use sp_api::impl_runtime_apis; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{ + AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, One, Verify, + }, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, MultiSignature, +}; +use sp_std::prelude::*; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; + +// A few exports that help ease life for downstream crates. +pub use frame_support::{ + construct_runtime, parameter_types, + traits::{ + ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, KeyOwnerProofSystem, Randomness, + StorageInfo, + }, + weights::{ + constants::{ + BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, + }, + IdentityFee, Weight, + }, + StorageValue, +}; +pub use frame_system::Call as SystemCall; +pub use pallet_balances::Call as BalancesCall; +pub use pallet_timestamp::Call as TimestampCall; +use pallet_transaction_payment::{ConstFeeMultiplier, CurrencyAdapter, Multiplier}; +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use sp_runtime::{Perbill, Permill}; + +/// Import the template pallet. +pub use pallet_template; + +/// An index to a block. +pub type BlockNumber = u32; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// Balance of an account. +pub type Balance = u128; + +/// Index of a transaction in the chain. +pub type Nonce = u32; + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core data structures. +pub mod opaque { + use super::*; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + + /// Opaque block header type. + pub type Header = generic::Header; + /// Opaque block type. + pub type Block = generic::Block; + /// Opaque block identifier type. + pub type BlockId = generic::BlockId; + + impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + pub grandpa: Grandpa, + } + } +} + +// To learn more about runtime versioning, see: +// https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning +#[sp_version::runtime_version] +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("Guessing Random Number Game"), + impl_name: create_runtime_str!("Guessing Random Number Game"), + authoring_version: 1, + // The version of the runtime specification. A full node will not attempt to use its native + // runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, + // `spec_version`, and `authoring_version` are the same between Wasm and native. + // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use + // the compatible custom types. + spec_version: 100, // updated runtime version + impl_version: 1, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, + state_version: 1, +}; + +/// This determines the average expected block time that we are targeting. +/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. +/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked +/// up by `pallet_aura` to implement `fn slot_duration()`. +/// +/// Change this to adjust the block time. +pub const MILLISECS_PER_BLOCK: u64 = 6000; + +// NOTE: Currently it is not possible to change the slot duration after the chain has started. +// Attempting to do so will brick block production. +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +// Time is measured by number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } +} + +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); + +parameter_types! { + pub const BlockHashCount: BlockNumber = 2400; + pub const Version: RuntimeVersion = VERSION; + /// We allow for 2 seconds of compute with a 6 second average block time. + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::with_sensible_defaults( + Weight::from_parts(2u64 * WEIGHT_REF_TIME_PER_SECOND, u64::MAX), + NORMAL_DISPATCH_RATIO, + ); + pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength + ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub const SS58Prefix: u8 = 42; +} + +// Configure FRAME pallets to include in runtime. + +impl frame_system::Config for Runtime { + /// The basic call filter to use in dispatchable. + type BaseCallFilter = frame_support::traits::Everything; + /// The block type for the runtime. + type Block = Block; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = BlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = BlockLength; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The type for storing how many extrinsics an account has signed. + type Nonce = Nonce; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// Version of the runtime. + type Version = Version; + /// Converts a module to the index of the module in `construct_runtime!`. + /// + /// This type is being generated by `construct_runtime!`. + type PalletInfo = PalletInfo; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// The set code logic, just the default since we're not a parachain. + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_aura::Config for Runtime { + type AuthorityId = AuraId; + type DisabledValidators = (); + type MaxAuthorities = ConstU32<32>; + type AllowMultipleBlocksPerSlot = ConstBool; +} + +impl pallet_grandpa::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + + type WeightInfo = (); + type MaxAuthorities = ConstU32<32>; + type MaxSetIdSessionEntries = ConstU64<0>; + + type KeyOwnerProof = sp_core::Void; + type EquivocationReportSystem = (); +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; + type WeightInfo = (); +} + +/// Existential deposit. +pub const EXISTENTIAL_DEPOSIT: u128 = 500; + +impl pallet_balances::Config for Runtime { + type MaxLocks = ConstU32<50>; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU128; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; + type FreezeIdentifier = (); + type MaxFreezes = (); + type RuntimeHoldReason = (); + type MaxHolds = (); +} + +parameter_types! { + pub FeeMultiplier: Multiplier = Multiplier::one(); +} + +impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = CurrencyAdapter; + type OperationalFeeMultiplier = ConstU8<5>; + type WeightToFee = IdentityFee; + type LengthToFee = IdentityFee; + type FeeMultiplierUpdate = ConstFeeMultiplier; +} + +impl pallet_sudo::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type WeightInfo = pallet_sudo::weights::SubstrateWeight; +} + +// Create the runtime by composing the FRAME pallets that were previously configured. +construct_runtime!( + pub struct Runtime { + System: frame_system, + Timestamp: pallet_timestamp, + Aura: pallet_aura, + Grandpa: pallet_grandpa, + Balances: pallet_balances, + TransactionPayment: pallet_transaction_payment, + Sudo: pallet_sudo, + // Include the custom logic from the pallet-template in the runtime. + GuessedNumberGame: pallet_template, + } +); + +/// The address format for describing accounts. +pub type Address = sp_runtime::MultiAddress; +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); + +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; +/// The payload being signed in transactions. +pub type SignedPayload = generic::SignedPayload; +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; + +#[cfg(feature = "runtime-benchmarks")] +#[macro_use] +extern crate frame_benchmarking; + +#[cfg(feature = "runtime-benchmarks")] +mod benches { + define_benchmarks!( + [frame_benchmarking, BaselineBench::] + [frame_system, SystemBench::] + [pallet_balances, Balances] + [pallet_timestamp, Timestamp] + [pallet_sudo, Sudo] + [pallet_template, GuessedNumberGame] + ); +} + +impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block); + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + OpaqueMetadata::new(Runtime::metadata().into()) + } + + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::CheckInherentsResult { + data.check_extrinsics(&block) + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction( + source: TransactionSource, + tx: ::Extrinsic, + block_hash: ::Hash, + ) -> TransactionValidity { + Executive::validate_transaction(source, tx, block_hash) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> sp_consensus_aura::SlotDuration { + sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) + } + + fn authorities() -> Vec { + Aura::authorities().into_inner() + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + opaque::SessionKeys::generate(seed) + } + + fn decode_session_keys( + encoded: Vec, + ) -> Option, KeyTypeId)>> { + opaque::SessionKeys::decode_into_raw_public_keys(&encoded) + } + } + + impl sp_consensus_grandpa::GrandpaApi for Runtime { + fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList { + Grandpa::grandpa_authorities() + } + + fn current_set_id() -> sp_consensus_grandpa::SetId { + Grandpa::current_set_id() + } + + fn submit_report_equivocation_unsigned_extrinsic( + _equivocation_proof: sp_consensus_grandpa::EquivocationProof< + ::Hash, + NumberFor, + >, + _key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof, + ) -> Option<()> { + None + } + + fn generate_key_ownership_proof( + _set_id: sp_consensus_grandpa::SetId, + _authority_id: GrandpaId, + ) -> Option { + // NOTE: this is the only implementation possible since we've + // defined our key owner proof type as a bottom type (i.e. a type + // with no values). + None + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Nonce { + System::account_nonce(account) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { + fn query_info( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + fn query_fee_details( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_fee_details(uxt, len) + } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi + for Runtime + { + fn query_call_info( + call: RuntimeCall, + len: u32, + ) -> pallet_transaction_payment::RuntimeDispatchInfo { + TransactionPayment::query_call_info(call, len) + } + fn query_call_fee_details( + call: RuntimeCall, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_call_fee_details(call, len) + } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + fn benchmark_metadata(extra: bool) -> ( + Vec, + Vec, + ) { + use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; + use frame_support::traits::StorageInfoTrait; + use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; + + let mut list = Vec::::new(); + list_benchmarks!(list, extra); + + let storage_info = AllPalletsWithSystem::storage_info(); + + (list, storage_info) + } + + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, TrackedStorageKey}; + + use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; + + impl frame_system_benchmarking::Config for Runtime {} + impl baseline::Config for Runtime {} + + use frame_support::traits::WhitelistedStorageKeys; + let whitelist: Vec = AllPalletsWithSystem::whitelisted_storage_keys(); + + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + add_benchmarks!(params, batches); + + Ok(batches) + } + } + + #[cfg(feature = "try-runtime")] + impl frame_try_runtime::TryRuntime for Runtime { + fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. If any of the pre/post migration checks fail, we shall stop + // right here and right now. + let weight = Executive::try_runtime_upgrade(checks).unwrap(); + (weight, BlockWeights::get().max_block) + } + + fn execute_block( + block: Block, + state_root_check: bool, + signature_check: bool, + select: frame_try_runtime::TryStateSelect + ) -> Weight { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. + Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed") + } + } +} + +/// Configure the pallet-template in pallets/template. +impl pallet_template::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} diff --git a/guessing-random-number-substrate-custom-blockchain/rust-toolchain.toml b/guessing-random-number-substrate-custom-blockchain/rust-toolchain.toml new file mode 100644 index 0000000..64daeff --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/rust-toolchain.toml @@ -0,0 +1,14 @@ +[toolchain] +channel = "nightly" +components = [ + "cargo", + "clippy", + "rust-analyzer", + "rust-src", + "rust-std", + "rustc-dev", + "rustc", + "rustfmt", +] +targets = [ "wasm32-unknown-unknown" ] +profile = "minimal" diff --git a/guessing-random-number-substrate-custom-blockchain/rustfmt.toml b/guessing-random-number-substrate-custom-blockchain/rustfmt.toml new file mode 100644 index 0000000..441913f --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/rustfmt.toml @@ -0,0 +1,23 @@ +# Basic +hard_tabs = true +max_width = 100 +use_small_heuristics = "Max" +# Imports +imports_granularity = "Crate" +reorder_imports = true +# Consistency +newline_style = "Unix" +# Format comments +comment_width = 100 +wrap_comments = true +# Misc +chain_width = 80 +spaces_around_ranges = false +binop_separator = "Back" +reorder_impl_items = false +match_arm_leading_pipes = "Preserve" +match_arm_blocks = false +match_block_trailing_comma = true +trailing_comma = "Vertical" +trailing_semicolon = false +use_field_init_shorthand = true diff --git a/guessing-random-number-substrate-custom-blockchain/scripts/init.sh b/guessing-random-number-substrate-custom-blockchain/scripts/init.sh new file mode 100755 index 0000000..f976f72 --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/scripts/init.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# This script is meant to be run on Unix/Linux based systems +set -e + +echo "*** Initializing WASM build environment" + +if [ -z $CI_PROJECT_NAME ] ; then + rustup update nightly + rustup update stable +fi + +rustup target add wasm32-unknown-unknown --toolchain nightly diff --git a/guessing-random-number-substrate-custom-blockchain/shell.nix b/guessing-random-number-substrate-custom-blockchain/shell.nix new file mode 100644 index 0000000..c08005c --- /dev/null +++ b/guessing-random-number-substrate-custom-blockchain/shell.nix @@ -0,0 +1,35 @@ +let + mozillaOverlay = + import (builtins.fetchGit { + url = "https://github.com/mozilla/nixpkgs-mozilla.git"; + rev = "57c8084c7ef41366993909c20491e359bbb90f54"; + }); + pinned = builtins.fetchGit { + # Descriptive name to make the store path easier to identify + url = "https://github.com/nixos/nixpkgs/"; + # Commit hash for nixos-unstable as of 2020-04-26 + # `git ls-remote https://github.com/nixos/nixpkgs nixos-unstable` + ref = "refs/heads/nixos-unstable"; + rev = "1fe6ed37fd9beb92afe90671c0c2a662a03463dd"; + }; + nixpkgs = import pinned { overlays = [ mozillaOverlay ]; }; + toolchain = with nixpkgs; (rustChannelOf { date = "2021-09-14"; channel = "nightly"; }); + rust-wasm = toolchain.rust.override { + targets = [ "wasm32-unknown-unknown" ]; + }; +in +with nixpkgs; pkgs.mkShell { + buildInputs = [ + clang + pkg-config + rust-wasm + ] ++ stdenv.lib.optionals stdenv.isDarwin [ + darwin.apple_sdk.frameworks.Security + ]; + + LIBCLANG_PATH = "${llvmPackages.libclang}/lib"; + PROTOC = "${protobuf}/bin/protoc"; + RUST_SRC_PATH = "${toolchain.rust-src}/lib/rustlib/src/rust/library/"; + ROCKSDB_LIB_DIR = "${rocksdb}/lib"; + +} From 74269d129f4cd92522612dcbf9a97e0d54c72077 Mon Sep 17 00:00:00 2001 From: ajaykumargdr Date: Thu, 18 Jan 2024 17:44:17 +0530 Subject: [PATCH 2/5] chore: Add custom token substrate pallet code --- .../Containerfile | 31 - .../LICENSE | 16 - .../README.md | 164 ----- .../node/src/benchmarking.rs | 161 ----- .../node/src/chain_spec.rs | 158 ----- .../node/src/cli.rs | 54 -- .../node/src/command.rs | 212 ------- .../node/src/rpc.rs | 57 -- .../node/src/service.rs | 331 ---------- .../pallets/template/README.md | 1 - .../pallets/template/src/lib.rs | 118 ---- .../runtime/build.rs | 10 - .../runtime/src/lib.rs | 569 ----------------- .../rust-toolchain.toml | 14 - .../rustfmt.toml | 23 - .../scripts/init.sh | 12 - .../shell.nix | 35 -- .../custom-token-substrate-pallet/Cargo.toml | 35 ++ .../custom-token-substrate-pallet/src/lib.rs | 78 +++ .../guessing-random-number-game}/Cargo.toml | 0 .../node/Cargo.toml | 0 .../node/build.rs | 4 +- .../node/src/benchmarking.rs | 172 ++++++ .../node/src/chain_spec.rs | 168 +++++ .../node/src/cli.rs | 54 ++ .../node/src/command.rs | 235 +++++++ .../node/src/lib.rs | 0 .../node/src/main.rs | 2 +- .../node/src/rpc.rs | 61 ++ .../node/src/service.rs | 344 +++++++++++ .../pallets/template/Cargo.toml | 0 .../pallets/template/src/lib.rs | 124 ++++ .../runtime/Cargo.toml | 0 .../runtime/build.rs | 10 + .../runtime/src/lib.rs | 572 ++++++++++++++++++ 35 files changed, 1856 insertions(+), 1969 deletions(-) delete mode 100644 guessing-random-number-substrate-custom-blockchain/Containerfile delete mode 100644 guessing-random-number-substrate-custom-blockchain/LICENSE delete mode 100644 guessing-random-number-substrate-custom-blockchain/README.md delete mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/benchmarking.rs delete mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/chain_spec.rs delete mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/cli.rs delete mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/command.rs delete mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/rpc.rs delete mode 100644 guessing-random-number-substrate-custom-blockchain/node/src/service.rs delete mode 100644 guessing-random-number-substrate-custom-blockchain/pallets/template/README.md delete mode 100644 guessing-random-number-substrate-custom-blockchain/pallets/template/src/lib.rs delete mode 100644 guessing-random-number-substrate-custom-blockchain/runtime/build.rs delete mode 100644 guessing-random-number-substrate-custom-blockchain/runtime/src/lib.rs delete mode 100644 guessing-random-number-substrate-custom-blockchain/rust-toolchain.toml delete mode 100644 guessing-random-number-substrate-custom-blockchain/rustfmt.toml delete mode 100755 guessing-random-number-substrate-custom-blockchain/scripts/init.sh delete mode 100644 guessing-random-number-substrate-custom-blockchain/shell.nix create mode 100644 substrate-blockchain/custom-token-substrate-pallet/Cargo.toml create mode 100644 substrate-blockchain/custom-token-substrate-pallet/src/lib.rs rename {guessing-random-number-substrate-custom-blockchain => substrate-blockchain/guessing-random-number-game}/Cargo.toml (100%) rename {guessing-random-number-substrate-custom-blockchain => substrate-blockchain/guessing-random-number-game}/node/Cargo.toml (100%) rename {guessing-random-number-substrate-custom-blockchain => substrate-blockchain/guessing-random-number-game}/node/build.rs (62%) create mode 100644 substrate-blockchain/guessing-random-number-game/node/src/benchmarking.rs create mode 100644 substrate-blockchain/guessing-random-number-game/node/src/chain_spec.rs create mode 100644 substrate-blockchain/guessing-random-number-game/node/src/cli.rs create mode 100644 substrate-blockchain/guessing-random-number-game/node/src/command.rs rename {guessing-random-number-substrate-custom-blockchain => substrate-blockchain/guessing-random-number-game}/node/src/lib.rs (100%) rename {guessing-random-number-substrate-custom-blockchain => substrate-blockchain/guessing-random-number-game}/node/src/main.rs (91%) create mode 100644 substrate-blockchain/guessing-random-number-game/node/src/rpc.rs create mode 100644 substrate-blockchain/guessing-random-number-game/node/src/service.rs rename {guessing-random-number-substrate-custom-blockchain => substrate-blockchain/guessing-random-number-game}/pallets/template/Cargo.toml (100%) create mode 100644 substrate-blockchain/guessing-random-number-game/pallets/template/src/lib.rs rename {guessing-random-number-substrate-custom-blockchain => substrate-blockchain/guessing-random-number-game}/runtime/Cargo.toml (100%) create mode 100644 substrate-blockchain/guessing-random-number-game/runtime/build.rs create mode 100644 substrate-blockchain/guessing-random-number-game/runtime/src/lib.rs diff --git a/guessing-random-number-substrate-custom-blockchain/Containerfile b/guessing-random-number-substrate-custom-blockchain/Containerfile deleted file mode 100644 index 01a4a54..0000000 --- a/guessing-random-number-substrate-custom-blockchain/Containerfile +++ /dev/null @@ -1,31 +0,0 @@ -FROM docker.io/library/ubuntu:22.04 - -# show backtraces -ENV RUST_BACKTRACE 1 - -# install tools and dependencies -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - ca-certificates && \ -# apt cleanup - apt-get autoremove -y && \ - apt-get clean && \ - find /var/lib/apt/lists/ -type f -not -name lock -delete; \ -# add user and link ~/.local/share/polkadot to /data - useradd -m -u 1000 -U -s /bin/sh -d /polkadot polkadot && \ - mkdir -p /data /polkadot/.local/share && \ - chown -R polkadot:polkadot /data && \ - ln -s /data /polkadot/.local/share/node-template - -USER polkadot - -# copy the compiled binary to the container -COPY --chown=polkadot:polkadot --chmod=774 node-template /usr/bin/node-template - -# check if executable works in this container -RUN /usr/bin/node-template --version - -# ws_port -EXPOSE 9930 9333 9944 30333 30334 - -CMD ["/usr/bin/node-template"] diff --git a/guessing-random-number-substrate-custom-blockchain/LICENSE b/guessing-random-number-substrate-custom-blockchain/LICENSE deleted file mode 100644 index ffa0b3f..0000000 --- a/guessing-random-number-substrate-custom-blockchain/LICENSE +++ /dev/null @@ -1,16 +0,0 @@ -MIT No Attribution - -Copyright Parity Technologies (UK) Ltd. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this -software and associated documentation files (the "Software"), to deal in the Software -without restriction, including without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/guessing-random-number-substrate-custom-blockchain/README.md b/guessing-random-number-substrate-custom-blockchain/README.md deleted file mode 100644 index 337faca..0000000 --- a/guessing-random-number-substrate-custom-blockchain/README.md +++ /dev/null @@ -1,164 +0,0 @@ -# Substrate Node Template - -A fresh [Substrate](https://substrate.io/) node, ready for hacking :rocket: - -A standalone version of this template is available for each release of Polkadot in the [Substrate Developer Hub Parachain Template](https://github.com/substrate-developer-hub/substrate-parachain-template/) repository. -The parachain template is generated directly at each Polkadot release branch from the [Node Template in Substrate](https://github.com/paritytech/substrate/tree/master/bin/node-template) upstream - -It is usually best to use the stand-alone version to start a new project. -All bugs, suggestions, and feature requests should be made upstream in the [Substrate](https://github.com/paritytech/substrate/tree/master/bin/node-template) repository. - -## Getting Started - -Depending on your operating system and Rust version, there might be additional packages required to compile this template. -Check the [Install](https://docs.substrate.io/install/) instructions for your platform for the most common dependencies. -Alternatively, you can use one of the [alternative installation](#alternatives-installations) options. - -### Build - -Use the following command to build the node without launching it: - -```sh -cargo build --release -``` - -### Embedded Docs - -After you build the project, you can use the following command to explore its parameters and subcommands: - -```sh -./target/release/node-template -h -``` - -You can generate and view the [Rust Docs](https://doc.rust-lang.org/cargo/commands/cargo-doc.html) for this template with this command: - -```sh -cargo +nightly doc --open -``` - -### Single-Node Development Chain - -The following command starts a single-node development chain that doesn't persist state: - -```sh -./target/release/node-template --dev -``` - -To purge the development chain's state, run the following command: - -```sh -./target/release/node-template purge-chain --dev -``` - -To start the development chain with detailed logging, run the following command: - -```sh -RUST_BACKTRACE=1 ./target/release/node-template -ldebug --dev -``` - -Development chains: - -- Maintain state in a `tmp` folder while the node is running. -- Use the **Alice** and **Bob** accounts as default validator authorities. -- Use the **Alice** account as the default `sudo` account. -- Are preconfigured with a genesis state (`/node/src/chain_spec.rs`) that includes several prefunded development accounts. - - -To persist chain state between runs, specify a base path by running a command similar to the following: - -```sh -// Create a folder to use as the db base path -$ mkdir my-chain-state - -// Use of that folder to store the chain state -$ ./target/release/node-template --dev --base-path ./my-chain-state/ - -// Check the folder structure created inside the base path after running the chain -$ ls ./my-chain-state -chains -$ ls ./my-chain-state/chains/ -dev -$ ls ./my-chain-state/chains/dev -db keystore network -``` - -### Connect with Polkadot-JS Apps Front-End - -After you start the node template locally, you can interact with it using the hosted version of the [Polkadot/Substrate Portal](https://polkadot.js.org/apps/#/explorer?rpc=ws://localhost:9944) front-end by connecting to the local node endpoint. -A hosted version is also available on [IPFS (redirect) here](https://dotapps.io/) or [IPNS (direct) here](ipns://dotapps.io/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/explorer). -You can also find the source code and instructions for hosting your own instance on the [polkadot-js/apps](https://github.com/polkadot-js/apps) repository. - -### Multi-Node Local Testnet - -If you want to see the multi-node consensus algorithm in action, see [Simulate a network](https://docs.substrate.io/tutorials/build-a-blockchain/simulate-network/). - -## Template Structure - -A Substrate project such as this consists of a number of components that are spread across a few directories. - -### Node - -A blockchain node is an application that allows users to participate in a blockchain network. -Substrate-based blockchain nodes expose a number of capabilities: - -- Networking: Substrate nodes use the [`libp2p`](https://libp2p.io/) networking stack to allow the - nodes in the network to communicate with one another. -- Consensus: Blockchains must have a way to come to [consensus](https://docs.substrate.io/fundamentals/consensus/) on the state of the network. - Substrate makes it possible to supply custom consensus engines and also ships with several consensus mechanisms that have been built on top of [Web3 Foundation research](https://research.web3.foundation/en/latest/polkadot/NPoS/index.html). -- RPC Server: A remote procedure call (RPC) server is used to interact with Substrate nodes. - -There are several files in the `node` directory. -Take special note of the following: - -- [`chain_spec.rs`](./node/src/chain_spec.rs): A [chain specification](https://docs.substrate.io/build/chain-spec/) is a source code file that defines a Substrate chain's initial (genesis) state. - Chain specifications are useful for development and testing, and critical when architecting the launch of a production chain. - Take note of the `development_config` and `testnet_genesis` functions,. - These functions are used to define the genesis state for the local development chain configuration. - These functions identify some [well-known accounts](https://docs.substrate.io/reference/command-line-tools/subkey/) and use them to configure the blockchain's initial state. -- [`service.rs`](./node/src/service.rs): This file defines the node implementation. - Take note of the libraries that this file imports and the names of the functions it invokes. - In particular, there are references to consensus-related topics, such as the [block finalization and forks](https://docs.substrate.io/fundamentals/consensus/#finalization-and-forks) and other [consensus mechanisms](https://docs.substrate.io/fundamentals/consensus/#default-consensus-models) such as Aura for block authoring and GRANDPA for finality. - - - -### Runtime - -In Substrate, the terms "runtime" and "state transition function" are analogous. -Both terms refer to the core logic of the blockchain that is responsible for validating blocks and executing the state changes they define. -The Substrate project in this repository uses [FRAME](https://docs.substrate.io/learn/runtime-development/#frame) to construct a blockchain runtime. -FRAME allows runtime developers to declare domain-specific logic in modules called "pallets". -At the heart of FRAME is a helpful [macro language](https://docs.substrate.io/reference/frame-macros/) that makes it easy to create pallets and flexibly compose them to create blockchains that can address [a variety of needs](https://substrate.io/ecosystem/projects/). - -Review the [FRAME runtime implementation](./runtime/src/lib.rs) included in this template and note the following: - -- This file configures several pallets to include in the runtime. - Each pallet configuration is defined by a code block that begins with `impl $PALLET_NAME::Config for Runtime`. -- The pallets are composed into a single runtime by way of the [`construct_runtime!`](https://paritytech.github.io/substrate/master/frame_support/macro.construct_runtime.html) macro, which is part of the [core FRAME pallet library](https://docs.substrate.io/reference/frame-pallets/#system-pallets). - -### Pallets - -The runtime in this project is constructed using many FRAME pallets that ship with [the Substrate repository](https://github.com/paritytech/substrate/tree/master/frame) and a template pallet that is [defined in the `pallets`](./pallets/template/src/lib.rs) directory. - -A FRAME pallet is comprised of a number of blockchain primitives, including: - -- Storage: FRAME defines a rich set of powerful [storage abstractions](https://docs.substrate.io/build/runtime-storage/) that makes it easy to use Substrate's efficient key-value database to manage the evolving state of a blockchain. -- Dispatchables: FRAME pallets define special types of functions that can be invoked (dispatched) from outside of the runtime in order to update its state. -- Events: Substrate uses [events](https://docs.substrate.io/build/events-and-errors/) to notify users of significant state changes. -- Errors: When a dispatchable fails, it returns an error. - -Each pallet has its own `Config` trait which serves as a configuration interface to generically define the types and parameters it depends on. - -## Alternatives Installations - -Instead of installing dependencies and building this source directly, consider the following alternatives. - -### Nix - -Install [nix](https://nixos.org/) and -[nix-direnv](https://github.com/nix-community/nix-direnv) for a fully plug-and-play -experience for setting up the development environment. -To get all the correct dependencies, activate direnv `direnv allow`. - -### Docker - -Please follow the [Substrate Docker instructions here](https://github.com/paritytech/substrate/blob/master/docker/README.md) to build the Docker container with the Substrate Node Template binary. diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/benchmarking.rs b/guessing-random-number-substrate-custom-blockchain/node/src/benchmarking.rs deleted file mode 100644 index 6e29ad1..0000000 --- a/guessing-random-number-substrate-custom-blockchain/node/src/benchmarking.rs +++ /dev/null @@ -1,161 +0,0 @@ -//! Setup code for [`super::command`] which would otherwise bloat that module. -//! -//! Should only be used for benchmarking as it may break in other contexts. - -use crate::service::FullClient; - -use node_template_runtime as runtime; -use runtime::{AccountId, Balance, BalancesCall, SystemCall}; -use sc_cli::Result; -use sc_client_api::BlockBackend; -use sp_core::{Encode, Pair}; -use sp_inherents::{InherentData, InherentDataProvider}; -use sp_keyring::Sr25519Keyring; -use sp_runtime::{OpaqueExtrinsic, SaturatedConversion}; - -use std::{sync::Arc, time::Duration}; - -/// Generates extrinsics for the `benchmark overhead` command. -/// -/// Note: Should only be used for benchmarking. -pub struct RemarkBuilder { - client: Arc, -} - -impl RemarkBuilder { - /// Creates a new [`Self`] from the given client. - pub fn new(client: Arc) -> Self { - Self { client } - } -} - -impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder { - fn pallet(&self) -> &str { - "system" - } - - fn extrinsic(&self) -> &str { - "remark" - } - - fn build(&self, nonce: u32) -> std::result::Result { - let acc = Sr25519Keyring::Bob.pair(); - let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( - self.client.as_ref(), - acc, - SystemCall::remark { remark: vec![] }.into(), - nonce, - ) - .into(); - - Ok(extrinsic) - } -} - -/// Generates `Balances::TransferKeepAlive` extrinsics for the benchmarks. -/// -/// Note: Should only be used for benchmarking. -pub struct TransferKeepAliveBuilder { - client: Arc, - dest: AccountId, - value: Balance, -} - -impl TransferKeepAliveBuilder { - /// Creates a new [`Self`] from the given client. - pub fn new(client: Arc, dest: AccountId, value: Balance) -> Self { - Self { client, dest, value } - } -} - -impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { - fn pallet(&self) -> &str { - "balances" - } - - fn extrinsic(&self) -> &str { - "transfer_keep_alive" - } - - fn build(&self, nonce: u32) -> std::result::Result { - let acc = Sr25519Keyring::Bob.pair(); - let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( - self.client.as_ref(), - acc, - BalancesCall::transfer_keep_alive { dest: self.dest.clone().into(), value: self.value } - .into(), - nonce, - ) - .into(); - - Ok(extrinsic) - } -} - -/// Create a transaction using the given `call`. -/// -/// Note: Should only be used for benchmarking. -pub fn create_benchmark_extrinsic( - client: &FullClient, - sender: sp_core::sr25519::Pair, - call: runtime::RuntimeCall, - nonce: u32, -) -> runtime::UncheckedExtrinsic { - let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); - let best_hash = client.chain_info().best_hash; - let best_block = client.chain_info().best_number; - - let period = runtime::BlockHashCount::get() - .checked_next_power_of_two() - .map(|c| c / 2) - .unwrap_or(2) as u64; - let extra: runtime::SignedExtra = ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(sp_runtime::generic::Era::mortal( - period, - best_block.saturated_into(), - )), - frame_system::CheckNonce::::from(nonce), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ); - - let raw_payload = runtime::SignedPayload::from_raw( - call.clone(), - extra.clone(), - ( - (), - runtime::VERSION.spec_version, - runtime::VERSION.transaction_version, - genesis_hash, - best_hash, - (), - (), - (), - ), - ); - let signature = raw_payload.using_encoded(|e| sender.sign(e)); - - runtime::UncheckedExtrinsic::new_signed( - call, - sp_runtime::AccountId32::from(sender.public()).into(), - runtime::Signature::Sr25519(signature), - extra, - ) -} - -/// Generates inherent data for the `benchmark overhead` command. -/// -/// Note: Should only be used for benchmarking. -pub fn inherent_benchmark_data() -> Result { - let mut inherent_data = InherentData::new(); - let d = Duration::from_millis(0); - let timestamp = sp_timestamp::InherentDataProvider::new(d.into()); - - futures::executor::block_on(timestamp.provide_inherent_data(&mut inherent_data)) - .map_err(|e| format!("creating inherent data: {:?}", e))?; - Ok(inherent_data) -} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/chain_spec.rs b/guessing-random-number-substrate-custom-blockchain/node/src/chain_spec.rs deleted file mode 100644 index 2cd2d07..0000000 --- a/guessing-random-number-substrate-custom-blockchain/node/src/chain_spec.rs +++ /dev/null @@ -1,158 +0,0 @@ -use node_template_runtime::{ - AccountId, AuraConfig, BalancesConfig, GrandpaConfig, RuntimeGenesisConfig, Signature, - SudoConfig, SystemConfig, WASM_BINARY, -}; -use sc_service::ChainType; -use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_consensus_grandpa::AuthorityId as GrandpaId; -use sp_core::{sr25519, Pair, Public}; -use sp_runtime::traits::{IdentifyAccount, Verify}; - -// The URL for the telemetry server. -// const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; - -/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. -pub type ChainSpec = sc_service::GenericChainSpec; - -/// Generate a crypto pair from seed. -pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{}", seed), None) - .expect("static values are valid; qed") - .public() -} - -type AccountPublic = ::Signer; - -/// Generate an account ID from seed. -pub fn get_account_id_from_seed(seed: &str) -> AccountId -where - AccountPublic: From<::Public>, -{ - AccountPublic::from(get_from_seed::(seed)).into_account() -} - -/// Generate an Aura authority key. -pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { - (get_from_seed::(s), get_from_seed::(s)) -} - -pub fn development_config() -> Result { - let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; - - Ok(ChainSpec::from_genesis( - // Name - "Development", - // ID - "dev", - ChainType::Development, - move || { - testnet_genesis( - wasm_binary, - // Initial PoA authorities - vec![authority_keys_from_seed("Alice")], - // Sudo account - get_account_id_from_seed::("Alice"), - // Pre-funded accounts - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - ], - true, - ) - }, - // Bootnodes - vec![], - // Telemetry - None, - // Protocol ID - None, - None, - // Properties - None, - // Extensions - None, - )) -} - -pub fn local_testnet_config() -> Result { - let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; - - Ok(ChainSpec::from_genesis( - // Name - "Local Testnet", - // ID - "local_testnet", - ChainType::Local, - move || { - testnet_genesis( - wasm_binary, - // Initial PoA authorities - vec![authority_keys_from_seed("Alice"), authority_keys_from_seed("Bob")], - // Sudo account - get_account_id_from_seed::("Alice"), - // Pre-funded accounts - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), - ], - true, - ) - }, - // Bootnodes - vec![], - // Telemetry - None, - // Protocol ID - None, - // Properties - None, - None, - // Extensions - None, - )) -} - -/// Configure initial storage state for FRAME modules. -fn testnet_genesis( - wasm_binary: &[u8], - initial_authorities: Vec<(AuraId, GrandpaId)>, - root_key: AccountId, - endowed_accounts: Vec, - _enable_println: bool, -) -> RuntimeGenesisConfig { - RuntimeGenesisConfig { - system: SystemConfig { - // Add Wasm runtime to storage. - code: wasm_binary.to_vec(), - ..Default::default() - }, - balances: BalancesConfig { - // Configure endowed accounts with initial balance of 1 << 60. - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), - }, - aura: AuraConfig { - authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), - }, - grandpa: GrandpaConfig { - authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), - ..Default::default() - }, - sudo: SudoConfig { - // Assign network admin rights. - key: Some(root_key), - }, - transaction_payment: Default::default(), - } -} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/cli.rs b/guessing-random-number-substrate-custom-blockchain/node/src/cli.rs deleted file mode 100644 index 15ceaa0..0000000 --- a/guessing-random-number-substrate-custom-blockchain/node/src/cli.rs +++ /dev/null @@ -1,54 +0,0 @@ -use sc_cli::RunCmd; - -#[derive(Debug, clap::Parser)] -pub struct Cli { - #[command(subcommand)] - pub subcommand: Option, - - #[clap(flatten)] - pub run: RunCmd, -} - -#[derive(Debug, clap::Subcommand)] -#[allow(clippy::large_enum_variant)] -pub enum Subcommand { - /// Key management cli utilities - #[command(subcommand)] - Key(sc_cli::KeySubcommand), - - /// Build a chain specification. - BuildSpec(sc_cli::BuildSpecCmd), - - /// Validate blocks. - CheckBlock(sc_cli::CheckBlockCmd), - - /// Export blocks. - ExportBlocks(sc_cli::ExportBlocksCmd), - - /// Export the state of a given block into a chain spec. - ExportState(sc_cli::ExportStateCmd), - - /// Import blocks. - ImportBlocks(sc_cli::ImportBlocksCmd), - - /// Remove the whole chain. - PurgeChain(sc_cli::PurgeChainCmd), - - /// Revert the chain to a previous state. - Revert(sc_cli::RevertCmd), - - /// Sub-commands concerned with benchmarking. - #[command(subcommand)] - Benchmark(frame_benchmarking_cli::BenchmarkCmd), - - /// Try some command against runtime state. - #[cfg(feature = "try-runtime")] - TryRuntime(try_runtime_cli::TryRuntimeCmd), - - /// Try some command against runtime state. Note: `try-runtime` feature must be enabled. - #[cfg(not(feature = "try-runtime"))] - TryRuntime, - - /// Db meta columns information. - ChainInfo(sc_cli::ChainInfoCmd), -} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/command.rs b/guessing-random-number-substrate-custom-blockchain/node/src/command.rs deleted file mode 100644 index 8fc697b..0000000 --- a/guessing-random-number-substrate-custom-blockchain/node/src/command.rs +++ /dev/null @@ -1,212 +0,0 @@ -use crate::{ - benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder}, - chain_spec, - cli::{Cli, Subcommand}, - service, -}; -use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory, SUBSTRATE_REFERENCE_HARDWARE}; -use node_template_runtime::{Block, EXISTENTIAL_DEPOSIT}; -use sc_cli::SubstrateCli; -use sc_service::PartialComponents; -use sp_keyring::Sr25519Keyring; - -#[cfg(feature = "try-runtime")] -use try_runtime_cli::block_building_info::timestamp_with_aura_info; - -impl SubstrateCli for Cli { - fn impl_name() -> String { - "Substrate Node".into() - } - - fn impl_version() -> String { - env!("SUBSTRATE_CLI_IMPL_VERSION").into() - } - - fn description() -> String { - env!("CARGO_PKG_DESCRIPTION").into() - } - - fn author() -> String { - env!("CARGO_PKG_AUTHORS").into() - } - - fn support_url() -> String { - "support.anonymous.an".into() - } - - fn copyright_start_year() -> i32 { - 2017 - } - - fn load_spec(&self, id: &str) -> Result, String> { - Ok(match id { - "dev" => Box::new(chain_spec::development_config()?), - "" | "local" => Box::new(chain_spec::local_testnet_config()?), - path => - Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), - }) - } -} - -/// Parse and run command line arguments -pub fn run() -> sc_cli::Result<()> { - let cli = Cli::from_args(); - - match &cli.subcommand { - Some(Subcommand::Key(cmd)) => cmd.run(&cli), - Some(Subcommand::BuildSpec(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - }, - Some(Subcommand::CheckBlock(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, .. } = - service::new_partial(&config)?; - Ok((cmd.run(client, import_queue), task_manager)) - }) - }, - Some(Subcommand::ExportBlocks(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; - Ok((cmd.run(client, config.database), task_manager)) - }) - }, - Some(Subcommand::ExportState(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; - Ok((cmd.run(client, config.chain_spec), task_manager)) - }) - }, - Some(Subcommand::ImportBlocks(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, .. } = - service::new_partial(&config)?; - Ok((cmd.run(client, import_queue), task_manager)) - }) - }, - Some(Subcommand::PurgeChain(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run(config.database)) - }, - Some(Subcommand::Revert(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, backend, .. } = - service::new_partial(&config)?; - let aux_revert = Box::new(|client, _, blocks| { - sc_consensus_grandpa::revert(client, blocks)?; - Ok(()) - }); - Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) - }) - }, - Some(Subcommand::Benchmark(cmd)) => { - let runner = cli.create_runner(cmd)?; - - runner.sync_run(|config| { - // This switch needs to be in the client, since the client decides - // which sub-commands it wants to support. - match cmd { - BenchmarkCmd::Pallet(cmd) => { - if !cfg!(feature = "runtime-benchmarks") { - return Err( - "Runtime benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." - .into(), - ) - } - - cmd.run::(config) - }, - BenchmarkCmd::Block(cmd) => { - let PartialComponents { client, .. } = service::new_partial(&config)?; - cmd.run(client) - }, - #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => Err( - "Storage benchmarking can be enabled with `--features runtime-benchmarks`." - .into(), - ), - #[cfg(feature = "runtime-benchmarks")] - BenchmarkCmd::Storage(cmd) => { - let PartialComponents { client, backend, .. } = - service::new_partial(&config)?; - let db = backend.expose_db(); - let storage = backend.expose_storage(); - - cmd.run(config, client, db, storage) - }, - BenchmarkCmd::Overhead(cmd) => { - let PartialComponents { client, .. } = service::new_partial(&config)?; - let ext_builder = RemarkBuilder::new(client.clone()); - - cmd.run( - config, - client, - inherent_benchmark_data()?, - Vec::new(), - &ext_builder, - ) - }, - BenchmarkCmd::Extrinsic(cmd) => { - let PartialComponents { client, .. } = service::new_partial(&config)?; - // Register the *Remark* and *TKA* builders. - let ext_factory = ExtrinsicFactory(vec![ - Box::new(RemarkBuilder::new(client.clone())), - Box::new(TransferKeepAliveBuilder::new( - client.clone(), - Sr25519Keyring::Alice.to_account_id(), - EXISTENTIAL_DEPOSIT, - )), - ]); - - cmd.run(client, inherent_benchmark_data()?, Vec::new(), &ext_factory) - }, - BenchmarkCmd::Machine(cmd) => - cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()), - } - }) - }, - #[cfg(feature = "try-runtime")] - Some(Subcommand::TryRuntime(cmd)) => { - use crate::service::ExecutorDispatch; - use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, NativeExecutionDispatch}; - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - // we don't need any of the components of new_partial, just a runtime, or a task - // manager to do `async_run`. - let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); - let task_manager = - sc_service::TaskManager::new(config.tokio_handle.clone(), registry) - .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; - let info_provider = timestamp_with_aura_info(6000); - - Ok(( - cmd.run::::ExtendHostFunctions, - >, _>(Some(info_provider)), - task_manager, - )) - }) - }, - #[cfg(not(feature = "try-runtime"))] - Some(Subcommand::TryRuntime) => Err("TryRuntime wasn't enabled when building the node. \ - You can enable it with `--features try-runtime`." - .into()), - Some(Subcommand::ChainInfo(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(&config)) - }, - None => { - let runner = cli.create_runner(&cli.run)?; - runner.run_node_until_exit(|config| async move { - service::new_full(config).map_err(sc_cli::Error::Service) - }) - }, - } -} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/rpc.rs b/guessing-random-number-substrate-custom-blockchain/node/src/rpc.rs deleted file mode 100644 index f4f1540..0000000 --- a/guessing-random-number-substrate-custom-blockchain/node/src/rpc.rs +++ /dev/null @@ -1,57 +0,0 @@ -//! A collection of node-specific RPC methods. -//! Substrate provides the `sc-rpc` crate, which defines the core RPC layer -//! used by Substrate nodes. This file extends those RPC definitions with -//! capabilities that are specific to this project's runtime configuration. - -#![warn(missing_docs)] - -use std::sync::Arc; - -use jsonrpsee::RpcModule; -use node_template_runtime::{opaque::Block, AccountId, Balance, Nonce}; -use sc_transaction_pool_api::TransactionPool; -use sp_api::ProvideRuntimeApi; -use sp_block_builder::BlockBuilder; -use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; - -pub use sc_rpc_api::DenyUnsafe; - -/// Full client dependencies. -pub struct FullDeps { - /// The client instance to use. - pub client: Arc, - /// Transaction pool instance. - pub pool: Arc

, - /// Whether to deny unsafe calls - pub deny_unsafe: DenyUnsafe, -} - -/// Instantiate all full RPC extensions. -pub fn create_full( - deps: FullDeps, -) -> Result, Box> -where - C: ProvideRuntimeApi, - C: HeaderBackend + HeaderMetadata + 'static, - C: Send + Sync + 'static, - C::Api: substrate_frame_rpc_system::AccountNonceApi, - C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, - C::Api: BlockBuilder, - P: TransactionPool + 'static, -{ - use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; - use substrate_frame_rpc_system::{System, SystemApiServer}; - - let mut module = RpcModule::new(()); - let FullDeps { client, pool, deny_unsafe } = deps; - - module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; - module.merge(TransactionPayment::new(client).into_rpc())?; - - // Extend this RPC with a custom API by using the following syntax. - // `YourRpcStruct` should have a reference to a client, which is needed - // to call into the runtime. - // `module.merge(YourRpcTrait::into_rpc(YourRpcStruct::new(ReferenceToClient, ...)))?;` - - Ok(module) -} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/service.rs b/guessing-random-number-substrate-custom-blockchain/node/src/service.rs deleted file mode 100644 index 355e24c..0000000 --- a/guessing-random-number-substrate-custom-blockchain/node/src/service.rs +++ /dev/null @@ -1,331 +0,0 @@ -//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. - -use futures::FutureExt; -use node_template_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::{Backend, BlockBackend}; -use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; -use sc_consensus_grandpa::SharedVoterState; -pub use sc_executor::NativeElseWasmExecutor; -use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncParams}; -use sc_telemetry::{Telemetry, TelemetryWorker}; -use sc_transaction_pool_api::OffchainTransactionPoolFactory; -use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; -use std::{sync::Arc, time::Duration}; - -// Our native executor instance. -pub struct ExecutorDispatch; - -impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { - /// Only enable the benchmarking host functions when we actually want to benchmark. - #[cfg(feature = "runtime-benchmarks")] - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - /// Otherwise we only use the default Substrate host functions. - #[cfg(not(feature = "runtime-benchmarks"))] - type ExtendHostFunctions = (); - - fn dispatch(method: &str, data: &[u8]) -> Option> { - node_template_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - node_template_runtime::native_version() - } -} - -pub(crate) type FullClient = - sc_service::TFullClient>; -type FullBackend = sc_service::TFullBackend; -type FullSelectChain = sc_consensus::LongestChain; - -#[allow(clippy::type_complexity)] -pub fn new_partial( - config: &Configuration, -) -> Result< - sc_service::PartialComponents< - FullClient, - FullBackend, - FullSelectChain, - sc_consensus::DefaultImportQueue, - sc_transaction_pool::FullPool, - ( - sc_consensus_grandpa::GrandpaBlockImport< - FullBackend, - Block, - FullClient, - FullSelectChain, - >, - sc_consensus_grandpa::LinkHalf, - Option, - ), - >, - ServiceError, -> { - let telemetry = config - .telemetry_endpoints - .clone() - .filter(|x| !x.is_empty()) - .map(|endpoints| -> Result<_, sc_telemetry::Error> { - let worker = TelemetryWorker::new(16)?; - let telemetry = worker.handle().new_telemetry(endpoints); - Ok((worker, telemetry)) - }) - .transpose()?; - - let executor = sc_service::new_native_or_wasm_executor(config); - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; - let client = Arc::new(client); - - let telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", None, worker.run()); - telemetry - }); - - let select_chain = sc_consensus::LongestChain::new(backend.clone()); - - let transaction_pool = sc_transaction_pool::BasicPool::new_full( - config.transaction_pool.clone(), - config.role.is_authority().into(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - ); - - let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( - client.clone(), - &client, - select_chain.clone(), - telemetry.as_ref().map(|x| x.handle()), - )?; - - let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - - let import_queue = - sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import.clone())), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - }, - spawner: &task_manager.spawn_essential_handle(), - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), - })?; - - Ok(sc_service::PartialComponents { - client, - backend, - task_manager, - import_queue, - keystore_container, - select_chain, - transaction_pool, - other: (grandpa_block_import, grandpa_link, telemetry), - }) -} - -/// Builds a new service for a full client. -pub fn new_full(config: Configuration) -> Result { - let sc_service::PartialComponents { - client, - backend, - mut task_manager, - import_queue, - keystore_container, - select_chain, - transaction_pool, - other: (block_import, grandpa_link, mut telemetry), - } = new_partial(&config)?; - - let mut net_config = sc_network::config::FullNetworkConfiguration::new(&config.network); - - let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name( - &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), - &config.chain_spec, - ); - net_config.add_notification_protocol(sc_consensus_grandpa::grandpa_peers_set_config( - grandpa_protocol_name.clone(), - )); - - let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( - backend.clone(), - grandpa_link.shared_authority_set().clone(), - Vec::default(), - )); - - let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - net_config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - block_announce_validator_builder: None, - warp_sync_params: Some(WarpSyncParams::WithProvider(warp_sync)), - })?; - - if config.offchain_worker.enabled { - task_manager.spawn_handle().spawn( - "offchain-workers-runner", - "offchain-worker", - sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { - runtime_api_provider: client.clone(), - is_validator: config.role.is_authority(), - keystore: Some(keystore_container.keystore()), - offchain_db: backend.offchain_storage(), - transaction_pool: Some(OffchainTransactionPoolFactory::new( - transaction_pool.clone(), - )), - network_provider: network.clone(), - enable_http_requests: true, - custom_extensions: |_| vec![], - }) - .run(client.clone(), task_manager.spawn_handle()) - .boxed(), - ); - } - - let role = config.role.clone(); - let force_authoring = config.force_authoring; - let backoff_authoring_blocks: Option<()> = None; - let name = config.network.node_name.clone(); - let enable_grandpa = !config.disable_grandpa; - let prometheus_registry = config.prometheus_registry().cloned(); - - let rpc_extensions_builder = { - let client = client.clone(); - let pool = transaction_pool.clone(); - - Box::new(move |deny_unsafe, _| { - let deps = - crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; - crate::rpc::create_full(deps).map_err(Into::into) - }) - }; - - let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { - network: network.clone(), - client: client.clone(), - keystore: keystore_container.keystore(), - task_manager: &mut task_manager, - transaction_pool: transaction_pool.clone(), - rpc_builder: rpc_extensions_builder, - backend, - system_rpc_tx, - tx_handler_controller, - sync_service: sync_service.clone(), - config, - telemetry: telemetry.as_mut(), - })?; - - if role.is_authority() { - let proposer_factory = sc_basic_authorship::ProposerFactory::new( - task_manager.spawn_handle(), - client.clone(), - transaction_pool.clone(), - prometheus_registry.as_ref(), - telemetry.as_ref().map(|x| x.handle()), - ); - - let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - - let aura = sc_consensus_aura::start_aura::( - StartAuraParams { - slot_duration, - client, - select_chain, - block_import, - proposer_factory, - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - }, - force_authoring, - backoff_authoring_blocks, - keystore: keystore_container.keystore(), - sync_oracle: sync_service.clone(), - justification_sync_link: sync_service.clone(), - block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), - max_block_proposal_slot_portion: None, - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), - }, - )?; - - // the AURA authoring task is considered essential, i.e. if it - // fails we take down the service with it. - task_manager - .spawn_essential_handle() - .spawn_blocking("aura", Some("block-authoring"), aura); - } - - if enable_grandpa { - // if the node isn't actively participating in consensus then it doesn't - // need a keystore, regardless of which protocol we use below. - let keystore = if role.is_authority() { Some(keystore_container.keystore()) } else { None }; - - let grandpa_config = sc_consensus_grandpa::Config { - // FIXME #1578 make this available through chainspec - gossip_duration: Duration::from_millis(333), - justification_period: 512, - name: Some(name), - observer_enabled: false, - keystore, - local_role: role, - telemetry: telemetry.as_ref().map(|x| x.handle()), - protocol_name: grandpa_protocol_name, - }; - - // start the full GRANDPA voter - // NOTE: non-authorities could run the GRANDPA observer protocol, but at - // this point the full voter should provide better guarantees of block - // and vote data availability than the observer. The observer has not - // been tested extensively yet and having most nodes in a network run it - // could lead to finality stalls. - let grandpa_config = sc_consensus_grandpa::GrandpaParams { - config: grandpa_config, - link: grandpa_link, - network, - sync: Arc::new(sync_service), - voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(), - prometheus_registry, - shared_voter_state: SharedVoterState::empty(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool), - }; - - // the GRANDPA voter task is considered infallible, i.e. - // if it fails we take down the service with it. - task_manager.spawn_essential_handle().spawn_blocking( - "grandpa-voter", - None, - sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?, - ); - } - - network_starter.start_network(); - Ok(task_manager) -} diff --git a/guessing-random-number-substrate-custom-blockchain/pallets/template/README.md b/guessing-random-number-substrate-custom-blockchain/pallets/template/README.md deleted file mode 100644 index d0d5953..0000000 --- a/guessing-random-number-substrate-custom-blockchain/pallets/template/README.md +++ /dev/null @@ -1 +0,0 @@ -License: MIT-0 \ No newline at end of file diff --git a/guessing-random-number-substrate-custom-blockchain/pallets/template/src/lib.rs b/guessing-random-number-substrate-custom-blockchain/pallets/template/src/lib.rs deleted file mode 100644 index fb94828..0000000 --- a/guessing-random-number-substrate-custom-blockchain/pallets/template/src/lib.rs +++ /dev/null @@ -1,118 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -// Re-export pallet items so that they can be accessed from the crate namespace. -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - // pub use frame_support::traits::Randomness; - - #[pallet::pallet] - // #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - /// Configure the pallet by specifying the parameters and types on which it depends. - #[pallet::config] - pub trait Config: frame_system::Config { - /// Because this pallet emits events, it depends on the runtime's definition of an event. - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - } - - #[pallet::storage] - pub(super) type TargetNumber = StorageValue<_, u32, ValueQuery>; - - #[pallet::storage] - pub(super) type Guesses = StorageMap<_, Blake2_128Concat, u32, (T::AccountId, u32)>; - - // Pallets use events to inform users when important changes are made. - // Event documentation should end with an array that provides descriptive names for parameters. - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - TargetNotSet, - - ExactNumber { who: T::AccountId, number: u32 }, - - TargetNumberChanged, - - TargetNumberRemoved, - - GuessedNumber { who: T::AccountId, number: u32 }, - } - - // Errors inform users that something went wrong. - #[pallet::error] - pub enum Error { - TargetNotSet, - - PredecessorNumber, - - SuccessorNumber, - - TooManyTurns, - } - - // Dispatchable functions allow users to interact with the pallet and invoke state changes. - // These functions materialize as "extrinsics", which are often compared to transactions. - // Dispatchable functions must be annotated with a weight and must return a DispatchResult. - - #[pallet::call] - impl Pallet { - #[pallet::weight(0)] - #[pallet::call_index(1)] - pub fn set_target(origin: OriginFor, number: u32) -> DispatchResult { - // Check that the extrinsic was root. - // This function will return an error if the extrinsic is not signed. - ensure_root(origin)?; - Self::deposit_event(Event::TargetNumberChanged); - TargetNumber::::put(number); - - Ok(()) - } - - #[pallet::weight(0)] - #[pallet::call_index(2)] - pub fn check_with(origin: OriginFor, number: u32) -> DispatchResult { - if !TargetNumber::::exists() { - return Err(Error::::TargetNotSet.into()) - } - - // Check that the extrinsic was signed and get the signer. - // This function will return an error if the extrinsic is not signed. - let sender = ensure_signed(origin)?; - - let target = TargetNumber::::get(); - - Self::deposit_event(Event::GuessedNumber { who: sender.clone(), number }); - - if number == target { - Self::deposit_event(Event::ExactNumber { who: sender, number }); - TargetNumber::::kill(); - Self::deposit_event(Event::TargetNumberRemoved); - } else if number < target { - return Err(Error::::PredecessorNumber.into()) - } else { - return Err(Error::::SuccessorNumber.into()) - } - - return Ok(()); - } - - #[pallet::weight(0)] - #[pallet::call_index(3)] - pub fn remove_target(origin: OriginFor) -> DispatchResult { - // Check that the extrinsic was root. - // This function will return an error if the extrinsic is not signed. - ensure_root(origin)?; - ensure!(TargetNumber::::exists(), Error::::TargetNotSet); - - TargetNumber::::kill(); - - Self::deposit_event(Event::TargetNumberRemoved); - Ok(()) - } - } -} diff --git a/guessing-random-number-substrate-custom-blockchain/runtime/build.rs b/guessing-random-number-substrate-custom-blockchain/runtime/build.rs deleted file mode 100644 index c03d618..0000000 --- a/guessing-random-number-substrate-custom-blockchain/runtime/build.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn main() { - #[cfg(feature = "std")] - { - substrate_wasm_builder::WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() - .build(); - } -} diff --git a/guessing-random-number-substrate-custom-blockchain/runtime/src/lib.rs b/guessing-random-number-substrate-custom-blockchain/runtime/src/lib.rs deleted file mode 100644 index 15ae259..0000000 --- a/guessing-random-number-substrate-custom-blockchain/runtime/src/lib.rs +++ /dev/null @@ -1,569 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit = "256"] - -// Make the WASM binary available. -#[cfg(feature = "std")] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); - -use pallet_grandpa::AuthorityId as GrandpaId; -use sp_api::impl_runtime_apis; -use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::{ - create_runtime_str, generic, impl_opaque_keys, - traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, One, Verify, - }, - transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, MultiSignature, -}; -use sp_std::prelude::*; -#[cfg(feature = "std")] -use sp_version::NativeVersion; -use sp_version::RuntimeVersion; - -// A few exports that help ease life for downstream crates. -pub use frame_support::{ - construct_runtime, parameter_types, - traits::{ - ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, KeyOwnerProofSystem, Randomness, - StorageInfo, - }, - weights::{ - constants::{ - BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, - }, - IdentityFee, Weight, - }, - StorageValue, -}; -pub use frame_system::Call as SystemCall; -pub use pallet_balances::Call as BalancesCall; -pub use pallet_timestamp::Call as TimestampCall; -use pallet_transaction_payment::{ConstFeeMultiplier, CurrencyAdapter, Multiplier}; -#[cfg(any(feature = "std", test))] -pub use sp_runtime::BuildStorage; -pub use sp_runtime::{Perbill, Permill}; - -/// Import the template pallet. -pub use pallet_template; - -/// An index to a block. -pub type BlockNumber = u32; - -/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; - -/// Some way of identifying an account on the chain. We intentionally make it equivalent -/// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; - -/// Balance of an account. -pub type Balance = u128; - -/// Index of a transaction in the chain. -pub type Nonce = u32; - -/// A hash of some data used by the chain. -pub type Hash = sp_core::H256; - -/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know -/// the specifics of the runtime. They can then be made to be agnostic over specific formats -/// of data like extrinsics, allowing for them to continue syncing the network through upgrades -/// to even the core data structures. -pub mod opaque { - use super::*; - - pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; - - /// Opaque block header type. - pub type Header = generic::Header; - /// Opaque block type. - pub type Block = generic::Block; - /// Opaque block identifier type. - pub type BlockId = generic::BlockId; - - impl_opaque_keys! { - pub struct SessionKeys { - pub aura: Aura, - pub grandpa: Grandpa, - } - } -} - -// To learn more about runtime versioning, see: -// https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning -#[sp_version::runtime_version] -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("Guessing Random Number Game"), - impl_name: create_runtime_str!("Guessing Random Number Game"), - authoring_version: 1, - // The version of the runtime specification. A full node will not attempt to use its native - // runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, - // `spec_version`, and `authoring_version` are the same between Wasm and native. - // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use - // the compatible custom types. - spec_version: 100, // updated runtime version - impl_version: 1, - apis: RUNTIME_API_VERSIONS, - transaction_version: 1, - state_version: 1, -}; - -/// This determines the average expected block time that we are targeting. -/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. -/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked -/// up by `pallet_aura` to implement `fn slot_duration()`. -/// -/// Change this to adjust the block time. -pub const MILLISECS_PER_BLOCK: u64 = 6000; - -// NOTE: Currently it is not possible to change the slot duration after the chain has started. -// Attempting to do so will brick block production. -pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; - -// Time is measured by number of blocks. -pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); -pub const HOURS: BlockNumber = MINUTES * 60; -pub const DAYS: BlockNumber = HOURS * 24; - -/// The version information used to identify this runtime when compiled natively. -#[cfg(feature = "std")] -pub fn native_version() -> NativeVersion { - NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } -} - -const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); - -parameter_types! { - pub const BlockHashCount: BlockNumber = 2400; - pub const Version: RuntimeVersion = VERSION; - /// We allow for 2 seconds of compute with a 6 second average block time. - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::with_sensible_defaults( - Weight::from_parts(2u64 * WEIGHT_REF_TIME_PER_SECOND, u64::MAX), - NORMAL_DISPATCH_RATIO, - ); - pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength - ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub const SS58Prefix: u8 = 42; -} - -// Configure FRAME pallets to include in runtime. - -impl frame_system::Config for Runtime { - /// The basic call filter to use in dispatchable. - type BaseCallFilter = frame_support::traits::Everything; - /// The block type for the runtime. - type Block = Block; - /// Block & extrinsics weights: base values and limits. - type BlockWeights = BlockWeights; - /// The maximum length of a block (in bytes). - type BlockLength = BlockLength; - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - /// The type for storing how many extrinsics an account has signed. - type Nonce = Nonce; - /// The type for hashing blocks and tries. - type Hash = Hash; - /// The hashing algorithm used. - type Hashing = BlakeTwo256; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - /// The ubiquitous origin type. - type RuntimeOrigin = RuntimeOrigin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; - /// Version of the runtime. - type Version = Version; - /// Converts a module to the index of the module in `construct_runtime!`. - /// - /// This type is being generated by `construct_runtime!`. - type PalletInfo = PalletInfo; - /// What to do if a new account is created. - type OnNewAccount = (); - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); - /// This is used as an identifier of the chain. 42 is the generic substrate prefix. - type SS58Prefix = SS58Prefix; - /// The set code logic, just the default since we're not a parachain. - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -impl pallet_aura::Config for Runtime { - type AuthorityId = AuraId; - type DisabledValidators = (); - type MaxAuthorities = ConstU32<32>; - type AllowMultipleBlocksPerSlot = ConstBool; -} - -impl pallet_grandpa::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - - type WeightInfo = (); - type MaxAuthorities = ConstU32<32>; - type MaxSetIdSessionEntries = ConstU64<0>; - - type KeyOwnerProof = sp_core::Void; - type EquivocationReportSystem = (); -} - -impl pallet_timestamp::Config for Runtime { - /// A timestamp: milliseconds since the unix epoch. - type Moment = u64; - type OnTimestampSet = Aura; - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; - type WeightInfo = (); -} - -/// Existential deposit. -pub const EXISTENTIAL_DEPOSIT: u128 = 500; - -impl pallet_balances::Config for Runtime { - type MaxLocks = ConstU32<50>; - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - /// The type for recording an account's balance. - type Balance = Balance; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ConstU128; - type AccountStore = System; - type WeightInfo = pallet_balances::weights::SubstrateWeight; - type FreezeIdentifier = (); - type MaxFreezes = (); - type RuntimeHoldReason = (); - type MaxHolds = (); -} - -parameter_types! { - pub FeeMultiplier: Multiplier = Multiplier::one(); -} - -impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = CurrencyAdapter; - type OperationalFeeMultiplier = ConstU8<5>; - type WeightToFee = IdentityFee; - type LengthToFee = IdentityFee; - type FeeMultiplierUpdate = ConstFeeMultiplier; -} - -impl pallet_sudo::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type WeightInfo = pallet_sudo::weights::SubstrateWeight; -} - -// Create the runtime by composing the FRAME pallets that were previously configured. -construct_runtime!( - pub struct Runtime { - System: frame_system, - Timestamp: pallet_timestamp, - Aura: pallet_aura, - Grandpa: pallet_grandpa, - Balances: pallet_balances, - TransactionPayment: pallet_transaction_payment, - Sudo: pallet_sudo, - // Include the custom logic from the pallet-template in the runtime. - GuessedNumberGame: pallet_template, - } -); - -/// The address format for describing accounts. -pub type Address = sp_runtime::MultiAddress; -/// Block header type as expected by this runtime. -pub type Header = generic::Header; -/// Block type as expected by this runtime. -pub type Block = generic::Block; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment, -); - -/// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; -/// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; -/// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, ->; - -#[cfg(feature = "runtime-benchmarks")] -#[macro_use] -extern crate frame_benchmarking; - -#[cfg(feature = "runtime-benchmarks")] -mod benches { - define_benchmarks!( - [frame_benchmarking, BaselineBench::] - [frame_system, SystemBench::] - [pallet_balances, Balances] - [pallet_timestamp, Timestamp] - [pallet_sudo, Sudo] - [pallet_template, GuessedNumberGame] - ); -} - -impl_runtime_apis! { - impl sp_api::Core for Runtime { - fn version() -> RuntimeVersion { - VERSION - } - - fn execute_block(block: Block) { - Executive::execute_block(block); - } - - fn initialize_block(header: &::Header) { - Executive::initialize_block(header) - } - } - - impl sp_api::Metadata for Runtime { - fn metadata() -> OpaqueMetadata { - OpaqueMetadata::new(Runtime::metadata().into()) - } - - fn metadata_at_version(version: u32) -> Option { - Runtime::metadata_at_version(version) - } - - fn metadata_versions() -> sp_std::vec::Vec { - Runtime::metadata_versions() - } - } - - impl sp_block_builder::BlockBuilder for Runtime { - fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { - Executive::apply_extrinsic(extrinsic) - } - - fn finalize_block() -> ::Header { - Executive::finalize_block() - } - - fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { - data.create_extrinsics() - } - - fn check_inherents( - block: Block, - data: sp_inherents::InherentData, - ) -> sp_inherents::CheckInherentsResult { - data.check_extrinsics(&block) - } - } - - impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { - fn validate_transaction( - source: TransactionSource, - tx: ::Extrinsic, - block_hash: ::Hash, - ) -> TransactionValidity { - Executive::validate_transaction(source, tx, block_hash) - } - } - - impl sp_offchain::OffchainWorkerApi for Runtime { - fn offchain_worker(header: &::Header) { - Executive::offchain_worker(header) - } - } - - impl sp_consensus_aura::AuraApi for Runtime { - fn slot_duration() -> sp_consensus_aura::SlotDuration { - sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) - } - - fn authorities() -> Vec { - Aura::authorities().into_inner() - } - } - - impl sp_session::SessionKeys for Runtime { - fn generate_session_keys(seed: Option>) -> Vec { - opaque::SessionKeys::generate(seed) - } - - fn decode_session_keys( - encoded: Vec, - ) -> Option, KeyTypeId)>> { - opaque::SessionKeys::decode_into_raw_public_keys(&encoded) - } - } - - impl sp_consensus_grandpa::GrandpaApi for Runtime { - fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList { - Grandpa::grandpa_authorities() - } - - fn current_set_id() -> sp_consensus_grandpa::SetId { - Grandpa::current_set_id() - } - - fn submit_report_equivocation_unsigned_extrinsic( - _equivocation_proof: sp_consensus_grandpa::EquivocationProof< - ::Hash, - NumberFor, - >, - _key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof, - ) -> Option<()> { - None - } - - fn generate_key_ownership_proof( - _set_id: sp_consensus_grandpa::SetId, - _authority_id: GrandpaId, - ) -> Option { - // NOTE: this is the only implementation possible since we've - // defined our key owner proof type as a bottom type (i.e. a type - // with no values). - None - } - } - - impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(account: AccountId) -> Nonce { - System::account_nonce(account) - } - } - - impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { - fn query_info( - uxt: ::Extrinsic, - len: u32, - ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { - TransactionPayment::query_info(uxt, len) - } - fn query_fee_details( - uxt: ::Extrinsic, - len: u32, - ) -> pallet_transaction_payment::FeeDetails { - TransactionPayment::query_fee_details(uxt, len) - } - fn query_weight_to_fee(weight: Weight) -> Balance { - TransactionPayment::weight_to_fee(weight) - } - fn query_length_to_fee(length: u32) -> Balance { - TransactionPayment::length_to_fee(length) - } - } - - impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi - for Runtime - { - fn query_call_info( - call: RuntimeCall, - len: u32, - ) -> pallet_transaction_payment::RuntimeDispatchInfo { - TransactionPayment::query_call_info(call, len) - } - fn query_call_fee_details( - call: RuntimeCall, - len: u32, - ) -> pallet_transaction_payment::FeeDetails { - TransactionPayment::query_call_fee_details(call, len) - } - fn query_weight_to_fee(weight: Weight) -> Balance { - TransactionPayment::weight_to_fee(weight) - } - fn query_length_to_fee(length: u32) -> Balance { - TransactionPayment::length_to_fee(length) - } - } - - #[cfg(feature = "runtime-benchmarks")] - impl frame_benchmarking::Benchmark for Runtime { - fn benchmark_metadata(extra: bool) -> ( - Vec, - Vec, - ) { - use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; - use frame_support::traits::StorageInfoTrait; - use frame_system_benchmarking::Pallet as SystemBench; - use baseline::Pallet as BaselineBench; - - let mut list = Vec::::new(); - list_benchmarks!(list, extra); - - let storage_info = AllPalletsWithSystem::storage_info(); - - (list, storage_info) - } - - fn dispatch_benchmark( - config: frame_benchmarking::BenchmarkConfig - ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, TrackedStorageKey}; - - use frame_system_benchmarking::Pallet as SystemBench; - use baseline::Pallet as BaselineBench; - - impl frame_system_benchmarking::Config for Runtime {} - impl baseline::Config for Runtime {} - - use frame_support::traits::WhitelistedStorageKeys; - let whitelist: Vec = AllPalletsWithSystem::whitelisted_storage_keys(); - - let mut batches = Vec::::new(); - let params = (&config, &whitelist); - add_benchmarks!(params, batches); - - Ok(batches) - } - } - - #[cfg(feature = "try-runtime")] - impl frame_try_runtime::TryRuntime for Runtime { - fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { - // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to - // have a backtrace here. If any of the pre/post migration checks fail, we shall stop - // right here and right now. - let weight = Executive::try_runtime_upgrade(checks).unwrap(); - (weight, BlockWeights::get().max_block) - } - - fn execute_block( - block: Block, - state_root_check: bool, - signature_check: bool, - select: frame_try_runtime::TryStateSelect - ) -> Weight { - // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to - // have a backtrace here. - Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed") - } - } -} - -/// Configure the pallet-template in pallets/template. -impl pallet_template::Config for Runtime { - type RuntimeEvent = RuntimeEvent; -} diff --git a/guessing-random-number-substrate-custom-blockchain/rust-toolchain.toml b/guessing-random-number-substrate-custom-blockchain/rust-toolchain.toml deleted file mode 100644 index 64daeff..0000000 --- a/guessing-random-number-substrate-custom-blockchain/rust-toolchain.toml +++ /dev/null @@ -1,14 +0,0 @@ -[toolchain] -channel = "nightly" -components = [ - "cargo", - "clippy", - "rust-analyzer", - "rust-src", - "rust-std", - "rustc-dev", - "rustc", - "rustfmt", -] -targets = [ "wasm32-unknown-unknown" ] -profile = "minimal" diff --git a/guessing-random-number-substrate-custom-blockchain/rustfmt.toml b/guessing-random-number-substrate-custom-blockchain/rustfmt.toml deleted file mode 100644 index 441913f..0000000 --- a/guessing-random-number-substrate-custom-blockchain/rustfmt.toml +++ /dev/null @@ -1,23 +0,0 @@ -# Basic -hard_tabs = true -max_width = 100 -use_small_heuristics = "Max" -# Imports -imports_granularity = "Crate" -reorder_imports = true -# Consistency -newline_style = "Unix" -# Format comments -comment_width = 100 -wrap_comments = true -# Misc -chain_width = 80 -spaces_around_ranges = false -binop_separator = "Back" -reorder_impl_items = false -match_arm_leading_pipes = "Preserve" -match_arm_blocks = false -match_block_trailing_comma = true -trailing_comma = "Vertical" -trailing_semicolon = false -use_field_init_shorthand = true diff --git a/guessing-random-number-substrate-custom-blockchain/scripts/init.sh b/guessing-random-number-substrate-custom-blockchain/scripts/init.sh deleted file mode 100755 index f976f72..0000000 --- a/guessing-random-number-substrate-custom-blockchain/scripts/init.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -# This script is meant to be run on Unix/Linux based systems -set -e - -echo "*** Initializing WASM build environment" - -if [ -z $CI_PROJECT_NAME ] ; then - rustup update nightly - rustup update stable -fi - -rustup target add wasm32-unknown-unknown --toolchain nightly diff --git a/guessing-random-number-substrate-custom-blockchain/shell.nix b/guessing-random-number-substrate-custom-blockchain/shell.nix deleted file mode 100644 index c08005c..0000000 --- a/guessing-random-number-substrate-custom-blockchain/shell.nix +++ /dev/null @@ -1,35 +0,0 @@ -let - mozillaOverlay = - import (builtins.fetchGit { - url = "https://github.com/mozilla/nixpkgs-mozilla.git"; - rev = "57c8084c7ef41366993909c20491e359bbb90f54"; - }); - pinned = builtins.fetchGit { - # Descriptive name to make the store path easier to identify - url = "https://github.com/nixos/nixpkgs/"; - # Commit hash for nixos-unstable as of 2020-04-26 - # `git ls-remote https://github.com/nixos/nixpkgs nixos-unstable` - ref = "refs/heads/nixos-unstable"; - rev = "1fe6ed37fd9beb92afe90671c0c2a662a03463dd"; - }; - nixpkgs = import pinned { overlays = [ mozillaOverlay ]; }; - toolchain = with nixpkgs; (rustChannelOf { date = "2021-09-14"; channel = "nightly"; }); - rust-wasm = toolchain.rust.override { - targets = [ "wasm32-unknown-unknown" ]; - }; -in -with nixpkgs; pkgs.mkShell { - buildInputs = [ - clang - pkg-config - rust-wasm - ] ++ stdenv.lib.optionals stdenv.isDarwin [ - darwin.apple_sdk.frameworks.Security - ]; - - LIBCLANG_PATH = "${llvmPackages.libclang}/lib"; - PROTOC = "${protobuf}/bin/protoc"; - RUST_SRC_PATH = "${toolchain.rust-src}/lib/rustlib/src/rust/library/"; - ROCKSDB_LIB_DIR = "${rocksdb}/lib"; - -} diff --git a/substrate-blockchain/custom-token-substrate-pallet/Cargo.toml b/substrate-blockchain/custom-token-substrate-pallet/Cargo.toml new file mode 100644 index 0000000..fe63f80 --- /dev/null +++ b/substrate-blockchain/custom-token-substrate-pallet/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "pallet-custom-token" +version = "4.0.0-dev" +edition = "2021" +license = "MIT-0" +publish = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +[dev-dependencies] +sp-core = { version = "21.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-io = { version = "23.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-runtime = { version = "24.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", +] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] +try-runtime = ["frame-support/try-runtime"] diff --git a/substrate-blockchain/custom-token-substrate-pallet/src/lib.rs b/substrate-blockchain/custom-token-substrate-pallet/src/lib.rs new file mode 100644 index 0000000..016a4ab --- /dev/null +++ b/substrate-blockchain/custom-token-substrate-pallet/src/lib.rs @@ -0,0 +1,78 @@ +#![cfg_attr(not(feature = "std"), no_std)] +pub use pallet::*; + +#[frame_support::pallet] +pub mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::storage] + type BalanceStore = StorageMap<_, Blake2_128Concat, T::AccountId, u32>; + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + Balance { dest: T::AccountId, amount: u32 }, + } + + #[pallet::call] + impl Pallet { + #[pallet::weight(0)] + #[pallet::call_index(1)] + pub fn add_amount(origin: OriginFor, dest: T::AccountId, amount: u32) -> DispatchResult { + ensure_root(origin)?; + + >::insert(&dest, amount); + + Ok(()) + } + + #[pallet::weight(0)] + #[pallet::call_index(2)] + pub fn my_transfer( + origin: OriginFor, + dest: T::AccountId, + amount: u32, + ) -> DispatchResult { + let owner = ensure_signed(origin)?; + + >::mutate(&owner, |balance| { + *balance = Some(balance.unwrap() - amount); + }); + + >::mutate(&dest, |balance| { + *balance = Some(balance.unwrap() + amount); + }); + + Ok(()) + } + + #[pallet::weight(0)] + #[pallet::call_index(3)] + pub fn get_balance(origin: OriginFor) -> DispatchResult { + let owner = ensure_signed(origin)?; + + let balance = >::get(&owner); + + match balance { + Some(balance) => Self::deposit_event(Event::Balance { + dest: owner, + amount: balance, + }), + None => Self::deposit_event(Event::Balance { + dest: owner, + amount: 0, + }), + } + + Ok(()) + } + } +} diff --git a/guessing-random-number-substrate-custom-blockchain/Cargo.toml b/substrate-blockchain/guessing-random-number-game/Cargo.toml similarity index 100% rename from guessing-random-number-substrate-custom-blockchain/Cargo.toml rename to substrate-blockchain/guessing-random-number-game/Cargo.toml diff --git a/guessing-random-number-substrate-custom-blockchain/node/Cargo.toml b/substrate-blockchain/guessing-random-number-game/node/Cargo.toml similarity index 100% rename from guessing-random-number-substrate-custom-blockchain/node/Cargo.toml rename to substrate-blockchain/guessing-random-number-game/node/Cargo.toml diff --git a/guessing-random-number-substrate-custom-blockchain/node/build.rs b/substrate-blockchain/guessing-random-number-game/node/build.rs similarity index 62% rename from guessing-random-number-substrate-custom-blockchain/node/build.rs rename to substrate-blockchain/guessing-random-number-game/node/build.rs index e3bfe31..f9d839f 100644 --- a/guessing-random-number-substrate-custom-blockchain/node/build.rs +++ b/substrate-blockchain/guessing-random-number-game/node/build.rs @@ -1,7 +1,7 @@ use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; fn main() { - generate_cargo_keys(); + generate_cargo_keys(); - rerun_if_git_head_changed(); + rerun_if_git_head_changed(); } diff --git a/substrate-blockchain/guessing-random-number-game/node/src/benchmarking.rs b/substrate-blockchain/guessing-random-number-game/node/src/benchmarking.rs new file mode 100644 index 0000000..7b5bda9 --- /dev/null +++ b/substrate-blockchain/guessing-random-number-game/node/src/benchmarking.rs @@ -0,0 +1,172 @@ +//! Setup code for [`super::command`] which would otherwise bloat that module. +//! +//! Should only be used for benchmarking as it may break in other contexts. + +use crate::service::FullClient; + +use node_template_runtime as runtime; +use runtime::{AccountId, Balance, BalancesCall, SystemCall}; +use sc_cli::Result; +use sc_client_api::BlockBackend; +use sp_core::{Encode, Pair}; +use sp_inherents::{InherentData, InherentDataProvider}; +use sp_keyring::Sr25519Keyring; +use sp_runtime::{OpaqueExtrinsic, SaturatedConversion}; + +use std::{sync::Arc, time::Duration}; + +/// Generates extrinsics for the `benchmark overhead` command. +/// +/// Note: Should only be used for benchmarking. +pub struct RemarkBuilder { + client: Arc, +} + +impl RemarkBuilder { + /// Creates a new [`Self`] from the given client. + pub fn new(client: Arc) -> Self { + Self { client } + } +} + +impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder { + fn pallet(&self) -> &str { + "system" + } + + fn extrinsic(&self) -> &str { + "remark" + } + + fn build(&self, nonce: u32) -> std::result::Result { + let acc = Sr25519Keyring::Bob.pair(); + let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( + self.client.as_ref(), + acc, + SystemCall::remark { remark: vec![] }.into(), + nonce, + ) + .into(); + + Ok(extrinsic) + } +} + +/// Generates `Balances::TransferKeepAlive` extrinsics for the benchmarks. +/// +/// Note: Should only be used for benchmarking. +pub struct TransferKeepAliveBuilder { + client: Arc, + dest: AccountId, + value: Balance, +} + +impl TransferKeepAliveBuilder { + /// Creates a new [`Self`] from the given client. + pub fn new(client: Arc, dest: AccountId, value: Balance) -> Self { + Self { + client, + dest, + value, + } + } +} + +impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { + fn pallet(&self) -> &str { + "balances" + } + + fn extrinsic(&self) -> &str { + "transfer_keep_alive" + } + + fn build(&self, nonce: u32) -> std::result::Result { + let acc = Sr25519Keyring::Bob.pair(); + let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( + self.client.as_ref(), + acc, + BalancesCall::transfer_keep_alive { + dest: self.dest.clone().into(), + value: self.value, + } + .into(), + nonce, + ) + .into(); + + Ok(extrinsic) + } +} + +/// Create a transaction using the given `call`. +/// +/// Note: Should only be used for benchmarking. +pub fn create_benchmark_extrinsic( + client: &FullClient, + sender: sp_core::sr25519::Pair, + call: runtime::RuntimeCall, + nonce: u32, +) -> runtime::UncheckedExtrinsic { + let genesis_hash = client + .block_hash(0) + .ok() + .flatten() + .expect("Genesis block exists; qed"); + let best_hash = client.chain_info().best_hash; + let best_block = client.chain_info().best_number; + + let period = runtime::BlockHashCount::get() + .checked_next_power_of_two() + .map(|c| c / 2) + .unwrap_or(2) as u64; + let extra: runtime::SignedExtra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(sp_runtime::generic::Era::mortal( + period, + best_block.saturated_into(), + )), + frame_system::CheckNonce::::from(nonce), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + ); + + let raw_payload = runtime::SignedPayload::from_raw( + call.clone(), + extra.clone(), + ( + (), + runtime::VERSION.spec_version, + runtime::VERSION.transaction_version, + genesis_hash, + best_hash, + (), + (), + (), + ), + ); + let signature = raw_payload.using_encoded(|e| sender.sign(e)); + + runtime::UncheckedExtrinsic::new_signed( + call, + sp_runtime::AccountId32::from(sender.public()).into(), + runtime::Signature::Sr25519(signature), + extra, + ) +} + +/// Generates inherent data for the `benchmark overhead` command. +/// +/// Note: Should only be used for benchmarking. +pub fn inherent_benchmark_data() -> Result { + let mut inherent_data = InherentData::new(); + let d = Duration::from_millis(0); + let timestamp = sp_timestamp::InherentDataProvider::new(d.into()); + + futures::executor::block_on(timestamp.provide_inherent_data(&mut inherent_data)) + .map_err(|e| format!("creating inherent data: {:?}", e))?; + Ok(inherent_data) +} diff --git a/substrate-blockchain/guessing-random-number-game/node/src/chain_spec.rs b/substrate-blockchain/guessing-random-number-game/node/src/chain_spec.rs new file mode 100644 index 0000000..cf8d26e --- /dev/null +++ b/substrate-blockchain/guessing-random-number-game/node/src/chain_spec.rs @@ -0,0 +1,168 @@ +use node_template_runtime::{ + AccountId, AuraConfig, BalancesConfig, GrandpaConfig, RuntimeGenesisConfig, Signature, + SudoConfig, SystemConfig, WASM_BINARY, +}; +use sc_service::ChainType; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_consensus_grandpa::AuthorityId as GrandpaId; +use sp_core::{sr25519, Pair, Public}; +use sp_runtime::traits::{IdentifyAccount, Verify}; + +// The URL for the telemetry server. +// const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; + +/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. +pub type ChainSpec = sc_service::GenericChainSpec; + +/// Generate a crypto pair from seed. +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +type AccountPublic = ::Signer; + +/// Generate an account ID from seed. +pub fn get_account_id_from_seed(seed: &str) -> AccountId +where + AccountPublic: From<::Public>, +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} + +/// Generate an Aura authority key. +pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { + (get_from_seed::(s), get_from_seed::(s)) +} + +pub fn development_config() -> Result { + let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; + + Ok(ChainSpec::from_genesis( + // Name + "Development", + // ID + "dev", + ChainType::Development, + move || { + testnet_genesis( + wasm_binary, + // Initial PoA authorities + vec![authority_keys_from_seed("Alice")], + // Sudo account + get_account_id_from_seed::("Alice"), + // Pre-funded accounts + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + ], + true, + ) + }, + // Bootnodes + vec![], + // Telemetry + None, + // Protocol ID + None, + None, + // Properties + None, + // Extensions + None, + )) +} + +pub fn local_testnet_config() -> Result { + let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; + + Ok(ChainSpec::from_genesis( + // Name + "Local Testnet", + // ID + "local_testnet", + ChainType::Local, + move || { + testnet_genesis( + wasm_binary, + // Initial PoA authorities + vec![ + authority_keys_from_seed("Alice"), + authority_keys_from_seed("Bob"), + ], + // Sudo account + get_account_id_from_seed::("Alice"), + // Pre-funded accounts + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ], + true, + ) + }, + // Bootnodes + vec![], + // Telemetry + None, + // Protocol ID + None, + // Properties + None, + None, + // Extensions + None, + )) +} + +/// Configure initial storage state for FRAME modules. +fn testnet_genesis( + wasm_binary: &[u8], + initial_authorities: Vec<(AuraId, GrandpaId)>, + root_key: AccountId, + endowed_accounts: Vec, + _enable_println: bool, +) -> RuntimeGenesisConfig { + RuntimeGenesisConfig { + system: SystemConfig { + // Add Wasm runtime to storage. + code: wasm_binary.to_vec(), + ..Default::default() + }, + balances: BalancesConfig { + // Configure endowed accounts with initial balance of 1 << 60. + balances: endowed_accounts + .iter() + .cloned() + .map(|k| (k, 1 << 60)) + .collect(), + }, + aura: AuraConfig { + authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), + }, + grandpa: GrandpaConfig { + authorities: initial_authorities + .iter() + .map(|x| (x.1.clone(), 1)) + .collect(), + ..Default::default() + }, + sudo: SudoConfig { + // Assign network admin rights. + key: Some(root_key), + }, + transaction_payment: Default::default(), + } +} diff --git a/substrate-blockchain/guessing-random-number-game/node/src/cli.rs b/substrate-blockchain/guessing-random-number-game/node/src/cli.rs new file mode 100644 index 0000000..80245fe --- /dev/null +++ b/substrate-blockchain/guessing-random-number-game/node/src/cli.rs @@ -0,0 +1,54 @@ +use sc_cli::RunCmd; + +#[derive(Debug, clap::Parser)] +pub struct Cli { + #[command(subcommand)] + pub subcommand: Option, + + #[clap(flatten)] + pub run: RunCmd, +} + +#[derive(Debug, clap::Subcommand)] +#[allow(clippy::large_enum_variant)] +pub enum Subcommand { + /// Key management cli utilities + #[command(subcommand)] + Key(sc_cli::KeySubcommand), + + /// Build a chain specification. + BuildSpec(sc_cli::BuildSpecCmd), + + /// Validate blocks. + CheckBlock(sc_cli::CheckBlockCmd), + + /// Export blocks. + ExportBlocks(sc_cli::ExportBlocksCmd), + + /// Export the state of a given block into a chain spec. + ExportState(sc_cli::ExportStateCmd), + + /// Import blocks. + ImportBlocks(sc_cli::ImportBlocksCmd), + + /// Remove the whole chain. + PurgeChain(sc_cli::PurgeChainCmd), + + /// Revert the chain to a previous state. + Revert(sc_cli::RevertCmd), + + /// Sub-commands concerned with benchmarking. + #[command(subcommand)] + Benchmark(frame_benchmarking_cli::BenchmarkCmd), + + /// Try some command against runtime state. + #[cfg(feature = "try-runtime")] + TryRuntime(try_runtime_cli::TryRuntimeCmd), + + /// Try some command against runtime state. Note: `try-runtime` feature must be enabled. + #[cfg(not(feature = "try-runtime"))] + TryRuntime, + + /// Db meta columns information. + ChainInfo(sc_cli::ChainInfoCmd), +} diff --git a/substrate-blockchain/guessing-random-number-game/node/src/command.rs b/substrate-blockchain/guessing-random-number-game/node/src/command.rs new file mode 100644 index 0000000..6c83b2c --- /dev/null +++ b/substrate-blockchain/guessing-random-number-game/node/src/command.rs @@ -0,0 +1,235 @@ +use crate::{ + benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder}, + chain_spec, + cli::{Cli, Subcommand}, + service, +}; +use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory, SUBSTRATE_REFERENCE_HARDWARE}; +use node_template_runtime::{Block, EXISTENTIAL_DEPOSIT}; +use sc_cli::SubstrateCli; +use sc_service::PartialComponents; +use sp_keyring::Sr25519Keyring; + +#[cfg(feature = "try-runtime")] +use try_runtime_cli::block_building_info::timestamp_with_aura_info; + +impl SubstrateCli for Cli { + fn impl_name() -> String { + "Substrate Node".into() + } + + fn impl_version() -> String { + env!("SUBSTRATE_CLI_IMPL_VERSION").into() + } + + fn description() -> String { + env!("CARGO_PKG_DESCRIPTION").into() + } + + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } + + fn support_url() -> String { + "support.anonymous.an".into() + } + + fn copyright_start_year() -> i32 { + 2017 + } + + fn load_spec(&self, id: &str) -> Result, String> { + Ok(match id { + "dev" => Box::new(chain_spec::development_config()?), + "" | "local" => Box::new(chain_spec::local_testnet_config()?), + path => Box::new(chain_spec::ChainSpec::from_json_file( + std::path::PathBuf::from(path), + )?), + }) + } +} + +/// Parse and run command line arguments +pub fn run() -> sc_cli::Result<()> { + let cli = Cli::from_args(); + + match &cli.subcommand { + Some(Subcommand::Key(cmd)) => cmd.run(&cli), + Some(Subcommand::BuildSpec(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) + } + Some(Subcommand::CheckBlock(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + import_queue, + .. + } = service::new_partial(&config)?; + Ok((cmd.run(client, import_queue), task_manager)) + }) + } + Some(Subcommand::ExportBlocks(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + .. + } = service::new_partial(&config)?; + Ok((cmd.run(client, config.database), task_manager)) + }) + } + Some(Subcommand::ExportState(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + .. + } = service::new_partial(&config)?; + Ok((cmd.run(client, config.chain_spec), task_manager)) + }) + } + Some(Subcommand::ImportBlocks(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + import_queue, + .. + } = service::new_partial(&config)?; + Ok((cmd.run(client, import_queue), task_manager)) + }) + } + Some(Subcommand::PurgeChain(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.database)) + } + Some(Subcommand::Revert(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + backend, + .. + } = service::new_partial(&config)?; + let aux_revert = Box::new(|client, _, blocks| { + sc_consensus_grandpa::revert(client, blocks)?; + Ok(()) + }); + Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) + }) + } + Some(Subcommand::Benchmark(cmd)) => { + let runner = cli.create_runner(cmd)?; + + runner.sync_run(|config| { + // This switch needs to be in the client, since the client decides + // which sub-commands it wants to support. + match cmd { + BenchmarkCmd::Pallet(cmd) => { + if !cfg!(feature = "runtime-benchmarks") { + return Err( + "Runtime benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + .into(), + ); + } + + cmd.run::(config) + } + BenchmarkCmd::Block(cmd) => { + let PartialComponents { client, .. } = service::new_partial(&config)?; + cmd.run(client) + } + #[cfg(not(feature = "runtime-benchmarks"))] + BenchmarkCmd::Storage(_) => Err( + "Storage benchmarking can be enabled with `--features runtime-benchmarks`." + .into(), + ), + #[cfg(feature = "runtime-benchmarks")] + BenchmarkCmd::Storage(cmd) => { + let PartialComponents { + client, backend, .. + } = service::new_partial(&config)?; + let db = backend.expose_db(); + let storage = backend.expose_storage(); + + cmd.run(config, client, db, storage) + } + BenchmarkCmd::Overhead(cmd) => { + let PartialComponents { client, .. } = service::new_partial(&config)?; + let ext_builder = RemarkBuilder::new(client.clone()); + + cmd.run( + config, + client, + inherent_benchmark_data()?, + Vec::new(), + &ext_builder, + ) + } + BenchmarkCmd::Extrinsic(cmd) => { + let PartialComponents { client, .. } = service::new_partial(&config)?; + // Register the *Remark* and *TKA* builders. + let ext_factory = ExtrinsicFactory(vec![ + Box::new(RemarkBuilder::new(client.clone())), + Box::new(TransferKeepAliveBuilder::new( + client.clone(), + Sr25519Keyring::Alice.to_account_id(), + EXISTENTIAL_DEPOSIT, + )), + ]); + + cmd.run(client, inherent_benchmark_data()?, Vec::new(), &ext_factory) + } + BenchmarkCmd::Machine(cmd) => { + cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()) + } + } + }) + } + #[cfg(feature = "try-runtime")] + Some(Subcommand::TryRuntime(cmd)) => { + use crate::service::ExecutorDispatch; + use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, NativeExecutionDispatch}; + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + // we don't need any of the components of new_partial, just a runtime, or a task + // manager to do `async_run`. + let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); + let task_manager = + sc_service::TaskManager::new(config.tokio_handle.clone(), registry) + .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; + let info_provider = timestamp_with_aura_info(6000); + + Ok(( + cmd.run::::ExtendHostFunctions, + >, _>(Some(info_provider)), + task_manager, + )) + }) + } + #[cfg(not(feature = "try-runtime"))] + Some(Subcommand::TryRuntime) => Err("TryRuntime wasn't enabled when building the node. \ + You can enable it with `--features try-runtime`." + .into()), + Some(Subcommand::ChainInfo(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run::(&config)) + } + None => { + let runner = cli.create_runner(&cli.run)?; + runner.run_node_until_exit(|config| async move { + service::new_full(config).map_err(sc_cli::Error::Service) + }) + } + } +} diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/lib.rs b/substrate-blockchain/guessing-random-number-game/node/src/lib.rs similarity index 100% rename from guessing-random-number-substrate-custom-blockchain/node/src/lib.rs rename to substrate-blockchain/guessing-random-number-game/node/src/lib.rs diff --git a/guessing-random-number-substrate-custom-blockchain/node/src/main.rs b/substrate-blockchain/guessing-random-number-game/node/src/main.rs similarity index 91% rename from guessing-random-number-substrate-custom-blockchain/node/src/main.rs rename to substrate-blockchain/guessing-random-number-game/node/src/main.rs index 426cbab..33c3195 100644 --- a/guessing-random-number-substrate-custom-blockchain/node/src/main.rs +++ b/substrate-blockchain/guessing-random-number-game/node/src/main.rs @@ -10,5 +10,5 @@ mod command; mod rpc; fn main() -> sc_cli::Result<()> { - command::run() + command::run() } diff --git a/substrate-blockchain/guessing-random-number-game/node/src/rpc.rs b/substrate-blockchain/guessing-random-number-game/node/src/rpc.rs new file mode 100644 index 0000000..041417b --- /dev/null +++ b/substrate-blockchain/guessing-random-number-game/node/src/rpc.rs @@ -0,0 +1,61 @@ +//! A collection of node-specific RPC methods. +//! Substrate provides the `sc-rpc` crate, which defines the core RPC layer +//! used by Substrate nodes. This file extends those RPC definitions with +//! capabilities that are specific to this project's runtime configuration. + +#![warn(missing_docs)] + +use std::sync::Arc; + +use jsonrpsee::RpcModule; +use node_template_runtime::{opaque::Block, AccountId, Balance, Nonce}; +use sc_transaction_pool_api::TransactionPool; +use sp_api::ProvideRuntimeApi; +use sp_block_builder::BlockBuilder; +use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; + +pub use sc_rpc_api::DenyUnsafe; + +/// Full client dependencies. +pub struct FullDeps { + /// The client instance to use. + pub client: Arc, + /// Transaction pool instance. + pub pool: Arc

, + /// Whether to deny unsafe calls + pub deny_unsafe: DenyUnsafe, +} + +/// Instantiate all full RPC extensions. +pub fn create_full( + deps: FullDeps, +) -> Result, Box> +where + C: ProvideRuntimeApi, + C: HeaderBackend + HeaderMetadata + 'static, + C: Send + Sync + 'static, + C::Api: substrate_frame_rpc_system::AccountNonceApi, + C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, + C::Api: BlockBuilder, + P: TransactionPool + 'static, +{ + use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; + use substrate_frame_rpc_system::{System, SystemApiServer}; + + let mut module = RpcModule::new(()); + let FullDeps { + client, + pool, + deny_unsafe, + } = deps; + + module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; + module.merge(TransactionPayment::new(client).into_rpc())?; + + // Extend this RPC with a custom API by using the following syntax. + // `YourRpcStruct` should have a reference to a client, which is needed + // to call into the runtime. + // `module.merge(YourRpcTrait::into_rpc(YourRpcStruct::new(ReferenceToClient, ...)))?;` + + Ok(module) +} diff --git a/substrate-blockchain/guessing-random-number-game/node/src/service.rs b/substrate-blockchain/guessing-random-number-game/node/src/service.rs new file mode 100644 index 0000000..4d81695 --- /dev/null +++ b/substrate-blockchain/guessing-random-number-game/node/src/service.rs @@ -0,0 +1,344 @@ +//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. + +use futures::FutureExt; +use node_template_runtime::{self, opaque::Block, RuntimeApi}; +use sc_client_api::{Backend, BlockBackend}; +use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; +use sc_consensus_grandpa::SharedVoterState; +pub use sc_executor::NativeElseWasmExecutor; +use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncParams}; +use sc_telemetry::{Telemetry, TelemetryWorker}; +use sc_transaction_pool_api::OffchainTransactionPoolFactory; +use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; +use std::{sync::Arc, time::Duration}; + +// Our native executor instance. +pub struct ExecutorDispatch; + +impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { + /// Only enable the benchmarking host functions when we actually want to benchmark. + #[cfg(feature = "runtime-benchmarks")] + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + /// Otherwise we only use the default Substrate host functions. + #[cfg(not(feature = "runtime-benchmarks"))] + type ExtendHostFunctions = (); + + fn dispatch(method: &str, data: &[u8]) -> Option> { + node_template_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + node_template_runtime::native_version() + } +} + +pub(crate) type FullClient = + sc_service::TFullClient>; +type FullBackend = sc_service::TFullBackend; +type FullSelectChain = sc_consensus::LongestChain; + +#[allow(clippy::type_complexity)] +pub fn new_partial( + config: &Configuration, +) -> Result< + sc_service::PartialComponents< + FullClient, + FullBackend, + FullSelectChain, + sc_consensus::DefaultImportQueue, + sc_transaction_pool::FullPool, + ( + sc_consensus_grandpa::GrandpaBlockImport< + FullBackend, + Block, + FullClient, + FullSelectChain, + >, + sc_consensus_grandpa::LinkHalf, + Option, + ), + >, + ServiceError, +> { + let telemetry = config + .telemetry_endpoints + .clone() + .filter(|x| !x.is_empty()) + .map(|endpoints| -> Result<_, sc_telemetry::Error> { + let worker = TelemetryWorker::new(16)?; + let telemetry = worker.handle().new_telemetry(endpoints); + Ok((worker, telemetry)) + }) + .transpose()?; + + let executor = sc_service::new_native_or_wasm_executor(config); + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; + let client = Arc::new(client); + + let telemetry = telemetry.map(|(worker, telemetry)| { + task_manager + .spawn_handle() + .spawn("telemetry", None, worker.run()); + telemetry + }); + + let select_chain = sc_consensus::LongestChain::new(backend.clone()); + + let transaction_pool = sc_transaction_pool::BasicPool::new_full( + config.transaction_pool.clone(), + config.role.is_authority().into(), + config.prometheus_registry(), + task_manager.spawn_essential_handle(), + client.clone(), + ); + + let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( + client.clone(), + &client, + select_chain.clone(), + telemetry.as_ref().map(|x| x.handle()), + )?; + + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; + + let import_queue = + sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: grandpa_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import.clone())), + client: client.clone(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + }, + spawner: &task_manager.spawn_essential_handle(), + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), + })?; + + Ok(sc_service::PartialComponents { + client, + backend, + task_manager, + import_queue, + keystore_container, + select_chain, + transaction_pool, + other: (grandpa_block_import, grandpa_link, telemetry), + }) +} + +/// Builds a new service for a full client. +pub fn new_full(config: Configuration) -> Result { + let sc_service::PartialComponents { + client, + backend, + mut task_manager, + import_queue, + keystore_container, + select_chain, + transaction_pool, + other: (block_import, grandpa_link, mut telemetry), + } = new_partial(&config)?; + + let mut net_config = sc_network::config::FullNetworkConfiguration::new(&config.network); + + let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name( + &client + .block_hash(0) + .ok() + .flatten() + .expect("Genesis block exists; qed"), + &config.chain_spec, + ); + net_config.add_notification_protocol(sc_consensus_grandpa::grandpa_peers_set_config( + grandpa_protocol_name.clone(), + )); + + let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( + backend.clone(), + grandpa_link.shared_authority_set().clone(), + Vec::default(), + )); + + let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + net_config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + block_announce_validator_builder: None, + warp_sync_params: Some(WarpSyncParams::WithProvider(warp_sync)), + })?; + + if config.offchain_worker.enabled { + task_manager.spawn_handle().spawn( + "offchain-workers-runner", + "offchain-worker", + sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { + runtime_api_provider: client.clone(), + is_validator: config.role.is_authority(), + keystore: Some(keystore_container.keystore()), + offchain_db: backend.offchain_storage(), + transaction_pool: Some(OffchainTransactionPoolFactory::new( + transaction_pool.clone(), + )), + network_provider: network.clone(), + enable_http_requests: true, + custom_extensions: |_| vec![], + }) + .run(client.clone(), task_manager.spawn_handle()) + .boxed(), + ); + } + + let role = config.role.clone(); + let force_authoring = config.force_authoring; + let backoff_authoring_blocks: Option<()> = None; + let name = config.network.node_name.clone(); + let enable_grandpa = !config.disable_grandpa; + let prometheus_registry = config.prometheus_registry().cloned(); + + let rpc_extensions_builder = { + let client = client.clone(); + let pool = transaction_pool.clone(); + + Box::new(move |deny_unsafe, _| { + let deps = crate::rpc::FullDeps { + client: client.clone(), + pool: pool.clone(), + deny_unsafe, + }; + crate::rpc::create_full(deps).map_err(Into::into) + }) + }; + + let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { + network: network.clone(), + client: client.clone(), + keystore: keystore_container.keystore(), + task_manager: &mut task_manager, + transaction_pool: transaction_pool.clone(), + rpc_builder: rpc_extensions_builder, + backend, + system_rpc_tx, + tx_handler_controller, + sync_service: sync_service.clone(), + config, + telemetry: telemetry.as_mut(), + })?; + + if role.is_authority() { + let proposer_factory = sc_basic_authorship::ProposerFactory::new( + task_manager.spawn_handle(), + client.clone(), + transaction_pool.clone(), + prometheus_registry.as_ref(), + telemetry.as_ref().map(|x| x.handle()), + ); + + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; + + let aura = sc_consensus_aura::start_aura::( + StartAuraParams { + slot_duration, + client, + select_chain, + block_import, + proposer_factory, + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + }, + force_authoring, + backoff_authoring_blocks, + keystore: keystore_container.keystore(), + sync_oracle: sync_service.clone(), + justification_sync_link: sync_service.clone(), + block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + max_block_proposal_slot_portion: None, + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), + }, + )?; + + // the AURA authoring task is considered essential, i.e. if it + // fails we take down the service with it. + task_manager + .spawn_essential_handle() + .spawn_blocking("aura", Some("block-authoring"), aura); + } + + if enable_grandpa { + // if the node isn't actively participating in consensus then it doesn't + // need a keystore, regardless of which protocol we use below. + let keystore = if role.is_authority() { + Some(keystore_container.keystore()) + } else { + None + }; + + let grandpa_config = sc_consensus_grandpa::Config { + // FIXME #1578 make this available through chainspec + gossip_duration: Duration::from_millis(333), + justification_period: 512, + name: Some(name), + observer_enabled: false, + keystore, + local_role: role, + telemetry: telemetry.as_ref().map(|x| x.handle()), + protocol_name: grandpa_protocol_name, + }; + + // start the full GRANDPA voter + // NOTE: non-authorities could run the GRANDPA observer protocol, but at + // this point the full voter should provide better guarantees of block + // and vote data availability than the observer. The observer has not + // been tested extensively yet and having most nodes in a network run it + // could lead to finality stalls. + let grandpa_config = sc_consensus_grandpa::GrandpaParams { + config: grandpa_config, + link: grandpa_link, + network, + sync: Arc::new(sync_service), + voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(), + prometheus_registry, + shared_voter_state: SharedVoterState::empty(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool), + }; + + // the GRANDPA voter task is considered infallible, i.e. + // if it fails we take down the service with it. + task_manager.spawn_essential_handle().spawn_blocking( + "grandpa-voter", + None, + sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?, + ); + } + + network_starter.start_network(); + Ok(task_manager) +} diff --git a/guessing-random-number-substrate-custom-blockchain/pallets/template/Cargo.toml b/substrate-blockchain/guessing-random-number-game/pallets/template/Cargo.toml similarity index 100% rename from guessing-random-number-substrate-custom-blockchain/pallets/template/Cargo.toml rename to substrate-blockchain/guessing-random-number-game/pallets/template/Cargo.toml diff --git a/substrate-blockchain/guessing-random-number-game/pallets/template/src/lib.rs b/substrate-blockchain/guessing-random-number-game/pallets/template/src/lib.rs new file mode 100644 index 0000000..8e7a98b --- /dev/null +++ b/substrate-blockchain/guessing-random-number-game/pallets/template/src/lib.rs @@ -0,0 +1,124 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; + +#[frame_support::pallet] +pub mod pallet { + + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + // pub use frame_support::traits::Randomness; + + #[pallet::pallet] + // #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + /// Configure the pallet by specifying the parameters and types on which it depends. + #[pallet::config] + pub trait Config: frame_system::Config { + /// Because this pallet emits events, it depends on the runtime's definition of an event. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::storage] + pub(super) type TargetNumber = StorageValue<_, u32, ValueQuery>; + + #[pallet::storage] + pub(super) type Guesses = StorageMap<_, Blake2_128Concat, u32, (T::AccountId, u32)>; + + // Pallets use events to inform users when important changes are made. + // Event documentation should end with an array that provides descriptive names for parameters. + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + TargetNotSet, + + ExactNumber { who: T::AccountId, number: u32 }, + + TargetNumberChanged, + + TargetNumberRemoved, + + GuessedNumber { who: T::AccountId, number: u32 }, + } + + // Errors inform users that something went wrong. + #[pallet::error] + pub enum Error { + TargetNotSet, + + PredecessorNumber, + + SuccessorNumber, + + TooManyTurns, + } + + // Dispatchable functions allow users to interact with the pallet and invoke state changes. + // These functions materialize as "extrinsics", which are often compared to transactions. + // Dispatchable functions must be annotated with a weight and must return a DispatchResult. + + #[pallet::call] + impl Pallet { + #[pallet::weight(0)] + #[pallet::call_index(1)] + pub fn set_target(origin: OriginFor, number: u32) -> DispatchResult { + // Check that the extrinsic was root. + // This function will return an error if the extrinsic is not signed. + ensure_root(origin)?; + Self::deposit_event(Event::TargetNumberChanged); + TargetNumber::::put(number); + + Ok(()) + } + + #[pallet::weight(0)] + #[pallet::call_index(2)] + pub fn check_with(origin: OriginFor, number: u32) -> DispatchResult { + if !TargetNumber::::exists() { + return Err(Error::::TargetNotSet.into()); + } + + // Check that the extrinsic was signed and get the signer. + // This function will return an error if the extrinsic is not signed. + let sender = ensure_signed(origin)?; + + let target = TargetNumber::::get(); + + Self::deposit_event(Event::GuessedNumber { + who: sender.clone(), + number, + }); + + if number == target { + Self::deposit_event(Event::ExactNumber { + who: sender, + number, + }); + TargetNumber::::kill(); + Self::deposit_event(Event::TargetNumberRemoved); + } else if number < target { + return Err(Error::::PredecessorNumber.into()); + } else { + return Err(Error::::SuccessorNumber.into()); + } + + return Ok(()); + } + + #[pallet::weight(0)] + #[pallet::call_index(3)] + pub fn remove_target(origin: OriginFor) -> DispatchResult { + // Check that the extrinsic was root. + // This function will return an error if the extrinsic is not signed. + ensure_root(origin)?; + ensure!(TargetNumber::::exists(), Error::::TargetNotSet); + + TargetNumber::::kill(); + + Self::deposit_event(Event::TargetNumberRemoved); + Ok(()) + } + } +} diff --git a/guessing-random-number-substrate-custom-blockchain/runtime/Cargo.toml b/substrate-blockchain/guessing-random-number-game/runtime/Cargo.toml similarity index 100% rename from guessing-random-number-substrate-custom-blockchain/runtime/Cargo.toml rename to substrate-blockchain/guessing-random-number-game/runtime/Cargo.toml diff --git a/substrate-blockchain/guessing-random-number-game/runtime/build.rs b/substrate-blockchain/guessing-random-number-game/runtime/build.rs new file mode 100644 index 0000000..8f021e8 --- /dev/null +++ b/substrate-blockchain/guessing-random-number-game/runtime/build.rs @@ -0,0 +1,10 @@ +fn main() { + #[cfg(feature = "std")] + { + substrate_wasm_builder::WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build(); + } +} diff --git a/substrate-blockchain/guessing-random-number-game/runtime/src/lib.rs b/substrate-blockchain/guessing-random-number-game/runtime/src/lib.rs new file mode 100644 index 0000000..89cdbfc --- /dev/null +++ b/substrate-blockchain/guessing-random-number-game/runtime/src/lib.rs @@ -0,0 +1,572 @@ +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +use pallet_grandpa::AuthorityId as GrandpaId; +use sp_api::impl_runtime_apis; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{ + AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, One, Verify, + }, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, MultiSignature, +}; +use sp_std::prelude::*; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; + +// A few exports that help ease life for downstream crates. +pub use frame_support::{ + construct_runtime, parameter_types, + traits::{ + ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, KeyOwnerProofSystem, Randomness, + StorageInfo, + }, + weights::{ + constants::{ + BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, + }, + IdentityFee, Weight, + }, + StorageValue, +}; +pub use frame_system::Call as SystemCall; +pub use pallet_balances::Call as BalancesCall; +pub use pallet_timestamp::Call as TimestampCall; +use pallet_transaction_payment::{ConstFeeMultiplier, CurrencyAdapter, Multiplier}; +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use sp_runtime::{Perbill, Permill}; + +/// Import the template pallet. +pub use pallet_template; + +/// An index to a block. +pub type BlockNumber = u32; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// Balance of an account. +pub type Balance = u128; + +/// Index of a transaction in the chain. +pub type Nonce = u32; + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core data structures. +pub mod opaque { + use super::*; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + + /// Opaque block header type. + pub type Header = generic::Header; + /// Opaque block type. + pub type Block = generic::Block; + /// Opaque block identifier type. + pub type BlockId = generic::BlockId; + + impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + pub grandpa: Grandpa, + } + } +} + +// To learn more about runtime versioning, see: +// https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning +#[sp_version::runtime_version] +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("Guessing Random Number Game"), + impl_name: create_runtime_str!("Guessing Random Number Game"), + authoring_version: 1, + // The version of the runtime specification. A full node will not attempt to use its native + // runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, + // `spec_version`, and `authoring_version` are the same between Wasm and native. + // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use + // the compatible custom types. + spec_version: 100, // updated runtime version + impl_version: 1, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, + state_version: 1, +}; + +/// This determines the average expected block time that we are targeting. +/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. +/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked +/// up by `pallet_aura` to implement `fn slot_duration()`. +/// +/// Change this to adjust the block time. +pub const MILLISECS_PER_BLOCK: u64 = 6000; + +// NOTE: Currently it is not possible to change the slot duration after the chain has started. +// Attempting to do so will brick block production. +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +// Time is measured by number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); + +parameter_types! { + pub const BlockHashCount: BlockNumber = 2400; + pub const Version: RuntimeVersion = VERSION; + /// We allow for 2 seconds of compute with a 6 second average block time. + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::with_sensible_defaults( + Weight::from_parts(2u64 * WEIGHT_REF_TIME_PER_SECOND, u64::MAX), + NORMAL_DISPATCH_RATIO, + ); + pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength + ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub const SS58Prefix: u8 = 42; +} + +// Configure FRAME pallets to include in runtime. + +impl frame_system::Config for Runtime { + /// The basic call filter to use in dispatchable. + type BaseCallFilter = frame_support::traits::Everything; + /// The block type for the runtime. + type Block = Block; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = BlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = BlockLength; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The type for storing how many extrinsics an account has signed. + type Nonce = Nonce; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// Version of the runtime. + type Version = Version; + /// Converts a module to the index of the module in `construct_runtime!`. + /// + /// This type is being generated by `construct_runtime!`. + type PalletInfo = PalletInfo; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// The set code logic, just the default since we're not a parachain. + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_aura::Config for Runtime { + type AuthorityId = AuraId; + type DisabledValidators = (); + type MaxAuthorities = ConstU32<32>; + type AllowMultipleBlocksPerSlot = ConstBool; +} + +impl pallet_grandpa::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + + type WeightInfo = (); + type MaxAuthorities = ConstU32<32>; + type MaxSetIdSessionEntries = ConstU64<0>; + + type KeyOwnerProof = sp_core::Void; + type EquivocationReportSystem = (); +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; + type WeightInfo = (); +} + +/// Existential deposit. +pub const EXISTENTIAL_DEPOSIT: u128 = 500; + +impl pallet_balances::Config for Runtime { + type MaxLocks = ConstU32<50>; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU128; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; + type FreezeIdentifier = (); + type MaxFreezes = (); + type RuntimeHoldReason = (); + type MaxHolds = (); +} + +parameter_types! { + pub FeeMultiplier: Multiplier = Multiplier::one(); +} + +impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = CurrencyAdapter; + type OperationalFeeMultiplier = ConstU8<5>; + type WeightToFee = IdentityFee; + type LengthToFee = IdentityFee; + type FeeMultiplierUpdate = ConstFeeMultiplier; +} + +impl pallet_sudo::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type WeightInfo = pallet_sudo::weights::SubstrateWeight; +} + +// Create the runtime by composing the FRAME pallets that were previously configured. +construct_runtime!( + pub struct Runtime { + System: frame_system, + Timestamp: pallet_timestamp, + Aura: pallet_aura, + Grandpa: pallet_grandpa, + Balances: pallet_balances, + TransactionPayment: pallet_transaction_payment, + Sudo: pallet_sudo, + // Include the custom logic from the pallet-template in the runtime. + GuessedNumberGame: pallet_template, + } +); + +/// The address format for describing accounts. +pub type Address = sp_runtime::MultiAddress; +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); + +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; +/// The payload being signed in transactions. +pub type SignedPayload = generic::SignedPayload; +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; + +#[cfg(feature = "runtime-benchmarks")] +#[macro_use] +extern crate frame_benchmarking; + +#[cfg(feature = "runtime-benchmarks")] +mod benches { + define_benchmarks!( + [frame_benchmarking, BaselineBench::] + [frame_system, SystemBench::] + [pallet_balances, Balances] + [pallet_timestamp, Timestamp] + [pallet_sudo, Sudo] + [pallet_template, GuessedNumberGame] + ); +} + +impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block); + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + OpaqueMetadata::new(Runtime::metadata().into()) + } + + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::CheckInherentsResult { + data.check_extrinsics(&block) + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction( + source: TransactionSource, + tx: ::Extrinsic, + block_hash: ::Hash, + ) -> TransactionValidity { + Executive::validate_transaction(source, tx, block_hash) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> sp_consensus_aura::SlotDuration { + sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) + } + + fn authorities() -> Vec { + Aura::authorities().into_inner() + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + opaque::SessionKeys::generate(seed) + } + + fn decode_session_keys( + encoded: Vec, + ) -> Option, KeyTypeId)>> { + opaque::SessionKeys::decode_into_raw_public_keys(&encoded) + } + } + + impl sp_consensus_grandpa::GrandpaApi for Runtime { + fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList { + Grandpa::grandpa_authorities() + } + + fn current_set_id() -> sp_consensus_grandpa::SetId { + Grandpa::current_set_id() + } + + fn submit_report_equivocation_unsigned_extrinsic( + _equivocation_proof: sp_consensus_grandpa::EquivocationProof< + ::Hash, + NumberFor, + >, + _key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof, + ) -> Option<()> { + None + } + + fn generate_key_ownership_proof( + _set_id: sp_consensus_grandpa::SetId, + _authority_id: GrandpaId, + ) -> Option { + // NOTE: this is the only implementation possible since we've + // defined our key owner proof type as a bottom type (i.e. a type + // with no values). + None + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Nonce { + System::account_nonce(account) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { + fn query_info( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + fn query_fee_details( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_fee_details(uxt, len) + } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi + for Runtime + { + fn query_call_info( + call: RuntimeCall, + len: u32, + ) -> pallet_transaction_payment::RuntimeDispatchInfo { + TransactionPayment::query_call_info(call, len) + } + fn query_call_fee_details( + call: RuntimeCall, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_call_fee_details(call, len) + } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + fn benchmark_metadata(extra: bool) -> ( + Vec, + Vec, + ) { + use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; + use frame_support::traits::StorageInfoTrait; + use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; + + let mut list = Vec::::new(); + list_benchmarks!(list, extra); + + let storage_info = AllPalletsWithSystem::storage_info(); + + (list, storage_info) + } + + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, TrackedStorageKey}; + + use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; + + impl frame_system_benchmarking::Config for Runtime {} + impl baseline::Config for Runtime {} + + use frame_support::traits::WhitelistedStorageKeys; + let whitelist: Vec = AllPalletsWithSystem::whitelisted_storage_keys(); + + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + add_benchmarks!(params, batches); + + Ok(batches) + } + } + + #[cfg(feature = "try-runtime")] + impl frame_try_runtime::TryRuntime for Runtime { + fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. If any of the pre/post migration checks fail, we shall stop + // right here and right now. + let weight = Executive::try_runtime_upgrade(checks).unwrap(); + (weight, BlockWeights::get().max_block) + } + + fn execute_block( + block: Block, + state_root_check: bool, + signature_check: bool, + select: frame_try_runtime::TryStateSelect + ) -> Weight { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. + Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed") + } + } +} + +/// Configure the pallet-template in pallets/template. +impl pallet_template::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} From 9da0f1e30eae47b8dddd72196b2cc2ba7ce1de23 Mon Sep 17 00:00:00 2001 From: ajaykumargdr Date: Wed, 24 Jan 2024 18:57:57 +0530 Subject: [PATCH 3/5] chore: Add method for exchanging native currency to custom token --- .../custom-token-substrate-pallet/Cargo.toml | 3 +- .../custom-token-substrate-pallet/src/lib.rs | 86 +++++++++++++++---- 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/substrate-blockchain/custom-token-substrate-pallet/Cargo.toml b/substrate-blockchain/custom-token-substrate-pallet/Cargo.toml index fe63f80..e008316 100644 --- a/substrate-blockchain/custom-token-substrate-pallet/Cargo.toml +++ b/substrate-blockchain/custom-token-substrate-pallet/Cargo.toml @@ -16,11 +16,11 @@ scale-info = { version = "2.5.0", default-features = false, features = ["derive" frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } [dev-dependencies] sp-core = { version = "21.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } sp-io = { version = "23.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } -sp-runtime = { version = "24.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } [features] default = ["std"] @@ -30,6 +30,7 @@ std = [ "frame-support/std", "frame-system/std", "scale-info/std", + "sp-runtime/std", ] runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] try-runtime = ["frame-support/try-runtime"] diff --git a/substrate-blockchain/custom-token-substrate-pallet/src/lib.rs b/substrate-blockchain/custom-token-substrate-pallet/src/lib.rs index 016a4ab..17d526b 100644 --- a/substrate-blockchain/custom-token-substrate-pallet/src/lib.rs +++ b/substrate-blockchain/custom-token-substrate-pallet/src/lib.rs @@ -1,9 +1,13 @@ #![cfg_attr(not(feature = "std"), no_std)] pub use pallet::*; +const TOKEN_VALUE: u32 = 2; + #[frame_support::pallet] pub mod pallet { + use super::*; use frame_support::pallet_prelude::*; + use frame_support::traits::Currency; use frame_system::pallet_prelude::*; #[pallet::pallet] @@ -12,24 +16,53 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type Currency: Currency; + } + + #[pallet::error] + pub enum Error { + NoSufficientBalance, + NoneValue, } #[pallet::storage] type BalanceStore = StorageMap<_, Blake2_128Concat, T::AccountId, u32>; + + // #[pallet::storage] + pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - Balance { dest: T::AccountId, amount: u32 }, + Balance { + amount: u32, + }, + TokenTransferred { + from: T::AccountId, + to: T::AccountId, + amount: u32, + }, } #[pallet::call] impl Pallet { - #[pallet::weight(0)] - #[pallet::call_index(1)] - pub fn add_amount(origin: OriginFor, dest: T::AccountId, amount: u32) -> DispatchResult { - ensure_root(origin)?; + #[pallet::weight(10_000)] + #[pallet::call_index(0)] + pub fn exchange_native_to_custom_token( + origin: OriginFor, + amount: u32, + ) -> DispatchResult { + let owner = ensure_signed(origin)?; + + let total_fee: u32 = amount * TOKEN_VALUE; - >::insert(&dest, amount); + if T::Currency::total_balance(&owner) < total_fee.into() { + return Err(Error::::NoSufficientBalance.into()); + } + + T::Currency::burn(total_fee.into()); + >::insert(&owner, amount); Ok(()) } @@ -43,12 +76,34 @@ pub mod pallet { ) -> DispatchResult { let owner = ensure_signed(origin)?; + match >::get(&owner) { + Some(balance) => { + if balance < amount { + return Err(Error::::NoSufficientBalance.into()); + } + } + None => { + >::insert(owner.clone(), 0); + return Err(Error::::NoSufficientBalance.into()); + } + } + >::mutate(&owner, |balance| { *balance = Some(balance.unwrap() - amount); }); - >::mutate(&dest, |balance| { - *balance = Some(balance.unwrap() + amount); + if !>::contains_key(dest.clone()) { + >::insert(dest.clone(), amount); + } else { + >::mutate(&dest, |balance| { + *balance = Some(balance.unwrap() + amount); + }); + } + + Self::deposit_event(Event::TokenTransferred { + from: owner, + to: dest, + amount, }); Ok(()) @@ -58,20 +113,15 @@ pub mod pallet { #[pallet::call_index(3)] pub fn get_balance(origin: OriginFor) -> DispatchResult { let owner = ensure_signed(origin)?; - let balance = >::get(&owner); match balance { - Some(balance) => Self::deposit_event(Event::Balance { - dest: owner, - amount: balance, - }), - None => Self::deposit_event(Event::Balance { - dest: owner, - amount: 0, - }), + Some(balance) => Self::deposit_event(Event::Balance { amount: balance }), + None => { + Self::deposit_event(Event::Balance { amount: 0 }); + >::insert(owner, 0); + } } - Ok(()) } } From bb590c3dd61b1955fdd42b84835efe0883f169b0 Mon Sep 17 00:00:00 2001 From: ajaykumargdr Date: Wed, 24 Jan 2024 19:38:07 +0530 Subject: [PATCH 4/5] chore: Add README to custom-token-substrate-pallet --- .../custom-token-substrate-pallet/README.md | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 substrate-blockchain/custom-token-substrate-pallet/README.md diff --git a/substrate-blockchain/custom-token-substrate-pallet/README.md b/substrate-blockchain/custom-token-substrate-pallet/README.md new file mode 100644 index 0000000..9d84f49 --- /dev/null +++ b/substrate-blockchain/custom-token-substrate-pallet/README.md @@ -0,0 +1,41 @@ +## Custom Token Pallet for Substrate + +The custom token pallet offered here facilitates the implementation of a custom token functionality within a Substrate runtime. It includes functionalities such as exchanging native currency for custom tokens, transferring tokens between accounts, and checking token balances. + +### Features +- **Exchange Native to Custom Token**: Allows users to exchange native currency for custom tokens, ensuring sufficient balance checks. +- **Token Transfer**: Facilitates the transfer of custom tokens between accounts, managing balances accordingly. +- **Get Balance**: Enables users to retrieve their current token balance. + +### Usage +To integrate this custom token pallet into your Substrate runtime, follow these steps: + +1. Add the custom token pallet to your Substrate runtime Cargo.toml file: + ```toml + pallet-custom-token = { version = "4.0.0-dev", default-features = false, path = "../pallets/template" } + ``` +2. In the Cargo.toml file, ensure that the custom token pallet is added as a dependency in the feature std by including the line: + ```toml + [features] + default = ["std"] + std = [ + # other dependencies + "pallet-custom-token/std" + ] + ``` +3. Configure the `pallet_custom_token` pallet in the Substrate node runtime as follows: + ```rust + impl pallet_custom_token::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + } + ``` +4. Deploy and run your updated Substrate runtime with the custom token pallet included to enable custom token using the following command + ```bash + cargo build --release + ``` +5. Run the node using the following command + ```bash + ./target/release/node-template --dev + ``` +6. Use the [polkadot.org.js](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/chainstate) for test the functionalities \ No newline at end of file From 7f0d3d983caa99c4f243c5edb9dac0ee14dcb95c Mon Sep 17 00:00:00 2001 From: ajaykumargdr Date: Wed, 24 Jan 2024 20:03:38 +0530 Subject: [PATCH 5/5] chore: Add README.md for guessing-random-number-game substrate blockchain --- .../guessing-random-number-game/README.md | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 substrate-blockchain/guessing-random-number-game/README.md diff --git a/substrate-blockchain/guessing-random-number-game/README.md b/substrate-blockchain/guessing-random-number-game/README.md new file mode 100644 index 0000000..33f882b --- /dev/null +++ b/substrate-blockchain/guessing-random-number-game/README.md @@ -0,0 +1,23 @@ +# Substrate Custom Pallet Readme + +## Overview +This custom Substrate blockchain allows users to play a number guessing game. Sudo user(admin) can set a target number and then let the players make guesses to try and match the target number. The pallet defines storage items, dispatchable functions, events, and errors to support the guessing game functionality. + +## Features +- Set a target number +- Check a guess the target number +- Remove the target number +- Emit events for setting a target, making a guess, and removing the target + +## Usage +Follow these steps for build and run this chain + +1. Clone the repo and build the chain using the following command + ```bash + cargo build --release + ``` +2. Run the node using the following command + ```bash + ./target/release/node-template --dev + ``` +3. Use the [polkadot.org.js](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/chainstate) for test the functionalities \ No newline at end of file