diff --git a/.gitignore b/.gitignore index 240697f..3b7b8a8 100644 --- a/.gitignore +++ b/.gitignore @@ -55,4 +55,5 @@ dist configLocal.json *.json.json node_modules -polkadot \ No newline at end of file +polkadot +.vscode diff --git a/Cargo.lock b/Cargo.lock index 5d840a9..ee350a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3209,11 +3209,14 @@ source = "git+https://github.com/paritytech/polkadot?branch=rococo-v1#943038a888 dependencies = [ "beefy-primitives", "bitvec", + "frame-benchmarking", "frame-executive", "frame-support", "frame-system", + "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", + "hex-literal 0.3.1", "log", "pallet-authority-discovery", "pallet-authorship", @@ -3233,11 +3236,13 @@ dependencies = [ "pallet-multisig", "pallet-nicks", "pallet-offences", + "pallet-offences-benchmarking", "pallet-proxy", "pallet-randomness-collective-flip", "pallet-recovery", "pallet-scheduler", "pallet-session", + "pallet-session-benchmarking", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", @@ -4436,6 +4441,23 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-aura" +version = "3.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" +dependencies = [ + "frame-support", + "frame-system", + "pallet-session", + "pallet-timestamp", + "parity-scale-codec", + "serde", + "sp-application-crypto", + "sp-consensus-aura", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-authority-discovery" version = "3.0.0" @@ -4526,6 +4548,7 @@ name = "pallet-bounties" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "pallet-treasury", @@ -4540,6 +4563,7 @@ name = "pallet-collective" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "log", @@ -4571,11 +4595,13 @@ name = "pallet-election-provider-multi-phase" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-election-provider-support", "frame-support", "frame-system", "log", "parity-scale-codec", + "rand 0.7.3", "serde", "sp-arithmetic", "sp-io", @@ -4590,6 +4616,7 @@ name = "pallet-elections-phragmen" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "log", @@ -4643,6 +4670,7 @@ name = "pallet-im-online" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "log", @@ -4662,6 +4690,7 @@ name = "pallet-indices" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", @@ -4744,6 +4773,7 @@ name = "pallet-multisig" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", @@ -4784,11 +4814,34 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-offences-benchmarking" +version = "3.0.0" +source = "git+https://github.com/paritytech/substrate?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "pallet-babe", + "pallet-balances", + "pallet-grandpa", + "pallet-im-online", + "pallet-offences", + "pallet-session", + "pallet-staking", + "parity-scale-codec", + "sp-runtime", + "sp-staking", + "sp-std", +] + [[package]] name = "pallet-proxy" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", @@ -4863,6 +4916,43 @@ dependencies = [ "sp-trie", ] +[[package]] +name = "pallet-session-benchmarking" +version = "3.0.0" +source = "git+https://github.com/paritytech/substrate?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-session", + "pallet-staking", + "rand 0.7.3", + "sp-runtime", + "sp-session", + "sp-std", +] + +[[package]] +name = "pallet-simple-staking" +version = "3.0.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-timestamp", + "parity-scale-codec", + "serde", + "sp-consensus-aura", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-society" version = "3.0.0" @@ -4882,6 +4972,7 @@ name = "pallet-staking" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-election-provider-support", "frame-support", "frame-system", @@ -4890,6 +4981,7 @@ dependencies = [ "pallet-session", "parity-scale-codec", "paste 1.0.5", + "rand_chacha 0.2.2", "serde", "sp-application-crypto", "sp-io", @@ -4924,20 +5016,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-template" -version = "3.0.0" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "parity-scale-codec", - "serde", - "sp-core", - "sp-io", - "sp-runtime", -] - [[package]] name = "pallet-timestamp" version = "3.0.0" @@ -4962,6 +5040,7 @@ name = "pallet-tips" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "pallet-treasury", @@ -5020,6 +5099,7 @@ name = "pallet-treasury" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "impl-trait-for-tuples", @@ -5035,6 +5115,7 @@ name = "pallet-utility" version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", @@ -5051,6 +5132,7 @@ version = "3.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" dependencies = [ "enumflags2", + "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", @@ -6131,11 +6213,14 @@ source = "git+https://github.com/paritytech/polkadot?branch=rococo-v1#943038a888 dependencies = [ "beefy-primitives", "bitvec", + "frame-benchmarking", "frame-executive", "frame-support", "frame-system", + "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", + "hex-literal 0.3.1", "log", "pallet-authority-discovery", "pallet-authorship", @@ -6155,10 +6240,12 @@ dependencies = [ "pallet-multisig", "pallet-nicks", "pallet-offences", + "pallet-offences-benchmarking", "pallet-proxy", "pallet-randomness-collective-flip", "pallet-scheduler", "pallet-session", + "pallet-session-benchmarking", "pallet-staking", "pallet-staking-reward-curve", "pallet-timestamp", @@ -6201,12 +6288,14 @@ source = "git+https://github.com/paritytech/polkadot?branch=rococo-v1#943038a888 dependencies = [ "beefy-primitives", "bitvec", + "frame-benchmarking", "frame-support", "frame-system", "impl-trait-for-tuples", "libsecp256k1", "log", "pallet-authorship", + "pallet-babe", "pallet-balances", "pallet-beefy", "pallet-mmr", @@ -6243,8 +6332,10 @@ source = "git+https://github.com/paritytech/polkadot?branch=rococo-v1#943038a888 dependencies = [ "bitvec", "derive_more 0.99.13", + "frame-benchmarking", "frame-support", "frame-system", + "libsecp256k1", "log", "pallet-authority-discovery", "pallet-authorship", @@ -7105,6 +7196,7 @@ dependencies = [ "node-primitives", "pallet-authorship", "pallet-balances", + "pallet-simple-staking", "parity-scale-codec", "polkadot-primitives", "polkadot-runtime-common", @@ -8751,6 +8843,22 @@ dependencies = [ "wasm-timer", ] +[[package]] +name = "sp-consensus-aura" +version = "0.9.0" +source = "git+https://github.com/paritytech/substrate.git?branch=rococo-v1#68cfc326fa0e3d96d0d92509e4db1a104b9da9bb" +dependencies = [ + "parity-scale-codec", + "sp-api", + "sp-application-crypto", + "sp-consensus", + "sp-consensus-slots", + "sp-inherents", + "sp-runtime", + "sp-std", + "sp-timestamp", +] + [[package]] name = "sp-consensus-babe" version = "0.9.0" @@ -9270,8 +9378,8 @@ dependencies = [ "pallet-multisig", "pallet-proxy", "pallet-randomness-collective-flip", + "pallet-simple-staking", "pallet-sudo", - "pallet-template", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", @@ -9377,8 +9485,8 @@ dependencies = [ "pallet-multisig", "pallet-proxy", "pallet-randomness-collective-flip", + "pallet-simple-staking", "pallet-sudo", - "pallet-template", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", @@ -10907,11 +11015,14 @@ source = "git+https://github.com/paritytech/polkadot?branch=rococo-v1#943038a888 dependencies = [ "beefy-primitives", "bitvec", + "frame-benchmarking", "frame-executive", "frame-support", "frame-system", + "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", + "hex-literal 0.3.1", "log", "pallet-authority-discovery", "pallet-authorship", @@ -10932,11 +11043,13 @@ dependencies = [ "pallet-multisig", "pallet-nicks", "pallet-offences", + "pallet-offences-benchmarking", "pallet-proxy", "pallet-randomness-collective-flip", "pallet-recovery", "pallet-scheduler", "pallet-session", + "pallet-session-benchmarking", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", diff --git a/Cargo.toml b/Cargo.toml index bc9917a..4759f8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ panic = 'unwind' [workspace] members = [ 'node', - 'pallets/template', + 'pallets/simple-staking', 'runtime/statemint', 'runtime/statemine', ] diff --git a/node/Cargo.toml b/node/Cargo.toml index 302bdcb..1078150 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -1,10 +1,6 @@ [[bin]] name = 'statemint' -[features] -default = [] -runtime-benchmarks = ['statemint-runtime/runtime-benchmarks'] - [package] authors = ['Anonymous'] build = 'build.rs' @@ -215,4 +211,12 @@ branch = 'rococo-v1' [build-dependencies.substrate-build-script-utils] git = 'https://github.com/paritytech/substrate.git' branch = 'rococo-v1' -version = '3.0.0' \ No newline at end of file +version = '3.0.0' + +[features] +default = [] +runtime-benchmarks = [ + 'polkadot-service/runtime-benchmarks', + 'statemint-runtime/runtime-benchmarks', + 'statemine-runtime/runtime-benchmarks', +] diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 57296a4..442126a 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -124,8 +124,9 @@ fn statemint_testnet_genesis( .map(|k| (k, 1 << 60)) .collect(), }, - pallet_sudo: statemint_runtime::SudoConfig { key: root_key }, + pallet_sudo: statemint_runtime::SudoConfig { key: root_key.clone() }, parachain_info: statemint_runtime::ParachainInfoConfig { parachain_id: id }, + pallet_simple_staking: statemint_runtime::SimpleStakingConfig { invulnerables: vec![root_key] }, } } @@ -219,7 +220,8 @@ fn statemine_testnet_genesis( .map(|k| (k, 1 << 60)) .collect(), }, - pallet_sudo: statemine_runtime::SudoConfig { key: root_key }, + pallet_sudo: statemine_runtime::SudoConfig { key: root_key.clone() }, parachain_info: statemine_runtime::ParachainInfoConfig { parachain_id: id }, + pallet_simple_staking: statemine_runtime::SimpleStakingConfig { invulnerables: vec![root_key] }, } } diff --git a/node/src/cli.rs b/node/src/cli.rs index 692b896..75c7750 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -34,6 +34,10 @@ pub enum Subcommand { /// Revert the chain to a previous state. Revert(sc_cli::RevertCmd), + + /// The custom benchmark subcommmand benchmarking runtime pallets. + #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + Benchmark(frame_benchmarking_cli::BenchmarkCmd), } /// Command for exporting the genesis state of the parachain diff --git a/node/src/command.rs b/node/src/command.rs index cd3cf01..dc93b42 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -36,6 +36,7 @@ use sp_core::hexdisplay::HexDisplay; use sp_runtime::traits::Block as BlockT; use statemint_runtime::Block; use std::{io::Write, net::SocketAddr}; +use crate::service::Executor; fn load_spec( id: &str, @@ -214,6 +215,16 @@ pub fn run() -> Result<()> { Ok((cmd.run(client, backend), task_manager)) }) } + Some(Subcommand::Benchmark(cmd)) => { + if cfg!(feature = "runtime-benchmarks") { + let runner = cli.create_runner(cmd)?; + + runner.sync_run(|config| cmd.run::(config)) + } else { + Err("Benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`.".into()) + } + } Some(Subcommand::ExportGenesisState(params)) => { let mut builder = sc_cli::LoggerBuilder::new(""); builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); diff --git a/node/src/service.rs b/node/src/service.rs index f33e1fd..6381cb5 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -21,6 +21,7 @@ native_executor_instance!( pub Executor, statemint_runtime::api::dispatch, statemint_runtime::native_version, + frame_benchmarking::benchmarking::HostFunctions, ); /// Starts a `ServiceBuilder` for a full service. diff --git a/pallets/template/Cargo.toml b/pallets/simple-staking/Cargo.toml similarity index 58% rename from pallets/template/Cargo.toml rename to pallets/simple-staking/Cargo.toml index e5bc598..e8c63da 100644 --- a/pallets/template/Cargo.toml +++ b/pallets/simple-staking/Cargo.toml @@ -4,7 +4,7 @@ description = 'FRAME pallet template for defining custom runtime logic.' edition = '2018' homepage = 'https://substrate.dev' license = 'Unlicense' -name = 'pallet-template' +name = 'pallet-simple-staking' readme = 'README.md' repository = 'https://github.com/paritytech/substrate/' version = '3.0.0' @@ -12,15 +12,9 @@ version = '3.0.0' [package.metadata.docs.rs] targets = ['x86_64-unknown-linux-gnu'] -[features] -default = ['std'] -runtime-benchmarks = ['frame-benchmarking'] -std = [ - 'codec/std', - 'frame-support/std', - 'frame-system/std', - 'frame-benchmarking/std', -] +[dependencies.log] +default-features = false +version = "0.4.0" [dependencies.codec] default-features = false @@ -28,6 +22,12 @@ features = ['derive'] package = 'parity-scale-codec' version = '2.0.0' +[dependencies.pallet-authorship] +default-features = false +git = 'https://github.com/paritytech/substrate.git' +branch = 'rococo-v1' +version = '3.0.0' + [dependencies.frame-benchmarking] default-features = false optional = true @@ -47,23 +47,64 @@ git = 'https://github.com/paritytech/substrate.git' branch = 'rococo-v1' version = '3.0.0' -[dev-dependencies] -serde = { version = "1.0.119" } +[dependencies.sp-std] +default-features = false +git = 'https://github.com/paritytech/substrate.git' +branch = 'rococo-v1' +version = '3.0.0' + +[dependencies.serde] +version = "1.0.119" +default-features = false [dev-dependencies.sp-core] -default-features = false git = 'https://github.com/paritytech/substrate.git' branch = 'rococo-v1' version = '3.0.0' [dev-dependencies.sp-io] -default-features = false git = 'https://github.com/paritytech/substrate.git' branch = 'rococo-v1' version = '3.0.0' [dev-dependencies.sp-runtime] -default-features = false git = 'https://github.com/paritytech/substrate.git' branch = 'rococo-v1' version = '3.0.0' + +[dev-dependencies.pallet-aura] +git = 'https://github.com/paritytech/substrate.git' +branch = 'rococo-v1' +version = '3.0.0' + +[dev-dependencies.pallet-timestamp] +git = 'https://github.com/paritytech/substrate.git' +branch = 'rococo-v1' +version = '3.0.0' + +[dev-dependencies.sp-consensus-aura] +git = 'https://github.com/paritytech/substrate.git' +branch = 'rococo-v1' +version = '0.9.0' + +[dev-dependencies.pallet-balances] +git = 'https://github.com/paritytech/substrate.git' +branch = 'rococo-v1' +version = '3.0.0' + +[features] +default = ['std'] +runtime-benchmarks = [ + 'frame-benchmarking', + 'frame-support/runtime-benchmarks', + 'frame-system/runtime-benchmarks', +] +std = [ + 'codec/std', + 'log/std', + 'sp-std/std', + 'frame-support/std', + 'frame-system/std', + 'frame-benchmarking/std', + 'pallet-authorship/std', +] diff --git a/pallets/template/README.md b/pallets/simple-staking/README.md similarity index 100% rename from pallets/template/README.md rename to pallets/simple-staking/README.md diff --git a/pallets/simple-staking/src/benchmarking.rs b/pallets/simple-staking/src/benchmarking.rs new file mode 100644 index 0000000..6c54c1f --- /dev/null +++ b/pallets/simple-staking/src/benchmarking.rs @@ -0,0 +1,147 @@ +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//! Benchmarking setup for pallet-simple-staking + +use super::*; + +#[allow(unused)] +use crate::Pallet as SimpleStaking; +use sp_std::prelude::*; +use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller, account}; +use frame_system::{RawOrigin, EventRecord}; +use frame_support::{ + assert_ok, + traits::{Currency, Get, EnsureOrigin}, +}; +use pallet_authorship::EventHandler; + +pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + +const SEED: u32 = 0; + +// TODO: remove if this is given in substrate commit. +macro_rules! whitelist { + ($acc:ident) => { + frame_benchmarking::benchmarking::add_to_whitelist( + frame_system::Account::::hashed_key_for(&$acc).into() + ); + }; +} + +fn assert_last_event(generic_event: ::Event) { + let events = frame_system::Pallet::::events(); + let system_event: ::Event = generic_event.into(); + // compare to the last event record + let EventRecord { event, .. } = &events[events.len() - 1]; + assert_eq!(event, &system_event); +} + +fn register_authors(count: u32) { + let authors = (0..count).map(|c| account("author", c, SEED)).collect::>(); + assert!(>::get() > 0u32.into(), "Bond cannot be zero!"); + for who in authors { + T::Currency::make_free_balance_be(&who, >::get() * 2u32.into()); + >::register_as_author(RawOrigin::Signed(who).into()).unwrap(); + } +} + +benchmarks! { + where_clause { where T: pallet_authorship::Config } + + set_invulnerables { + let b in 1 .. T::MaxInvulnerables::get(); + let new_invulnerables = (0..b).map(|c| account("author", c, SEED)).collect::>(); + let origin = T::UpdateOrigin::successful_origin(); + }: { + assert_ok!( + >::set_invulnerables(origin, new_invulnerables.clone()) + ); + } + verify { + assert_last_event::(Event::NewInvulnerables(new_invulnerables).into()); + } + + set_allowed_author_count { + let max: u32 = 999; + let origin = T::UpdateOrigin::successful_origin(); + }: { + assert_ok!( + >::set_allowed_author_count(origin, max.clone()) + ); + } + verify { + assert_last_event::(Event::NewAllowedAuthorCount(max).into()); + } + + set_author_bond { + let bond: BalanceOf = T::Currency::minimum_balance() * 10u32.into(); + let origin = T::UpdateOrigin::successful_origin(); + }: { + assert_ok!( + >::set_author_bond(origin, bond.clone()) + ); + } + verify { + assert_last_event::(Event::NewAuthorBond(bond).into()); + } + + // worse case is when we have all the max-author slots filled except one, and we fill that one. + register_as_author { + let c in 1 .. T::MaxAuthors::get(); + + >::put(T::Currency::minimum_balance()); + >::put(c + 1); + register_authors::(c); + + let caller: T::AccountId = whitelisted_caller(); + let bond: BalanceOf = T::Currency::minimum_balance() * 2u32.into(); + T::Currency::make_free_balance_be(&caller, bond.clone()); + + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert_last_event::(Event::AuthorAdded(caller, bond / 2u32.into()).into()); + } + + // worse case is the last author leaving. + leave_intent { + let c in 1 .. T::MaxAuthors::get(); + >::put(T::Currency::minimum_balance()); + >::put(c); + register_authors::(c); + + let leaving = >::get().last().unwrap().who.clone(); + whitelist!(leaving); + }: _(RawOrigin::Signed(leaving.clone())) + verify { + assert_last_event::(Event::AuthorRemoved(leaving).into()); + } + + // worse case is paying a non-existing author account. + note_author { + T::Currency::make_free_balance_be( + &>::account_id(), + T::Currency::minimum_balance() * 2u32.into(), + ); + let author = account("author", 0, SEED); + assert!(T::Currency::free_balance(&author) == 0u32.into()); + }: { + as EventHandler<_, _>>::note_author(author.clone()) + } verify { + assert!(T::Currency::free_balance(&author) > 0u32.into()); + } +} + +impl_benchmark_test_suite!(SimpleStaking, crate::mock::new_test_ext(), crate::mock::Test,); diff --git a/pallets/simple-staking/src/lib.rs b/pallets/simple-staking/src/lib.rs new file mode 100644 index 0000000..0b11570 --- /dev/null +++ b/pallets/simple-staking/src/lib.rs @@ -0,0 +1,281 @@ +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use pallet::*; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +pub mod weights; + +#[frame_support::pallet] +pub mod pallet { + use frame_support::{ + dispatch::DispatchResultWithPostInfo, + pallet_prelude::*, + inherent::Vec, + traits::{Currency, ReservableCurrency, EnsureOrigin, ExistenceRequirement::KeepAlive}, + PalletId + }; + use frame_system::pallet_prelude::*; + use frame_system::Config as SystemConfig; + use frame_support::{ + sp_runtime::{RuntimeDebug, traits::{AccountIdConversion}}, + weights::DispatchClass, + }; + use core::ops::Div; + pub use crate::weights::WeightInfo; + + + /// 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 Event: From> + IsType<::Event>; + /// The currency mechanism. + type Currency: ReservableCurrency; + + /// Origin that can dictate updating parameters of this pallet. + type UpdateOrigin: EnsureOrigin; + + /// Account Identifier using which the internal treasury account is generated. + type PotId: Get; + + /// Maximum number of authors that we should have. This is used for benchmarking and is not + /// enforced. + /// + /// This does not take into account the invulnerables. + type MaxAuthors: Get; + + /// Maximum number of invulnerables. + /// + /// Used only for benchmarking. + type MaxInvulnerables: Get; + + /// The weight information of this pallet. + type WeightInfo: WeightInfo; + } + + type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + + #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] + pub struct AuthorInfo { + pub who: AccountId, + pub deposit: Balance, + pub last_block: Option, + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + // The pallet's runtime storage items. + // https://substrate.dev/docs/en/knowledgebase/runtime/storage + + #[pallet::storage] + #[pallet::getter(fn invulnerables)] + pub type Invulnerables= StorageValue<_, Vec, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn authors)] + pub type Authors = StorageValue<_, Vec, T::BlockNumber>>, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn allowed_authors)] + pub type AllowedAuthors = StorageValue<_, u32, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn author_bond)] + pub type AuthorBond = StorageValue<_, BalanceOf, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn authority_bond)] + pub type AuthorityBond= StorageValue<_, BalanceOf>; + + #[pallet::genesis_config] + pub struct GenesisConfig { + pub invulnerables: Vec, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { + invulnerables: Default::default(), + } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + assert!( + T::MaxInvulnerables::get() >= (self.invulnerables.len() as u32), + "genesis invulnerables are more than T::MaxInvulnerables", + ); + >::put(&self.invulnerables); + } + } + + #[pallet::event] + #[pallet::metadata(T::AccountId = "AccountId", BalanceOf = "Balance")] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Event documentation should end with an array that provides descriptive names for event + /// parameters. [something, who] + NewInvulnerables(Vec), + NewAllowedAuthorCount(u32), + NewAuthorBond(BalanceOf), + AuthorAdded(T::AccountId, BalanceOf), + AuthorRemoved(T::AccountId) + } + + // Errors inform users that something went wrong. + #[pallet::error] + pub enum Error { + TooManyAuthors, + Unknown, + Permission, + AlreadyAuthor, + NotAuthor + } + + #[pallet::hooks] + impl Hooks> for Pallet { + //TODO add in on init hook to concat invulnerables with Authors and set as aura authorities + // Also consider implementing era's of X block + } + + // Dispatchable functions allows 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(T::WeightInfo::set_invulnerables(new.len() as u32))] + pub fn set_invulnerables( + origin: OriginFor, + new: Vec, + ) -> DispatchResultWithPostInfo { + T::UpdateOrigin::ensure_origin(origin)?; + // we trust origin calls, this is just a for more accurate benchmarking + if (new.len() as u32) > T::MaxInvulnerables::get() { + log::warn!( + "invulnerables > T::MaxInvulnerables; you might need to run benchmarks again" + ); + } + >::put(&new); + Self::deposit_event(Event::NewInvulnerables(new)); + Ok(().into()) + } + + #[pallet::weight(T::WeightInfo::set_allowed_author_count())] + pub fn set_allowed_author_count(origin: OriginFor, allowed: u32) -> DispatchResultWithPostInfo { + T::UpdateOrigin::ensure_origin(origin)?; + // we trust origin calls, this is just a for more accurate benchmarking + if allowed > T::MaxAuthors::get() { + log::warn!( + "allowed > T::MaxAuthors; you might need to run benchmarks again" + ); + } + >::put(&allowed); + Self::deposit_event(Event::NewAllowedAuthorCount(allowed)); + Ok(().into()) + } + + #[pallet::weight(T::WeightInfo::set_author_bond())] + pub fn set_author_bond(origin: OriginFor, author_bond: BalanceOf) -> DispatchResultWithPostInfo { + T::UpdateOrigin::ensure_origin(origin)?; + >::put(&author_bond); + Self::deposit_event(Event::NewAuthorBond(author_bond)); + Ok(().into()) + } + + #[pallet::weight(T::WeightInfo::register_as_author(T::MaxAuthors::get()))] + pub fn register_as_author(origin: OriginFor) -> DispatchResultWithPostInfo { + // lock deposit to start or require min? + let who = ensure_signed(origin)?; + let deposit = >::get(); + let length = >::decode_len().unwrap_or_default(); + ensure!((length as u32) < Self::allowed_authors(), Error::::TooManyAuthors); + let new_author = AuthorInfo { + who: who.clone(), + deposit, + last_block: None + }; + let author_count = >::try_mutate(|authors| -> Result { + if authors.into_iter().any(|author| author.who == who) { + Err(Error::::AlreadyAuthor)? + } else { + T::Currency::reserve(&who, deposit)?; + authors.push(new_author); + Self::deposit_event(Event::AuthorAdded(who, deposit)); + Ok(authors.len()) + } + })?; + Ok(Some(T::WeightInfo::register_as_author(author_count as u32)).into()) + } + + #[pallet::weight(T::WeightInfo::leave_intent(T::MaxAuthors::get()))] + pub fn leave_intent(origin: OriginFor) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + let author_count = >::try_mutate(|authors| -> Result { + let index = authors.iter().position(|author| author.who == who).ok_or(Error::::NotAuthor)?; + T::Currency::unreserve(&who, authors[index].deposit); + authors.remove(index); + Ok(authors.len()) + })?; + Self::deposit_event(Event::AuthorRemoved(who)); + Ok(Some(T::WeightInfo::leave_intent(author_count as u32)).into()) + } + } + + impl Pallet { + pub fn account_id() -> T::AccountId { + T::PotId::get().into_account() + } + } + + /// Keep track of number of authored blocks per authority, uncles are counted as + /// well since they're a valid proof of being online. + impl + pallet_authorship::EventHandler for Pallet + { + fn note_author(author: T::AccountId) { + let treasury = Self::account_id(); + let reward = T::Currency::free_balance(&treasury).div(2u32.into()); + + // `reward` is half of treasury account, this should never fail. + let _success = T::Currency::transfer(&treasury, &author, reward, KeepAlive); + debug_assert!(_success.is_ok()); + + frame_system::Pallet::::register_extra_weight_unchecked( + T::WeightInfo::note_author(), + DispatchClass::Mandatory, + ); + } + + fn note_uncle(_author: T::AccountId, _age: T::BlockNumber) { + //TODO can we ignore this? + } + } +} diff --git a/pallets/simple-staking/src/mock.rs b/pallets/simple-staking/src/mock.rs new file mode 100644 index 0000000..169f687 --- /dev/null +++ b/pallets/simple-staking/src/mock.rs @@ -0,0 +1,163 @@ +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; +use crate as simple_staking; +use sp_core::H256; +use frame_support::{ + parameter_types, ord_parameter_types, + traits::{FindAuthor, GenesisBuild}, + PalletId +}; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + testing::{Header}, +}; +use sp_consensus_aura::sr25519::AuthorityId; +use frame_system::{EnsureSignedBy}; +use frame_system as system; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Aura: pallet_aura::{Pallet, Call, Storage, Config}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + SimpleStaking: simple_staking::{Pallet, Call, Storage, Event}, + Authorship: pallet_authorship::{Pallet, Call, Storage, Inherent}, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} + +impl system::Config for Test { + type BaseCallFilter = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Call = Call; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); +} + +parameter_types! { + pub const ExistentialDeposit: u64 = 1; +} + +impl pallet_balances::Config for Test { + type Balance = u64; + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = (); +} + +pub struct Author4; +impl FindAuthor for Author4 { + fn find_author<'a, I>(_digests: I) -> Option + where I: 'a + IntoIterator, + { + Some(4) + } +} + +impl pallet_authorship::Config for Test { + type FindAuthor = Author4; + type UncleGenerations = (); + type FilterUncle = (); + type EventHandler = SimpleStaking; +} + +parameter_types! { + pub const MinimumPeriod: u64 = 1; +} + +impl pallet_timestamp::Config for Test { + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +impl pallet_aura::Config for Test { + type AuthorityId = AuthorityId; +} + +ord_parameter_types! { + pub const RootAccount: u64 = 777; +} +parameter_types! { + pub const PotId: PalletId = PalletId(*b"PotStake"); + pub const MaxAuthors: u32 = 20; + pub const MaxInvulnerables: u32 = 20; +} +impl Config for Test { + type Event = Event; + type Currency = Balances; + type UpdateOrigin = EnsureSignedBy; + type PotId = PotId; + type MaxAuthors = MaxAuthors; + type MaxInvulnerables = MaxInvulnerables; + type WeightInfo = (); +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let genesis = pallet_balances::GenesisConfig:: { + balances: vec![ + (1, 100), + (2, 200), + ], + }; + let genesis_staking = simple_staking::GenesisConfig:: { + invulnerables: vec![ + 1, + 2, + 3, + ], + }; + genesis.assimilate_storage(&mut t).unwrap(); + genesis_staking.assimilate_storage(&mut t).unwrap(); + t.into() +} diff --git a/pallets/simple-staking/src/tests.rs b/pallets/simple-staking/src/tests.rs new file mode 100644 index 0000000..be9d359 --- /dev/null +++ b/pallets/simple-staking/src/tests.rs @@ -0,0 +1,141 @@ +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{mock::*, Error, AuthorInfo}; +use frame_support::{assert_noop, assert_ok, traits::{OnInitialize, Currency}}; +use sp_runtime::traits::BadOrigin; +use pallet_balances::Error as BalancesError; + +#[test] +fn it_should_set_invulnerables() { + new_test_ext().execute_with(|| { + let new_handlers = vec![1, 2, 3, 4]; + assert_ok!(SimpleStaking::set_invulnerables( + Origin::signed(RootAccount::get()), + new_handlers.clone() + )); + assert_noop!( + SimpleStaking::set_invulnerables(Origin::signed(1), new_handlers.clone()), + BadOrigin + ); + assert_eq!(SimpleStaking::invulnerables(), new_handlers); + }); +} + +#[test] +fn set_allowed_author_count() { + new_test_ext().execute_with(|| { + assert_ok!(SimpleStaking::set_allowed_author_count(Origin::signed(RootAccount::get()), 7)); + assert_noop!(SimpleStaking::set_allowed_author_count(Origin::signed(1), 8), BadOrigin); + assert_eq!(SimpleStaking::allowed_authors(), 7); + }); +} + +#[test] +fn set_author_bond() { + new_test_ext().execute_with(|| { + assert_ok!(SimpleStaking::set_author_bond(Origin::signed(RootAccount::get()), 7)); + assert_noop!(SimpleStaking::set_author_bond(Origin::signed(1), 8), BadOrigin); + assert_eq!(SimpleStaking::author_bond(), 7); + }); +} + +#[test] +fn register_as_author() { + new_test_ext().execute_with(|| { + assert_noop!( + SimpleStaking::register_as_author(Origin::signed(1)), + Error::::TooManyAuthors + ); + + assert_ok!(SimpleStaking::set_author_bond(Origin::signed(RootAccount::get()), 10)); + assert_ok!(SimpleStaking::set_allowed_author_count(Origin::signed(RootAccount::get()), 1)); + + // can add 1 new + assert_ok!(SimpleStaking::register_as_author(Origin::signed(1))); + let addition = AuthorInfo { + who: 1, + deposit: 10, + last_block: None + }; + assert_eq!(SimpleStaking::authors(), vec![addition]); + assert_eq!(Balances::free_balance(1), 90); + + // but no more + assert_noop!( + SimpleStaking::register_as_author(Origin::signed(1)), + Error::::TooManyAuthors + ); + + // increase limit + assert_ok!(SimpleStaking::set_allowed_author_count(Origin::signed(RootAccount::get()), 5)); + // but still won't accept dupe.. + assert_noop!( + SimpleStaking::register_as_author(Origin::signed(1)), + Error::::AlreadyAuthor + ); + // or poor author (3 is not endowed) + assert_noop!( + SimpleStaking::register_as_author(Origin::signed(3)), + BalancesError::::InsufficientBalance + ); + // but an endowed account works now + assert_ok!(SimpleStaking::register_as_author(Origin::signed(2))); + + assert_eq!(SimpleStaking::authors().len(), 2); + }); +} + +#[test] +fn leave_intent() { + new_test_ext().execute_with(|| { + assert_ok!(SimpleStaking::set_allowed_author_count(Origin::signed(RootAccount::get()), 1)); + assert_ok!(SimpleStaking::set_author_bond(Origin::signed(RootAccount::get()), 10)); + assert_ok!(SimpleStaking::register_as_author(Origin::signed(1))); + assert_eq!(Balances::free_balance(1), 90); + assert_noop!( + SimpleStaking::leave_intent(Origin::signed(RootAccount::get())), + Error::::NotAuthor + ); + assert_ok!(SimpleStaking::leave_intent(Origin::signed(1))); + assert_eq!(SimpleStaking::authors(), vec![]); + assert_eq!(Balances::free_balance(1), 100); + }); +} + +#[test] +fn authorship_event_handler() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&SimpleStaking::account_id(), 100); + // 4 is the default author. + assert_eq!(Balances::free_balance(4), 0); + assert_eq!(Balances::free_balance(SimpleStaking::account_id()), 100); + // triggers `note_author` + Authorship::on_initialize(1); + + // half of the pot goes to the author. + assert_eq!(Balances::free_balance(4), 50); + // half stays. + assert_eq!(Balances::free_balance(SimpleStaking::account_id()), 50); + }); +} + +#[test] +fn on_genesis() { + new_test_ext().execute_with(|| { + assert_eq!(SimpleStaking::invulnerables(), vec![1,2,3]); + assert_eq!(SimpleStaking::invulnerables().len(), 3); + }); +} diff --git a/pallets/simple-staking/src/weights.rs b/pallets/simple-staking/src/weights.rs new file mode 100644 index 0000000..767c413 --- /dev/null +++ b/pallets/simple-staking/src/weights.rs @@ -0,0 +1,108 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +// The weight info trait for `pallet_simple_staking`. +pub trait WeightInfo { + fn set_invulnerables(_b: u32) -> Weight; + fn set_allowed_author_count() -> Weight; + fn set_author_bond() -> Weight; + fn register_as_author(_c: u32) -> Weight; + fn leave_intent(_c: u32) -> Weight; + fn note_author() -> Weight; +} + +/// Weights for pallet_simple_staking using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + fn set_invulnerables(b: u32, ) -> Weight { + (28_060_000 as Weight) + // Standard Error: 1_000 + .saturating_add((118_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn set_allowed_author_count() -> Weight { + (25_000_000 as Weight) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn set_author_bond() -> Weight { + (25_000_000 as Weight) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn register_as_author(c: u32, ) -> Weight { + (82_496_000 as Weight) + // Standard Error: 1_000 + .saturating_add((266_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn leave_intent(c: u32, ) -> Weight { + (65_836_000 as Weight) + // Standard Error: 2_000 + .saturating_add((273_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn note_author() -> Weight { + (97_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } +} + + +// For backwards compatibility and tests +impl WeightInfo for () { + fn set_invulnerables(b: u32, ) -> Weight { + (28_060_000 as Weight) + // Standard Error: 1_000 + .saturating_add((118_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn set_allowed_author_count() -> Weight { + (25_000_000 as Weight) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn set_author_bond() -> Weight { + (25_000_000 as Weight) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn register_as_author(c: u32, ) -> Weight { + (82_496_000 as Weight) + // Standard Error: 1_000 + .saturating_add((266_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn leave_intent(c: u32, ) -> Weight { + (65_836_000 as Weight) + // Standard Error: 2_000 + .saturating_add((273_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn note_author() -> Weight { + (97_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } +} \ No newline at end of file diff --git a/pallets/template/src/benchmarking.rs b/pallets/template/src/benchmarking.rs deleted file mode 100644 index 4e1acc8..0000000 --- a/pallets/template/src/benchmarking.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! Benchmarking setup for pallet-template - -use super::*; - -#[allow(unused)] -use crate::Module as Template; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; -use frame_system::RawOrigin; - -benchmarks! { - do_something { - let s in 0 .. 100; - let caller: T::AccountId = whitelisted_caller(); - }: _(RawOrigin::Signed(caller), s) - verify { - assert_eq!(Something::::get(), Some(s)); - } -} - -impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test,); diff --git a/pallets/template/src/lib.rs b/pallets/template/src/lib.rs deleted file mode 100644 index 68220ac..0000000 --- a/pallets/template/src/lib.rs +++ /dev/null @@ -1,106 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -/// Edit this file to define custom logic or remove it if it is not needed. -/// Learn more about FRAME and the core library of Substrate FRAME pallets: -/// -pub use pallet::*; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod tests; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - -#[frame_support::pallet] -pub mod pallet { - use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*}; - use frame_system::pallet_prelude::*; - - /// 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 Event: From> + IsType<::Event>; - } - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - // The pallet's runtime storage items. - // https://substrate.dev/docs/en/knowledgebase/runtime/storage - #[pallet::storage] - #[pallet::getter(fn something)] - // Learn more about declaring storage items: - // https://substrate.dev/docs/en/knowledgebase/runtime/storage#declaring-storage-items - pub type Something = StorageValue<_, u32>; - - // Pallets use events to inform users when important changes are made. - // https://substrate.dev/docs/en/knowledgebase/runtime/events - #[pallet::event] - #[pallet::metadata(T::AccountId = "AccountId")] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// Event documentation should end with an array that provides descriptive names for event - /// parameters. [something, who] - SomethingStored(u32, T::AccountId), - } - - // Errors inform users that something went wrong. - #[pallet::error] - pub enum Error { - /// Error names should be descriptive. - NoneValue, - /// Errors should have helpful documentation associated with them. - StorageOverflow, - } - - #[pallet::hooks] - impl Hooks> for Pallet {} - - // Dispatchable functions allows 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 { - /// An example dispatchable that takes a singles value as a parameter, writes the value to - /// storage and emits an event. This function must be dispatched by a signed extrinsic. - #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] - pub fn do_something(origin: OriginFor, something: u32) -> DispatchResultWithPostInfo { - // Check that the extrinsic was signed and get the signer. - // This function will return an error if the extrinsic is not signed. - // https://substrate.dev/docs/en/knowledgebase/runtime/origin - let who = ensure_signed(origin)?; - - // Update storage. - >::put(something); - - // Emit an event. - Self::deposit_event(Event::SomethingStored(something, who)); - // Return a successful DispatchResultWithPostInfo - Ok(().into()) - } - - /// An example dispatchable that may throw a custom error. - #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))] - pub fn cause_error(origin: OriginFor) -> DispatchResultWithPostInfo { - let _who = ensure_signed(origin)?; - - // Read a value from storage. - match >::get() { - // Return an error if the value has not been set. - None => Err(Error::::NoneValue)?, - Some(old) => { - // Increment the value read from storage; will error in the event of overflow. - let new = old.checked_add(1).ok_or(Error::::StorageOverflow)?; - // Update the value in storage with the incremented result. - >::put(new); - Ok(().into()) - } - } - } - } -} diff --git a/pallets/template/src/mock.rs b/pallets/template/src/mock.rs deleted file mode 100644 index 1ebe3be..0000000 --- a/pallets/template/src/mock.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate as pallet_template; -use sp_core::H256; -use frame_support::parameter_types; -use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, testing::Header, -}; -use frame_system as system; - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -// Configure a mock runtime to test the pallet. -frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - TemplateModule: pallet_template::{Pallet, Call, Storage, Event}, - } -); - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; -} - -impl system::Config for Test { - type BaseCallFilter = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type Origin = Origin; - type Call = Call; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; -} - -impl pallet_template::Config for Test { - type Event = Event; -} - -// Build genesis storage according to the mock runtime. -pub fn new_test_ext() -> sp_io::TestExternalities { - system::GenesisConfig::default().build_storage::().unwrap().into() -} diff --git a/pallets/template/src/tests.rs b/pallets/template/src/tests.rs deleted file mode 100644 index aecf130..0000000 --- a/pallets/template/src/tests.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::{mock::*, Error}; -use frame_support::{assert_noop, assert_ok}; - -#[test] -fn it_works_for_default_value() { - new_test_ext().execute_with(|| { - // Dispatch a signed extrinsic. - assert_ok!(TemplateModule::do_something(Origin::signed(1), 42)); - // Read pallet storage and assert an expected result. - assert_eq!(TemplateModule::something(), Some(42)); - }); -} - -#[test] -fn correct_error_for_none_value() { - new_test_ext().execute_with(|| { - // Ensure the expected error is thrown when no value is present. - assert_noop!( - TemplateModule::cause_error(Origin::signed(1)), - Error::::NoneValue - ); - }); -} diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 8f0e134..e44649a 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -61,23 +61,20 @@ default-features = false git = 'https://github.com/paritytech/substrate.git' branch = 'rococo-v1' - [dependencies.polkadot-runtime-common] git = 'https://github.com/paritytech/polkadot' branch = 'rococo-v1' default-features = false - # Polkadot dependencies [dependencies.polkadot-primitives] git = 'https://github.com/paritytech/polkadot' branch = 'rococo-v1' default-features = false -[dependencies.pallet-authorship] +[dependencies.pallet-simple-staking] default-features = false -git = 'https://github.com/paritytech/substrate.git' -branch = 'rococo-v1' +path = '../../pallets/simple-staking' [dev-dependencies] serde = { version = "1.0.119" } @@ -100,6 +97,14 @@ git = 'https://github.com/paritytech/substrate.git' branch = 'rococo-v1' version = '3.0.0' +[dev-dependencies.pallet-authorship] +default-features = false +git = 'https://github.com/paritytech/substrate.git' +branch = 'rococo-v1' +version = '3.0.0' + + + [features] default = ["std"] std = [ @@ -109,7 +114,7 @@ std = [ 'frame-support/std', 'frame-executive/std', 'frame-system/std', - 'pallet-authorship/std', + 'pallet-simple-staking/std', 'pallet-balances/std', 'node-primitives/std', 'polkadot-runtime-common/std', diff --git a/runtime/common/src/impls.rs b/runtime/common/src/impls.rs index 07c8d6b..72ee436 100644 --- a/runtime/common/src/impls.rs +++ b/runtime/common/src/impls.rs @@ -21,23 +21,23 @@ use frame_support::traits::{Currency, Imbalance, OnUnbalanced}; pub type NegativeImbalance = as Currency<::AccountId>>::NegativeImbalance; /// Logic for the author to get a portion of fees. -pub struct ToAuthor(sp_std::marker::PhantomData); -impl OnUnbalanced> for ToAuthor +pub struct ToStakingPot(sp_std::marker::PhantomData); +impl OnUnbalanced> for ToStakingPot where - R: pallet_balances::Config + pallet_authorship::Config, + R: pallet_balances::Config + pallet_simple_staking::Config, ::AccountId: From, ::AccountId: Into, ::Event: From>, { fn on_nonzero_unbalanced(amount: NegativeImbalance) { let numeric_amount = amount.peek(); - let author = >::author(); + let staking_pot = >::account_id(); >::resolve_creating( - &>::author(), + &staking_pot, amount, ); >::deposit_event(pallet_balances::Event::Deposit( - author, + staking_pot, numeric_amount, )); } @@ -46,7 +46,7 @@ where pub struct DealWithFees(sp_std::marker::PhantomData); impl OnUnbalanced> for DealWithFees where - R: pallet_balances::Config + pallet_authorship::Config, + R: pallet_balances::Config + pallet_simple_staking::Config, ::AccountId: From, ::AccountId: Into, ::Event: From>, @@ -60,7 +60,7 @@ where if let Some(tips) = fees_then_tips.next() { tips.merge_into(&mut fees); } - as OnUnbalanced<_>>::on_unbalanced(fees); + as OnUnbalanced<_>>::on_unbalanced(fees); } } } @@ -69,8 +69,8 @@ where mod tests { use super::*; use frame_support::traits::FindAuthor; - use frame_support::{parameter_types, weights::DispatchClass}; - use frame_system::limits; + use frame_support::{parameter_types, weights::DispatchClass, PalletId}; + use frame_system::{limits, EnsureRoot}; use polkadot_primitives::v1::AccountId; use sp_core::H256; use sp_runtime::{ @@ -90,6 +90,7 @@ mod tests { { System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + SimpleStaking: pallet_simple_staking::{Pallet, Call, Storage, Event}, } ); @@ -130,6 +131,7 @@ mod tests { type OnKilledAccount = (); type SystemWeightInfo = (); type SS58Prefix = (); + type OnSetCode = (); } impl pallet_balances::Config for Test { @@ -151,6 +153,23 @@ mod tests { Some(Default::default()) } } + + + parameter_types! { + pub const PotId: PalletId = PalletId(*b"PotStake"); + pub const MaxAuthors: u32 = 20; + pub const MaxInvulnerables: u32 = 20; + } + impl pallet_simple_staking::Config for Test { + type Event = Event; + type Currency = Balances; + type UpdateOrigin = EnsureRoot; + type PotId = PotId; + type MaxAuthors = MaxAuthors; + type MaxInvulnerables = MaxInvulnerables; + type WeightInfo = (); + } + impl pallet_authorship::Config for Test { type FindAuthor = OneAuthor; type UncleGenerations = (); @@ -180,7 +199,7 @@ mod tests { DealWithFees::on_unbalanceds(vec![fee, tip].into_iter()); // Author gets 100% of tip and 100% of fee = 30 - assert_eq!(Balances::free_balance(AccountId::default()), 30); + assert_eq!(Balances::free_balance(SimpleStaking::account_id()), 30); }); } } diff --git a/runtime/statemine/Cargo.toml b/runtime/statemine/Cargo.toml index 23c577a..ece0770 100644 --- a/runtime/statemine/Cargo.toml +++ b/runtime/statemine/Cargo.toml @@ -274,28 +274,34 @@ git = 'https://github.com/paritytech/polkadot' branch = 'rococo-v1' default-features = false -[dependencies.template] +[dependencies.pallet-simple-staking] default-features = false -package = 'pallet-template' -path = '../../pallets/template' +path = '../../pallets/simple-staking' [dependencies.runtime-common] default-features = false +version = "0.8.30" path = '../common' [features] default = ['std'] runtime-benchmarks = [ + 'hex-literal', + 'xcm-builder/runtime-benchmarks', 'sp-runtime/runtime-benchmarks', 'frame-benchmarking', 'frame-support/runtime-benchmarks', 'frame-system-benchmarking', - 'hex-literal', 'frame-system/runtime-benchmarks', + 'pallet-assets/runtime-benchmarks', 'pallet-balances/runtime-benchmarks', + 'pallet-multisig/runtime-benchmarks', + 'pallet-proxy/runtime-benchmarks', + 'pallet-utility/runtime-benchmarks', 'pallet-timestamp/runtime-benchmarks', - 'template/runtime-benchmarks', + 'pallet-simple-staking/runtime-benchmarks', + 'pallet-xcm/runtime-benchmarks', ] std = [ 'codec/std', @@ -320,15 +326,15 @@ std = [ 'pallet-balances/std', 'pallet-multisig/std', 'pallet-proxy/std', - 'pallet-balances/std', 'pallet-utility/std', 'pallet-randomness-collective-flip/std', 'pallet-transaction-payment-rpc-runtime-api/std', 'pallet-timestamp/std', 'pallet-sudo/std', 'pallet-xcm/std', - 'node-primitives/std', 'pallet-transaction-payment/std', + 'pallet-simple-staking/std', + 'node-primitives/std', 'parachain-info/std', 'cumulus-pallet-parachain-system/std', "cumulus-pallet-xcmp-queue/std", @@ -341,5 +347,4 @@ std = [ 'polkadot-runtime-common/std', 'runtime-common/std', 'polkadot-primitives/std', - 'template/std', ] diff --git a/runtime/statemine/src/lib.rs b/runtime/statemine/src/lib.rs index ba1b4f5..be0fe0d 100644 --- a/runtime/statemine/src/lib.rs +++ b/runtime/statemine/src/lib.rs @@ -28,7 +28,7 @@ pub mod constants; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify, + AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify, AccountIdConversion }; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, @@ -70,7 +70,7 @@ pub use frame_support::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND}, DispatchClass, IdentityFee, Weight, }, - RuntimeDebug, StorageValue, + RuntimeDebug, StorageValue, PalletId }; use runtime_common::impls::DealWithFees; pub use pallet_balances::Call as BalancesCall; @@ -128,6 +128,8 @@ pub mod opaque { } } +mod weights; + pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("statemine"), impl_name: create_runtime_str!("statemine"), @@ -611,6 +613,30 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; } +parameter_types! { + pub const PotId: PalletId = PalletId(*b"PotStake"); + pub const MaxAuthors: u32 = 1000; + pub const MaxInvulnerables: u32 = 100; +} + +frame_support::ord_parameter_types! { + pub const RelayChainCouncilOrigin: AccountId = < + frame_support::PalletId + as + AccountIdConversion + >::into_account(&frame_support::PalletId(*b"TODOTODO")); +} + +impl pallet_simple_staking::Config for Runtime { + type Event = Event; + type Currency = Balances; + type UpdateOrigin = frame_system::EnsureSignedBy; + type PotId = PotId; + type MaxAuthors = MaxAuthors; + type MaxInvulnerables = MaxInvulnerables; + type WeightInfo = weights::pallet_simple_staking::WeightInfo; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime where @@ -631,7 +657,7 @@ construct_runtime!( Multisig: pallet_multisig::{Pallet, Call, Storage, Event}, Utility: pallet_utility::{Pallet, Call, Event}, Proxy: pallet_proxy::{Pallet, Call, Storage, Event}, - + SimpleStaking: pallet_simple_staking::{Pallet, Call, Storage, Event, Config}, // XCM helpers. XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event}, PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin}, @@ -773,7 +799,7 @@ impl_runtime_apis! { ) -> Result, sp_runtime::RuntimeString> { use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; - use frame_system_benchmarking::Module as SystemBench; + use frame_system_benchmarking::Pallet as SystemBench; impl frame_system_benchmarking::Config for Runtime {} let whitelist: Vec = vec![ @@ -793,8 +819,14 @@ impl_runtime_apis! { let params = (&config, &whitelist); add_benchmark!(params, batches, frame_system, SystemBench::); - add_benchmark!(params, batches, pallet_balances, Balances); - add_benchmark!(params, batches, pallet_timestamp, Timestamp); + //TODO we should re run all benchmarks for used pallets together + // add_benchmark!(params, batches, pallet_assets, Assets); + // add_benchmark!(params, batches, pallet_balances, Balances); + // add_benchmark!(params, batches, pallet_multisig, Multisig); + // add_benchmark!(params, batches, pallet_proxy, Proxy); + // add_benchmark!(params, batches, pallet_utility, Utility); + // add_benchmark!(params, batches, pallet_timestamp, Timestamp); + add_benchmark!(params, batches, pallet_simple_staking, SimpleStaking); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) diff --git a/runtime/statemine/src/weights/mod.rs b/runtime/statemine/src/weights/mod.rs new file mode 100644 index 0000000..aa58e41 --- /dev/null +++ b/runtime/statemine/src/weights/mod.rs @@ -0,0 +1 @@ +pub mod pallet_simple_staking; \ No newline at end of file diff --git a/runtime/statemine/src/weights/pallet_simple_staking.rs b/runtime/statemine/src/weights/pallet_simple_staking.rs new file mode 100644 index 0000000..81e9b39 --- /dev/null +++ b/runtime/statemine/src/weights/pallet_simple_staking.rs @@ -0,0 +1,72 @@ + +//! Autogenerated weights for pallet_simple_staking +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 +//! DATE: 2021-04-16, STEPS: `[20, ]`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("statemint-dev"), DB CACHE: 128 + +// Executed Command: +// ./target/release/statemint +// benchmark +// --chain +// statemint-dev +// --execution +// wasm +// --wasm-execution +// compiled +// --pallet +// pallet_simple_staking +// --extrinsic +// * +// --steps +// 20 +// --repeat +// 10 +// --raw +// --output +// ./ + + +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for pallet_simple_staking. +pub struct WeightInfo(PhantomData); +impl pallet_simple_staking::WeightInfo for WeightInfo { + fn set_invulnerables(b: u32, ) -> Weight { + (28_060_000 as Weight) + // Standard Error: 1_000 + .saturating_add((118_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn set_allowed_author_count() -> Weight { + (25_000_000 as Weight) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn set_author_bond() -> Weight { + (25_000_000 as Weight) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn register_as_author(c: u32, ) -> Weight { + (82_496_000 as Weight) + // Standard Error: 1_000 + .saturating_add((266_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn leave_intent(c: u32, ) -> Weight { + (65_836_000 as Weight) + // Standard Error: 2_000 + .saturating_add((273_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn note_author() -> Weight { + (97_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } +} diff --git a/runtime/statemint/Cargo.toml b/runtime/statemint/Cargo.toml index 764ea11..eb8e89f 100644 --- a/runtime/statemint/Cargo.toml +++ b/runtime/statemint/Cargo.toml @@ -274,28 +274,34 @@ git = 'https://github.com/paritytech/polkadot' branch = 'rococo-v1' default-features = false -[dependencies.template] +[dependencies.pallet-simple-staking] default-features = false -package = 'pallet-template' -path = '../../pallets/template' +path = '../../pallets/simple-staking' [dependencies.runtime-common] default-features = false +version = "0.8.30" path = '../common' [features] default = ['std'] runtime-benchmarks = [ + 'hex-literal', 'sp-runtime/runtime-benchmarks', + 'xcm-builder/runtime-benchmarks', 'frame-benchmarking', - 'frame-support/runtime-benchmarks', 'frame-system-benchmarking', - 'hex-literal', + 'frame-support/runtime-benchmarks', 'frame-system/runtime-benchmarks', + 'pallet-assets/runtime-benchmarks', 'pallet-balances/runtime-benchmarks', + 'pallet-multisig/runtime-benchmarks', + 'pallet-proxy/runtime-benchmarks', + 'pallet-utility/runtime-benchmarks', 'pallet-timestamp/runtime-benchmarks', - 'template/runtime-benchmarks', + 'pallet-xcm/runtime-benchmarks', + 'pallet-simple-staking/runtime-benchmarks', ] std = [ 'codec/std', @@ -320,15 +326,15 @@ std = [ 'pallet-balances/std', 'pallet-multisig/std', 'pallet-proxy/std', - 'pallet-balances/std', 'pallet-utility/std', 'pallet-randomness-collective-flip/std', 'pallet-transaction-payment-rpc-runtime-api/std', 'pallet-timestamp/std', 'pallet-sudo/std', 'pallet-xcm/std', - 'node-primitives/std', 'pallet-transaction-payment/std', + 'pallet-simple-staking/std', + 'node-primitives/std', 'parachain-info/std', 'cumulus-pallet-parachain-system/std', "cumulus-pallet-xcmp-queue/std", @@ -341,5 +347,4 @@ std = [ 'polkadot-runtime-common/std', 'runtime-common/std', 'polkadot-primitives/std', - 'template/std', ] diff --git a/runtime/statemint/src/lib.rs b/runtime/statemint/src/lib.rs index 08abaff..e3eaf22 100644 --- a/runtime/statemint/src/lib.rs +++ b/runtime/statemint/src/lib.rs @@ -28,7 +28,7 @@ pub mod constants; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify, + AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify, AccountIdConversion, }; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, @@ -70,7 +70,7 @@ pub use frame_support::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND}, DispatchClass, IdentityFee, Weight, }, - RuntimeDebug, StorageValue, + RuntimeDebug, StorageValue, PalletId }; use runtime_common::impls::DealWithFees; pub use pallet_balances::Call as BalancesCall; @@ -128,6 +128,9 @@ pub mod opaque { } } +mod weights; + + pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("statemint"), impl_name: create_runtime_str!("statemint"), @@ -611,6 +614,30 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; } +parameter_types! { + pub const PotId: PalletId = PalletId(*b"PotStake"); + pub const MaxAuthors: u32 = 1000; + pub const MaxInvulnerables: u32 = 100; +} + +frame_support::ord_parameter_types! { + pub const RelayChainCouncilOrigin: AccountId = < + frame_support::PalletId + as + AccountIdConversion + >::into_account(&frame_support::PalletId(*b"TODOTODO")); +} + +impl pallet_simple_staking::Config for Runtime { + type Event = Event; + type Currency = Balances; + type UpdateOrigin = frame_system::EnsureSignedBy; + type PotId = PotId; // Needs to be some random inaccessible account. (`ModuleId`) + type MaxAuthors = MaxAuthors; + type MaxInvulnerables = MaxInvulnerables; + type WeightInfo = weights::pallet_simple_staking::WeightInfo; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime where @@ -631,6 +658,7 @@ construct_runtime!( Multisig: pallet_multisig::{Pallet, Call, Storage, Event}, Utility: pallet_utility::{Pallet, Call, Event}, Proxy: pallet_proxy::{Pallet, Call, Storage, Event}, + SimpleStaking: pallet_simple_staking::{Pallet, Call, Storage, Event, Config}, // XCM helpers. XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event}, @@ -773,7 +801,7 @@ impl_runtime_apis! { ) -> Result, sp_runtime::RuntimeString> { use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; - use frame_system_benchmarking::Module as SystemBench; + use frame_system_benchmarking::Pallet as SystemBench; impl frame_system_benchmarking::Config for Runtime {} let whitelist: Vec = vec![ @@ -793,8 +821,15 @@ impl_runtime_apis! { let params = (&config, &whitelist); add_benchmark!(params, batches, frame_system, SystemBench::); - add_benchmark!(params, batches, pallet_balances, Balances); - add_benchmark!(params, batches, pallet_timestamp, Timestamp); + + //TODO we should re run all benchmarks for used pallets together + // add_benchmark!(params, batches, pallet_assets, Assets); + // add_benchmark!(params, batches, pallet_balances, Balances); + // add_benchmark!(params, batches, pallet_multisig, Multisig); + // add_benchmark!(params, batches, pallet_proxy, Proxy); + // add_benchmark!(params, batches, pallet_utility, Utility); + // add_benchmark!(params, batches, pallet_timestamp, Timestamp); + add_benchmark!(params, batches, pallet_simple_staking, SimpleStaking); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) diff --git a/runtime/statemint/src/weights/mod.rs b/runtime/statemint/src/weights/mod.rs new file mode 100644 index 0000000..aa58e41 --- /dev/null +++ b/runtime/statemint/src/weights/mod.rs @@ -0,0 +1 @@ +pub mod pallet_simple_staking; \ No newline at end of file diff --git a/runtime/statemint/src/weights/pallet_simple_staking.rs b/runtime/statemint/src/weights/pallet_simple_staking.rs new file mode 100644 index 0000000..81e9b39 --- /dev/null +++ b/runtime/statemint/src/weights/pallet_simple_staking.rs @@ -0,0 +1,72 @@ + +//! Autogenerated weights for pallet_simple_staking +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 +//! DATE: 2021-04-16, STEPS: `[20, ]`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("statemint-dev"), DB CACHE: 128 + +// Executed Command: +// ./target/release/statemint +// benchmark +// --chain +// statemint-dev +// --execution +// wasm +// --wasm-execution +// compiled +// --pallet +// pallet_simple_staking +// --extrinsic +// * +// --steps +// 20 +// --repeat +// 10 +// --raw +// --output +// ./ + + +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for pallet_simple_staking. +pub struct WeightInfo(PhantomData); +impl pallet_simple_staking::WeightInfo for WeightInfo { + fn set_invulnerables(b: u32, ) -> Weight { + (28_060_000 as Weight) + // Standard Error: 1_000 + .saturating_add((118_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn set_allowed_author_count() -> Weight { + (25_000_000 as Weight) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn set_author_bond() -> Weight { + (25_000_000 as Weight) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn register_as_author(c: u32, ) -> Weight { + (82_496_000 as Weight) + // Standard Error: 1_000 + .saturating_add((266_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn leave_intent(c: u32, ) -> Weight { + (65_836_000 as Weight) + // Standard Error: 2_000 + .saturating_add((273_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn note_author() -> Weight { + (97_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } +}