From f5e11478a243c2619adbfbdca7fcb8192b62d30a Mon Sep 17 00:00:00 2001 From: Loris Moulin Date: Tue, 14 Oct 2025 18:59:53 -0300 Subject: [PATCH 1/3] remove governance deadcode --- Cargo.lock | 22 - Cargo.toml | 3 - node/src/chain_spec/localnet.rs | 18 - node/src/chain_spec/mod.rs | 2 +- pallets/admin-utils/src/tests/mock.rs | 7 +- pallets/collective/Cargo.toml | 55 - pallets/collective/README.md | 25 - pallets/collective/src/benchmarking.rs | 606 ------- pallets/collective/src/lib.rs | 1247 ------------- pallets/collective/src/tests.rs | 1587 ----------------- pallets/collective/src/weights.rs | 554 ------ pallets/subtensor/Cargo.toml | 8 - pallets/subtensor/src/benchmarks.rs | 12 - pallets/subtensor/src/coinbase/root.rs | 170 +- pallets/subtensor/src/lib.rs | 89 - pallets/subtensor/src/macros/config.rs | 12 - pallets/subtensor/src/macros/dispatches.rs | 90 - pallets/subtensor/src/macros/errors.rs | 4 - pallets/subtensor/src/macros/events.rs | 9 - .../migrations/migrate_create_root_network.rs | 15 +- .../migrate_remove_unused_maps_and_values.rs | 30 +- pallets/subtensor/src/migrations/mod.rs | 20 + pallets/subtensor/src/swap/swap_hotkey.rs | 31 +- pallets/subtensor/src/tests/mock.rs | 171 +- pallets/subtensor/src/tests/mod.rs | 1 - pallets/subtensor/src/tests/senate.rs | 893 ---------- pallets/subtensor/src/tests/swap_coldkey.rs | 45 - pallets/subtensor/src/tests/swap_hotkey.rs | 28 - .../src/tests/swap_hotkey_with_subnet.rs | 27 - pallets/subtensor/src/utils/misc.rs | 19 - pallets/transaction-fee/src/tests/mock.rs | 7 +- pallets/utility/Cargo.toml | 3 - pallets/utility/src/tests.rs | 180 +- runtime/Cargo.toml | 10 - runtime/src/lib.rs | 206 +-- runtime/tests/pallet_proxy.rs | 45 +- support/linting/src/pallet_index.rs | 11 - .../src/runtime/parse/pallet_decl.rs | 3 +- support/tools/src/bump_version.rs | 3 +- 39 files changed, 66 insertions(+), 6202 deletions(-) delete mode 100644 pallets/collective/Cargo.toml delete mode 100644 pallets/collective/README.md delete mode 100644 pallets/collective/src/benchmarking.rs delete mode 100644 pallets/collective/src/lib.rs delete mode 100644 pallets/collective/src/tests.rs delete mode 100644 pallets/collective/src/weights.rs delete mode 100644 pallets/subtensor/src/tests/senate.rs diff --git a/Cargo.lock b/Cargo.lock index e20719b891..dd3a9012f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8291,7 +8291,6 @@ dependencies = [ "pallet-grandpa", "pallet-hotfix-sufficients", "pallet-insecure-randomness-collective-flip", - "pallet-membership", "pallet-multisig", "pallet-nomination-pools", "pallet-nomination-pools-runtime-api", @@ -8306,7 +8305,6 @@ dependencies = [ "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-subtensor", - "pallet-subtensor-collective", "pallet-subtensor-proxy", "pallet-subtensor-swap", "pallet-subtensor-swap-runtime-api", @@ -10654,10 +10652,8 @@ dependencies = [ "pallet-commitments", "pallet-crowdloan", "pallet-drand", - "pallet-membership", "pallet-preimage", "pallet-scheduler", - "pallet-subtensor-collective", "pallet-subtensor-proxy", "pallet-subtensor-swap", "pallet-subtensor-utility", @@ -10689,23 +10685,6 @@ dependencies = [ "w3f-bls 0.1.3", ] -[[package]] -name = "pallet-subtensor-collective" -version = "4.0.0-dev" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "subtensor-macros", -] - [[package]] name = "pallet-subtensor-proxy" version = "40.1.0" @@ -10782,7 +10761,6 @@ dependencies = [ "frame-system", "pallet-balances", "pallet-root-testing", - "pallet-subtensor-collective", "pallet-timestamp", "parity-scale-codec", "scale-info", diff --git a/Cargo.toml b/Cargo.toml index bae503765c..b962200509 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,6 @@ useless_conversion = "allow" # until polkadot is patched [workspace.dependencies] node-subtensor-runtime = { path = "runtime", default-features = false } pallet-admin-utils = { path = "pallets/admin-utils", default-features = false } -pallet-subtensor-collective = { path = "pallets/collective", default-features = false } pallet-commitments = { path = "pallets/commitments", default-features = false } pallet-registry = { path = "pallets/registry", default-features = false } pallet-crowdloan = { path = "pallets/crowdloan", default-features = false } @@ -136,7 +135,6 @@ pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "p pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2503-6", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2503-6", default-features = false } pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2503-6", default-features = false } -pallet-membership = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2503-6", default-features = false } pallet-multisig = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2503-6", default-features = false } pallet-preimage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2503-6", default-features = false } pallet-safe-mode = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2503-6", default-features = false } @@ -475,7 +473,6 @@ cumulus-client-parachain-inherent = { git = "https://github.com/opentensor/polka sc-runtime-utilities = { git = "https://github.com/opentensor/polkadot-sdk.git", rev = "7d1855ebff04c96bb273b43cfd5a5cf6fa2a7234" } frame-metadata-hash-extension = { git = "https://github.com/opentensor/polkadot-sdk.git", rev = "7d1855ebff04c96bb273b43cfd5a5cf6fa2a7234" } pallet-nomination-pools = { git = "https://github.com/opentensor/polkadot-sdk.git", rev = "7d1855ebff04c96bb273b43cfd5a5cf6fa2a7234" } -pallet-membership = { git = "https://github.com/opentensor/polkadot-sdk.git", rev = "7d1855ebff04c96bb273b43cfd5a5cf6fa2a7234" } pallet-multisig = { git = "https://github.com/opentensor/polkadot-sdk.git", rev = "7d1855ebff04c96bb273b43cfd5a5cf6fa2a7234" } pallet-nomination-pools-runtime-api = { git = "https://github.com/opentensor/polkadot-sdk.git", rev = "7d1855ebff04c96bb273b43cfd5a5cf6fa2a7234" } pallet-preimage = { git = "https://github.com/opentensor/polkadot-sdk.git", rev = "7d1855ebff04c96bb273b43cfd5a5cf6fa2a7234" } diff --git a/node/src/chain_spec/localnet.rs b/node/src/chain_spec/localnet.rs index 577f42e54a..d65849ae94 100644 --- a/node/src/chain_spec/localnet.rs +++ b/node/src/chain_spec/localnet.rs @@ -99,18 +99,6 @@ fn localnet_genesis( } } - let trimvirate_members: Vec = bounded_vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - ]; - - let senate_members: Vec = bounded_vec![ - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - ]; - serde_json::json!({ "balances": { "balances": balances }, "aura": { @@ -125,12 +113,6 @@ fn localnet_genesis( "sudo": { "key": Some(get_account_id_from_seed::("Alice")) }, - "triumvirateMembers": { - "members": trimvirate_members - }, - "senateMembers": { - "members": senate_members, - }, "evmChainId": { "chainId": 42, }, diff --git a/node/src/chain_spec/mod.rs b/node/src/chain_spec/mod.rs index 90a1493aa4..85ca78d353 100644 --- a/node/src/chain_spec/mod.rs +++ b/node/src/chain_spec/mod.rs @@ -12,7 +12,7 @@ use sc_service::ChainType; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::crypto::Ss58Codec; -use sp_core::{H256, Pair, Public, bounded_vec, sr25519}; +use sp_core::{H256, Pair, Public, sr25519}; use sp_runtime::AccountId32; use sp_runtime::traits::{IdentifyAccount, Verify}; use std::collections::HashSet; diff --git a/pallets/admin-utils/src/tests/mock.rs b/pallets/admin-utils/src/tests/mock.rs index 50b9ccd282..ed62be55d8 100644 --- a/pallets/admin-utils/src/tests/mock.rs +++ b/pallets/admin-utils/src/tests/mock.rs @@ -7,7 +7,7 @@ use frame_support::{ traits::{Everything, Hooks, InherentBuilder, PrivilegeCmp}, }; use frame_system::{self as system, offchain::CreateTransactionBase}; -use frame_system::{EnsureNever, EnsureRoot, limits}; +use frame_system::{EnsureRoot, limits}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_consensus_grandpa::AuthorityList as GrandpaAuthorityList; use sp_core::U256; @@ -128,7 +128,6 @@ parameter_types! { pub const InitialMinDifficulty: u64 = 1; pub const InitialMaxDifficulty: u64 = u64::MAX; pub const InitialRAORecycledForRegistration: u64 = 0; - pub const InitialSenateRequiredStakePercentage: u64 = 2; // 2 percent of total stake pub const InitialNetworkImmunityPeriod: u64 = 1_296_000; pub const InitialNetworkMinLockCost: u64 = 100_000_000_000; pub const InitialSubnetOwnerCut: u16 = 0; // 0%. 100% of rewards go to validators + miners. @@ -160,9 +159,6 @@ impl pallet_subtensor::Config for Test { type Currency = Balances; type InitialIssuance = InitialIssuance; type SudoRuntimeCall = TestRuntimeCall; - type CouncilOrigin = EnsureNever; - type SenateMembers = (); - type TriumvirateInterface = (); type Scheduler = Scheduler; type InitialMinAllowedWeights = InitialMinAllowedWeights; type InitialEmissionValue = InitialEmissionValue; @@ -205,7 +201,6 @@ impl pallet_subtensor::Config for Test { type MinBurnUpperBound = MinBurnUpperBound; type MaxBurnLowerBound = MaxBurnLowerBound; type InitialRAORecycledForRegistration = InitialRAORecycledForRegistration; - type InitialSenateRequiredStakePercentage = InitialSenateRequiredStakePercentage; type InitialNetworkImmunityPeriod = InitialNetworkImmunityPeriod; type InitialNetworkMinLockCost = InitialNetworkMinLockCost; type InitialSubnetOwnerCut = InitialSubnetOwnerCut; diff --git a/pallets/collective/Cargo.toml b/pallets/collective/Cargo.toml deleted file mode 100644 index 4cb8e1422e..0000000000 --- a/pallets/collective/Cargo.toml +++ /dev/null @@ -1,55 +0,0 @@ -[package] -name = "pallet-subtensor-collective" -version = "4.0.0-dev" -authors = ["Parity Technologies , Opentensor Technologies"] -edition.workspace = true -license = "Apache-2.0" -homepage = "https://bittensor.com" -repository = "https://github.com/opentensor/subtensor" -description = "Collective system: Members of a set of account IDs can make their collective feelings known through dispatched calls from one of two specialized origins." -readme = "README.md" - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -subtensor-macros.workspace = true -codec = { workspace = true, features = ["derive"] } -log.workspace = true -scale-info = { workspace = true, features = ["derive"] } -frame-benchmarking = { workspace = true, optional = true } -frame-support.workspace = true -frame-system.workspace = true -sp-core.workspace = true -sp-io.workspace = true -sp-runtime.workspace = true -sp-std.workspace = true - -[features] -default = ["std"] -std = [ - "codec/std", - "frame-benchmarking?/std", - "frame-support/std", - "frame-system/std", - "log/std", - "scale-info/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", -] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", - "sp-runtime/try-runtime", -] diff --git a/pallets/collective/README.md b/pallets/collective/README.md deleted file mode 100644 index 444927e51d..0000000000 --- a/pallets/collective/README.md +++ /dev/null @@ -1,25 +0,0 @@ -Collective system: Members of a set of account IDs can make their collective feelings known -through dispatched calls from one of two specialized origins. - -The membership can be provided in one of two ways: either directly, using the Root-dispatchable -function `set_members`, or indirectly, through implementing the `ChangeMembers`. -The pallet assumes that the amount of members stays at or below `MaxMembers` for its weight -calculations, but enforces this neither in `set_members` nor in `change_members_sorted`. - -A "prime" member may be set to help determine the default vote behavior based on chain -config. If `PrimeDefaultVote` is used, the prime vote acts as the default vote in case of any -abstentions after the voting period. If `MoreThanMajorityThenPrimeDefaultVote` is used, then -abstentations will first follow the majority of the collective voting, and then the prime -member. - -Voting happens through motions comprising a proposal (i.e. a dispatchable) plus a -number of approvals required for it to pass and be called. Motions are open for members to -vote on for a minimum period given by `MotionDuration`. As soon as the required number of -approvals is given, the motion is closed and executed. If the number of approvals is not reached -during the voting period, then `close` may be called by any account in order to force the end -the motion explicitly. If a prime member is defined, then their vote is used instead of any -abstentions and the proposal is executed if there are enough approvals counting the new votes. - -If there are not, or if no prime member is set, then the motion is dropped without being executed. - -License: Apache-2.0 diff --git a/pallets/collective/src/benchmarking.rs b/pallets/collective/src/benchmarking.rs deleted file mode 100644 index ec5c736614..0000000000 --- a/pallets/collective/src/benchmarking.rs +++ /dev/null @@ -1,606 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 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. - -//! Staking pallet benchmarking. -#![allow( - clippy::arithmetic_side_effects, - clippy::expect_used, - clippy::indexing_slicing -)] - -use super::*; -use crate::Pallet as Collective; - -use sp_runtime::traits::Bounded; -use sp_std::mem::size_of; - -use frame_benchmarking::v1::{account, benchmarks_instance_pallet, whitelisted_caller}; -use frame_system::{Call as SystemCall, Pallet as System, RawOrigin as SystemOrigin}; - -const SEED: u32 = 0; - -const MAX_BYTES: u32 = 1_024; - -fn assert_last_event( - generic_event: ::RuntimeEvent, -) { - frame_system::Pallet::::assert_last_event(generic_event.into()); -} - -fn id_to_remark_data(id: u32, length: usize) -> Vec { - id.to_le_bytes().into_iter().cycle().take(length).collect() -} - -benchmarks_instance_pallet! { - set_members { - let m in 0 .. T::MaxMembers::get(); - let n in 0 .. T::MaxMembers::get(); - let p in 0 .. T::MaxProposals::get(); - - // Set old members. - // We compute the difference of old and new members, so it should influence timing. - let mut old_members = vec![]; - for i in 0 .. m { - let old_member = account::("old member", i, SEED); - old_members.push(old_member); - } - let old_members_count = old_members.len() as u32; - - Collective::::set_members( - SystemOrigin::Root.into(), - old_members.clone(), - old_members.last().cloned(), - T::MaxMembers::get(), - )?; - - // If there were any old members generate a bunch of proposals. - if m > 0 { - // Set a high threshold for proposals passing so that they stay around. - let threshold = m.max(2); - // Length of the proposals should be irrelevant to `set_members`. - let length = 100; - for i in 0 .. p { - // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(i, length) }.into(); - Collective::::propose( - SystemOrigin::Signed(old_members.last().expect("m is greater than 0; old_members must have at least 1 element; qed").clone()).into(), - Box::new(proposal.clone()), - MAX_BYTES, - TryInto::>::try_into(3u64).ok().expect("convert u64 to block number.") - )?; - let hash = T::Hashing::hash_of(&proposal); - // Vote on the proposal to increase state relevant for `set_members`. - // Not voting for last old member because they proposed and not voting for the first member - // to keep the proposal from passing. - for j in 2 .. m - 1 { - let voter = &old_members[j as usize]; - let approve = true; - Collective::::vote( - SystemOrigin::Signed(voter.clone()).into(), - hash, - i, - approve, - )?; - } - } - } - - // Construct `new_members`. - // It should influence timing since it will sort this vector. - let mut new_members = vec![]; - for i in 0 .. n { - let member = account::("member", i, SEED); - new_members.push(member); - } - - }: _(SystemOrigin::Root, new_members.clone(), new_members.last().cloned(), T::MaxMembers::get()) - verify { - new_members.sort(); - assert_eq!(Collective::::members(), new_members); - } - - execute { - let b in 2 .. MAX_BYTES; - let m in 1 .. T::MaxMembers::get(); - - let bytes_in_storage = b + size_of::() as u32; - - // Construct `members`. - let mut members = vec![]; - for i in 0 .. m - 1 { - let member = account::("member", i, SEED); - members.push(member); - } - - let caller: T::AccountId = whitelisted_caller(); - members.push(caller.clone()); - - Collective::::set_members(SystemOrigin::Root.into(), members, None, T::MaxMembers::get())?; - - let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(1, b as usize) }.into(); - - }: _(SystemOrigin::Signed(caller), Box::new(proposal.clone()), bytes_in_storage) - verify { - let proposal_hash = T::Hashing::hash_of(&proposal); - // Note that execution fails due to mis-matched origin - assert_last_event::( - Event::MemberExecuted { proposal_hash, result: Ok(()) }.into() - ); - } - - // This tests when proposal is created and queued as "proposed" - propose_proposed { - let b in 2 .. MAX_BYTES; - let m in 2 .. T::MaxMembers::get(); - let p in 1 .. T::MaxProposals::get(); - - let bytes_in_storage = b + size_of::() as u32; - - // Construct `members`. - let mut members = vec![]; - for i in 0 .. m - 1 { - let member = account::("member", i, SEED); - members.push(member); - } - let caller: T::AccountId = whitelisted_caller(); - members.push(caller.clone()); - Collective::::set_members(SystemOrigin::Root.into(), members, None, T::MaxMembers::get())?; - - let threshold = (m / 2) + 1; - // Add previous proposals. - for i in 0 .. p - 1 { - // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(i, b as usize) }.into(); - Collective::::propose( - SystemOrigin::Signed(caller.clone()).into(), - Box::new(proposal), - bytes_in_storage, - TryInto::>::try_into(3u64).ok().expect("convert u64 to block number.") - )?; - } - - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - - let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(p, b as usize) }.into(); - - }: propose(SystemOrigin::Signed(caller.clone()), Box::new(proposal.clone()), bytes_in_storage, TryInto::>::try_into(3u64).ok().expect("convert u64 to block number.")) - verify { - // New proposal is recorded - assert_eq!(Collective::::proposals().len(), p as usize); - let proposal_hash = T::Hashing::hash_of(&proposal); - assert_last_event::(Event::Proposed { account: caller, proposal_index: p - 1, proposal_hash, threshold }.into()); - } - - vote { - // We choose 5 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) - let m in 5 .. T::MaxMembers::get(); - - let p = T::MaxProposals::get(); - let b = MAX_BYTES; - let bytes_in_storage = b + size_of::() as u32; - - // Construct `members`. - let mut members = vec![]; - let proposer: T::AccountId = account::("proposer", 0, SEED); - members.push(proposer.clone()); - for i in 1 .. m - 1 { - let member = account::("member", i, SEED); - members.push(member); - } - let voter: T::AccountId = account::("voter", 0, SEED); - members.push(voter.clone()); - Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None, T::MaxMembers::get())?; - - // Threshold is 1 less than the number of members so that one person can vote nay - let threshold = m - 1; - - // Add previous proposals - let mut last_hash = T::Hash::default(); - for i in 0 .. p { - // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(i, b as usize) }.into(); - Collective::::propose( - SystemOrigin::Signed(proposer.clone()).into(), - Box::new(proposal.clone()), - bytes_in_storage, - TryInto::>::try_into(3u64).ok().expect("convert u64 to block number.") - )?; - last_hash = T::Hashing::hash_of(&proposal); - } - - let index = p - 1; - // Have almost everyone vote aye on last proposal, while keeping it from passing. - for j in 0 .. m - 3 { - let voter = &members[j as usize]; - let approve = true; - Collective::::vote( - SystemOrigin::Signed(voter.clone()).into(), - last_hash, - index, - approve, - )?; - } - // Voter votes aye without resolving the vote. - let approve = true; - Collective::::vote( - SystemOrigin::Signed(voter.clone()).into(), - last_hash, - index, - approve, - )?; - - assert_eq!(Collective::::proposals().len(), p as usize); - - // Voter switches vote to nay, but does not kill the vote, just updates + inserts - let approve = false; - - // Whitelist voter account from further DB operations. - let voter_key = frame_system::Account::::hashed_key_for(&voter); - frame_benchmarking::benchmarking::add_to_whitelist(voter_key.into()); - }: _(SystemOrigin::Signed(voter), last_hash, index, approve) - verify { - // All proposals exist and the last proposal has just been updated. - assert_eq!(Collective::::proposals().len(), p as usize); - let voting = Collective::::voting(last_hash).ok_or("Proposal Missing")?; - assert_eq!(voting.ayes.len(), (m - 3) as usize); - assert_eq!(voting.nays.len(), 1); - } - - close_early_disapproved { - // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) - let m in 4 .. T::MaxMembers::get(); - let p in 1 .. T::MaxProposals::get(); - - let bytes = 100; - let bytes_in_storage = bytes + size_of::() as u32; - - // Construct `members`. - let mut members = vec![]; - let proposer = account::("proposer", 0, SEED); - members.push(proposer.clone()); - for i in 1 .. m - 1 { - let member = account::("member", i, SEED); - members.push(member); - } - let voter = account::("voter", 0, SEED); - members.push(voter.clone()); - Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None, T::MaxMembers::get())?; - - // Add previous proposals - let mut last_hash = T::Hash::default(); - for i in 0 .. p { - // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(i, bytes as usize) }.into(); - Collective::::propose( - SystemOrigin::Signed(proposer.clone()).into(), - Box::new(proposal.clone()), - bytes_in_storage, - TryInto::>::try_into(3u64).ok().expect("convert u64 to block number.") - )?; - last_hash = T::Hashing::hash_of(&proposal); - } - - let index = p - 1; - // Have most everyone vote nay on last proposal, while keeping it from passing. - for j in 0 .. m - 2 { - let voter = &members[j as usize]; - let approve = false; - Collective::::vote( - SystemOrigin::Signed(voter.clone()).into(), - last_hash, - index, - approve, - )?; - } - - // Voter votes aye without resolving the vote. - let approve = true; - Collective::::vote( - SystemOrigin::Signed(voter.clone()).into(), - last_hash, - index, - approve, - )?; - - assert_eq!(Collective::::proposals().len(), p as usize); - - // Whitelist voter account from further DB operations. - let voter_key = frame_system::Account::::hashed_key_for(&voter); - frame_benchmarking::benchmarking::add_to_whitelist(voter_key.into()); - }: close(SystemOrigin::Root, last_hash, index, Weight::MAX, bytes_in_storage) - verify { - // The last proposal is removed. - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(Event::Disapproved { proposal_hash: last_hash }.into()); - } - - close_early_approved { - let b in 2 .. MAX_BYTES; - // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) - let m in 4 .. T::MaxMembers::get(); - let p in 1 .. T::MaxProposals::get(); - - let bytes_in_storage = b + size_of::() as u32; - - // Construct `members`. - let mut members = vec![]; - for i in 0 .. m - 1 { - let member = account::("member", i, SEED); - members.push(member); - } - let caller: T::AccountId = whitelisted_caller(); - members.push(caller.clone()); - Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None, T::MaxMembers::get())?; - - // Add previous proposals - let mut last_hash = T::Hash::default(); - for i in 0 .. p { - // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(i, b as usize) }.into(); - Collective::::propose( - SystemOrigin::Signed(caller.clone()).into(), - Box::new(proposal.clone()), - bytes_in_storage, - TryInto::>::try_into(3u64).ok().expect("convert u64 to block number.") - )?; - last_hash = T::Hashing::hash_of(&proposal); - } - - // Caller switches vote to nay on their own proposal, allowing them to be the deciding approval vote - Collective::::vote( - SystemOrigin::Signed(caller.clone()).into(), - last_hash, - p - 1, - false, - )?; - - // Have almost everyone vote aye on last proposal, while keeping it from failing. - for j in 2 .. m - 1 { - let voter = &members[j as usize]; - let approve = true; - Collective::::vote( - SystemOrigin::Signed(voter.clone()).into(), - last_hash, - p - 1, - approve, - )?; - } - - // Member zero is the first aye - Collective::::vote( - SystemOrigin::Signed(members[0].clone()).into(), - last_hash, - p - 1, - true, - )?; - - assert_eq!(Collective::::proposals().len(), p as usize); - - // Caller switches vote to aye, which passes the vote - let index = p - 1; - let approve = true; - Collective::::vote( - SystemOrigin::Signed(caller.clone()).into(), - last_hash, - index, approve, - )?; - - }: close(SystemOrigin::Root, last_hash, index, Weight::MAX, bytes_in_storage) - verify { - // The last proposal is removed. - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(Event::Executed { proposal_hash: last_hash, result: Ok(()) }.into()); - } - - close_disapproved { - // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) - let m in 4 .. T::MaxMembers::get(); - let p in 1 .. T::MaxProposals::get(); - - let bytes = 100; - let bytes_in_storage = bytes + size_of::() as u32; - - // Construct `members`. - let mut members = vec![]; - for i in 0 .. m - 1 { - let member = account::("member", i, SEED); - members.push(member); - } - let caller: T::AccountId = whitelisted_caller(); - members.push(caller.clone()); - Collective::::set_members( - SystemOrigin::Root.into(), - members.clone(), - Some(caller.clone()), - T::MaxMembers::get(), - )?; - - // Add proposals - let mut last_hash = T::Hash::default(); - for i in 0 .. p { - // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(i, bytes as usize) }.into(); - Collective::::propose( - SystemOrigin::Signed(caller.clone()).into(), - Box::new(proposal.clone()), - bytes_in_storage, - TryInto::>::try_into(3u64).ok().expect("convert u64 to block number.") - )?; - last_hash = T::Hashing::hash_of(&proposal); - } - - let index = p - 1; - // Have almost everyone vote aye on last proposal, while keeping it from passing. - // A few abstainers will be the nay votes needed to fail the vote. - let mut yes_votes: MemberCount = 0; - for j in 2 .. m / 2 { - let voter = &members[j as usize]; - let approve = true; - yes_votes += 1; - // vote aye till a prime nay vote keeps the proposal disapproved. - if <>::DefaultVote as DefaultVote>::default_vote( - Some(false), - yes_votes, - 0, - m,) { - break; - } - Collective::::vote( - SystemOrigin::Signed(voter.clone()).into(), - last_hash, - index, - approve, - )?; - } - - // caller is prime, prime votes nay - Collective::::vote( - SystemOrigin::Signed(caller.clone()).into(), - last_hash, - index, - false, - )?; - - System::::set_block_number(BlockNumberFor::::max_value()); - assert_eq!(Collective::::proposals().len(), p as usize); - - // Prime nay will close it as disapproved - }: close(SystemOrigin::Root, last_hash, index, Weight::MAX, bytes_in_storage) - verify { - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(Event::Disapproved { proposal_hash: last_hash }.into()); - } - - close_approved { - let b in 2 .. MAX_BYTES; - // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) - let m in 4 .. T::MaxMembers::get(); - let p in 1 .. T::MaxProposals::get(); - - let bytes_in_storage = b + size_of::() as u32; - - // Construct `members`. - let mut members = vec![]; - for i in 0 .. m - 1 { - let member = account::("member", i, SEED); - members.push(member); - } - let caller: T::AccountId = whitelisted_caller(); - members.push(caller.clone()); - Collective::::set_members( - SystemOrigin::Root.into(), - members.clone(), - Some(caller.clone()), - T::MaxMembers::get(), - )?; - - // Add proposals - let mut last_hash = T::Hash::default(); - for i in 0 .. p { - // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(i, b as usize) }.into(); - Collective::::propose( - SystemOrigin::Signed(caller.clone()).into(), - Box::new(proposal.clone()), - bytes_in_storage, - TryInto::>::try_into(3u64).ok().expect("convert u64 to block number.") - )?; - last_hash = T::Hashing::hash_of(&proposal); - } - - // The prime member votes aye, so abstentions default to aye. - Collective::::vote( - SystemOrigin::Signed(caller.clone()).into(), - last_hash, - p - 1, - true // Vote aye. - )?; - - // Have almost everyone vote nay on last proposal, while keeping it from failing. - // A few abstainers will be the aye votes needed to pass the vote. - for j in 2 .. m / 2 { - let voter = &members[j as usize]; - let approve = false; - Collective::::vote( - SystemOrigin::Signed(voter.clone()).into(), - last_hash, - p - 1, - approve - )?; - } - - // caller is prime, prime already votes aye by creating the proposal - System::::set_block_number(BlockNumberFor::::max_value()); - assert_eq!(Collective::::proposals().len(), p as usize); - - // Prime aye will close it as approved - }: close(SystemOrigin::Root, last_hash, p - 1, Weight::MAX, bytes_in_storage) - verify { - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(Event::Executed { proposal_hash: last_hash, result: Ok(()) }.into()); - } - - disapprove_proposal { - let p in 1 .. T::MaxProposals::get(); - - let m = 3; - let b = MAX_BYTES; - let bytes_in_storage = b + size_of::() as u32; - - // Construct `members`. - let mut members = vec![]; - for i in 0 .. m - 1 { - let member = account::("member", i, SEED); - members.push(member); - } - let caller = account::("caller", 0, SEED); - members.push(caller.clone()); - Collective::::set_members( - SystemOrigin::Root.into(), - members.clone(), - Some(caller.clone()), - T::MaxMembers::get(), - )?; - - // Threshold is one less than total members so that two nays will disapprove the vote - let threshold = m - 1; - - // Add proposals - let mut last_hash = T::Hash::default(); - for i in 0 .. p { - // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(i, b as usize) }.into(); - Collective::::propose( - SystemOrigin::Signed(caller.clone()).into(), - Box::new(proposal.clone()), - bytes_in_storage, - TryInto::>::try_into(3u64).ok().expect("convert u64 to block number.") - )?; - last_hash = T::Hashing::hash_of(&proposal); - } - - System::::set_block_number(BlockNumberFor::::max_value()); - assert_eq!(Collective::::proposals().len(), p as usize); - - }: _(SystemOrigin::Root, last_hash) - verify { - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(Event::Disapproved { proposal_hash: last_hash }.into()); - } - - impl_benchmark_test_suite!(Collective, crate::tests::new_test_ext(), crate::tests::Test); -} diff --git a/pallets/collective/src/lib.rs b/pallets/collective/src/lib.rs deleted file mode 100644 index 8a9fc09fb5..0000000000 --- a/pallets/collective/src/lib.rs +++ /dev/null @@ -1,1247 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 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. - -//! Collective system: Members of a set of account IDs can make their collective feelings known -//! through dispatched calls from one of two specialized origins. -//! -//! The membership can be provided in one of two ways: either directly, using the Root-dispatchable -//! function `set_members`, or indirectly, through implementing the `ChangeMembers`. -//! The pallet assumes that the amount of members stays at or below `MaxMembers` for its weight -//! calculations, but enforces this neither in `set_members` nor in `change_members_sorted`. -//! -//! A "prime" member may be set to help determine the default vote behavior based on chain -//! config. If `PrimeDefaultVote` is used, the prime vote acts as the default vote in case of any -//! abstentions after the voting period. If `MoreThanMajorityThenPrimeDefaultVote` is used, then -//! abstentions will first follow the majority of the collective voting, and then the prime -//! member. -//! -//! Voting happens through motions comprising a proposal (i.e. a curried dispatchable) plus a -//! number of approvals required for it to pass and be called. Motions are open for members to -//! vote on for a minimum period given by `MotionDuration`. As soon as the needed number of -//! approvals is given, the motion is closed and executed. If the number of approvals is not reached -//! during the voting period, then `close` may be called by any account in order to force the end -//! the motion explicitly. If a prime member is defined then their vote is used in place of any -//! abstentions and the proposal is executed if there are enough approvals counting the new votes. -//! -//! If there are not, or if no prime is set, then the motion is dropped without being executed. - -#![cfg_attr(not(feature = "std"), no_std)] -#![recursion_limit = "128"] - -use codec::DecodeWithMemTracking; -use frame_support::{ - dispatch::{DispatchResultWithPostInfo, GetDispatchInfo, Pays, PostDispatchInfo}, - ensure, - pallet_prelude::*, - traits::{ - Backing, ChangeMembers, EnsureOrigin, Get, GetBacking, InitializeMembers, StorageVersion, - }, - weights::Weight, -}; -use scale_info::TypeInfo; -use sp_io::storage; -use sp_runtime::traits::Dispatchable; -use sp_runtime::{RuntimeDebug, Saturating, traits::Hash}; -use sp_std::{marker::PhantomData, prelude::*, result}; - -#[cfg(test)] -mod tests; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; -pub mod weights; - -pub use pallet::*; -use subtensor_macros::freeze_struct; -pub use weights::WeightInfo; - -const LOG_TARGET: &str = "runtime::collective"; - -/// Simple index type for proposal counting. -pub type ProposalIndex = u32; - -/// A number of members. -/// -/// This also serves as a number of voting members, and since for motions, each member may -/// vote exactly once, therefore also the number of votes for any given motion. -pub type MemberCount = u32; - -/// Default voting strategy when a member is inactive. -pub trait DefaultVote { - /// Get the default voting strategy, given: - /// - /// - Whether the prime member voted Aye. - /// - Raw number of yes votes. - /// - Raw number of no votes. - /// - Total number of member count. - fn default_vote( - prime_vote: Option, - yes_votes: MemberCount, - no_votes: MemberCount, - len: MemberCount, - ) -> bool; -} - -/// Set the prime member's vote as the default vote. -pub struct PrimeDefaultVote; - -impl DefaultVote for PrimeDefaultVote { - fn default_vote( - prime_vote: Option, - _yes_votes: MemberCount, - _no_votes: MemberCount, - _len: MemberCount, - ) -> bool { - prime_vote.unwrap_or(false) - } -} - -/// First see if yes vote are over majority of the whole collective. If so, set the default vote -/// as yes. Otherwise, use the prime member's vote as the default vote. -pub struct MoreThanMajorityThenPrimeDefaultVote; - -impl DefaultVote for MoreThanMajorityThenPrimeDefaultVote { - fn default_vote( - prime_vote: Option, - yes_votes: MemberCount, - _no_votes: MemberCount, - len: MemberCount, - ) -> bool { - let more_than_majority = yes_votes.saturating_mul(2) > len; - more_than_majority || prime_vote.unwrap_or(false) - } -} - -/// Origin for the collective module. -#[derive( - PartialEq, - Eq, - Clone, - RuntimeDebug, - Encode, - Decode, - DecodeWithMemTracking, - TypeInfo, - MaxEncodedLen, -)] -#[scale_info(skip_type_params(I))] -#[codec(mel_bound(AccountId: MaxEncodedLen))] -pub enum RawOrigin { - /// It has been condoned by a given number of members of the collective from a given total. - Members(MemberCount, MemberCount), - /// It has been condoned by a single member of the collective. - Member(AccountId), - /// Dummy to manage the fact we have instancing. - _Phantom(PhantomData), -} - -impl GetBacking for RawOrigin { - fn get_backing(&self) -> Option { - match self { - RawOrigin::Members(n, d) => Some(Backing { - approvals: *n, - eligible: *d, - }), - _ => None, - } - } -} - -/// Info for keeping track of a motion being voted on. -#[freeze_struct("a8e7b0b34ad52b17")] -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct Votes { - /// The proposal's unique index. - index: ProposalIndex, - /// The number of approval votes that are needed to pass the motion. - threshold: MemberCount, - /// The current set of voters that approved it. - ayes: Vec, - /// The current set of voters that rejected it. - nays: Vec, - /// The hard end time of this vote. - end: BlockNumber, -} - -#[deny(missing_docs)] -#[frame_support::pallet] -#[allow(clippy::expect_used)] -pub mod pallet { - use super::*; - use frame_system::pallet_prelude::*; - - /// The current storage version. - const STORAGE_VERSION: StorageVersion = StorageVersion::new(4); - - #[pallet::pallet] - #[pallet::storage_version(STORAGE_VERSION)] - #[pallet::without_storage_info] - pub struct Pallet(PhantomData<(T, I)>); - - #[pallet::config] - pub trait Config: frame_system::Config { - /// The runtime origin type. - type RuntimeOrigin: From>; - - /// The runtime call dispatch type. - type Proposal: Parameter - + Dispatchable< - RuntimeOrigin = >::RuntimeOrigin, - PostInfo = PostDispatchInfo, - > + From> - + GetDispatchInfo; - - /// The time-out for council motions. - type MotionDuration: Get>; - - /// Maximum number of proposals allowed to be active in parallel. - type MaxProposals: Get; - - /// The maximum number of members supported by the pallet. Used for weight estimation. - /// - /// NOTE: - /// + Benchmarks will need to be re-run and weights adjusted if this changes. - /// + This pallet assumes that dependents keep to the limit without enforcing it. - type MaxMembers: Get; - - /// Default vote strategy of this collective. - type DefaultVote: DefaultVote; - - /// Weight information for extrinsics in this pallet. - type WeightInfo: WeightInfo; - - /// Origin allowed to set collective members - type SetMembersOrigin: EnsureOrigin<::RuntimeOrigin>; - - /// Origin allowed to propose - type CanPropose: CanPropose; - - /// Origin allowed to vote - type CanVote: CanVote; - - /// Members to expect in a vote - type GetVotingMembers: GetVotingMembers; - } - - #[pallet::genesis_config] - pub struct GenesisConfig, I: 'static = ()> { - /// The phantom just for type place holder. - pub phantom: PhantomData, - /// The initial members of the collective. - pub members: Vec, - } - - impl, I: 'static> Default for GenesisConfig { - fn default() -> Self { - Self { - phantom: Default::default(), - members: Default::default(), - } - } - } - - #[pallet::genesis_build] - impl, I: 'static> BuildGenesisConfig for GenesisConfig { - fn build(&self) { - use sp_std::collections::btree_set::BTreeSet; - let members_set: BTreeSet<_> = self.members.iter().collect(); - assert_eq!( - members_set.len(), - self.members.len(), - "Members cannot contain duplicate accounts." - ); - - Pallet::::initialize_members(&self.members) - } - } - - /// Origin for the collective pallet. - #[pallet::origin] - pub type Origin = RawOrigin<::AccountId, I>; - - /// The hashes of the active proposals. - #[pallet::storage] - #[pallet::getter(fn proposals)] - pub type Proposals, I: 'static = ()> = - StorageValue<_, BoundedVec, ValueQuery>; - - /// Actual proposal for a given hash, if it's current. - #[pallet::storage] - #[pallet::getter(fn proposal_of)] - pub type ProposalOf, I: 'static = ()> = - StorageMap<_, Identity, T::Hash, >::Proposal, OptionQuery>; - - /// Votes on a given proposal, if it is ongoing. - #[pallet::storage] - #[pallet::getter(fn voting)] - pub type Voting, I: 'static = ()> = - StorageMap<_, Identity, T::Hash, Votes>, OptionQuery>; - - /// Proposals so far. - #[pallet::storage] - #[pallet::getter(fn proposal_count)] - pub type ProposalCount, I: 'static = ()> = StorageValue<_, u32, ValueQuery>; - - /// The current members of the collective. This is stored sorted (just by value). - #[pallet::storage] - #[pallet::getter(fn members)] - pub type Members, I: 'static = ()> = - StorageValue<_, Vec, ValueQuery>; - - /// The prime member that helps determine the default vote behavior in case of absentations. - #[pallet::storage] - #[pallet::getter(fn prime)] - pub type Prime, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event, I: 'static = ()> { - /// A motion (given hash) has been proposed (by given account) with a threshold (given - /// `MemberCount`). - Proposed { - /// The account that proposed the motion. - account: T::AccountId, - /// The index of the proposal. - proposal_index: ProposalIndex, - /// The hash of the proposal. - proposal_hash: T::Hash, - /// The threshold of member for the proposal. - threshold: MemberCount, - }, - /// A motion (given hash) has been voted on by given account, leaving - /// a tally (yes votes and no votes given respectively as `MemberCount`). - Voted { - /// The account that voted. - account: T::AccountId, - /// The hash of the proposal. - proposal_hash: T::Hash, - /// Whether the account voted aye. - voted: bool, - /// The number of yes votes. - yes: MemberCount, - /// The number of no votes. - no: MemberCount, - }, - /// A motion was approved by the required threshold. - Approved { - /// The hash of the proposal. - proposal_hash: T::Hash, - }, - /// A motion was not approved by the required threshold. - Disapproved { - /// The hash of the proposal. - proposal_hash: T::Hash, - }, - /// A motion was executed; result will be `Ok` if it returned without error. - Executed { - /// The hash of the proposal. - proposal_hash: T::Hash, - /// The result of the execution. - result: DispatchResult, - }, - /// A single member did some action; result will be `Ok` if it returned without error. - MemberExecuted { - /// The hash of the proposal. - proposal_hash: T::Hash, - /// The result of the execution. - result: DispatchResult, - }, - /// A proposal was closed because its threshold was reached or after its duration was up. - Closed { - /// The hash of the proposal. - proposal_hash: T::Hash, - /// Whether the proposal was approved. - yes: MemberCount, - /// Whether the proposal was rejected. - no: MemberCount, - }, - } - - #[pallet::error] - pub enum Error { - /// Account is not a member of collective - NotMember, - /// Duplicate proposals not allowed - DuplicateProposal, - /// Proposal must exist - ProposalNotExists, - /// Index mismatched the proposal hash - IndexMismatchProposalHash, - /// Duplicate vote ignored - DuplicateVote, - /// The call to close the proposal was made too early, before the end of the voting - TooEarlyToCloseProposal, - /// There can only be a maximum of `MaxProposals` active proposals. - TooManyActiveProposals, - /// The given weight-bound for the proposal was too low. - ProposalWeightLessThanDispatchCallWeight, - /// The given length-bound for the proposal was too low. - ProposalLengthBoundLessThanProposalLength, - /// The given motion duration for the proposal was too low. - DurationLowerThanConfiguredMotionDuration, - } - - // Note that councillor operations are assigned to the operational class. - #[pallet::call] - impl, I: 'static> Pallet { - #![deny(clippy::expect_used)] - - /// Set the collective's membership. - /// - /// - `new_members`: The new member list. Be nice to the chain and provide it sorted. - /// - `prime`: The prime member whose vote sets the default. - /// - `old_count`: The upper bound for the previous number of members in storage. Used for - /// weight estimation. - /// - /// The dispatch of this call must be `SetMembersOrigin`. - /// - /// NOTE: Does not enforce the expected `MaxMembers` limit on the amount of members, but - /// the weight estimations rely on it to estimate dispatchable weight. - /// - /// # WARNING: - /// - /// The `pallet-collective` can also be managed by logic outside of the pallet through the - /// implementation of the trait [`ChangeMembers`]. - /// Any call to `set_members` must be careful that the member set doesn't get out of sync - /// with other logic managing the member set. - /// - /// ## Complexity: - /// - `O(MP + N)` where: - /// - `M` old-members-count (code- and governance-bounded) - /// - `N` new-members-count (code- and governance-bounded) - /// - `P` proposals-count (code-bounded) - #[pallet::call_index(0)] - #[pallet::weight(( - T::WeightInfo::set_members( - *old_count, // M - new_members.len() as u32, // N - T::MaxProposals::get() // P - ), - DispatchClass::Operational - ))] - pub fn set_members( - origin: OriginFor, - new_members: Vec, - prime: Option, - old_count: MemberCount, - ) -> DispatchResultWithPostInfo { - T::SetMembersOrigin::ensure_origin(origin)?; - if new_members.len() > T::MaxMembers::get() as usize { - log::error!( - target: LOG_TARGET, - "New members count ({}) exceeds maximum amount of members expected ({}).", - new_members.len(), - T::MaxMembers::get(), - ); - } - - let old = Members::::get(); - if old.len() > old_count as usize { - log::warn!( - target: LOG_TARGET, - "Wrong count used to estimate set_members weight. expected ({}) vs actual ({})", - old_count, - old.len(), - ); - } - let mut new_members = new_members; - new_members.sort(); - >::set_members_sorted(&new_members, &old); - Prime::::set(prime); - - Ok(Some(T::WeightInfo::set_members( - old.len() as u32, // M - new_members.len() as u32, // N - T::MaxProposals::get(), // P - )) - .into()) - } - - /// Dispatch a proposal from a member using the `Member` origin. - /// - /// Origin must be a member of the collective. - /// - /// ## Complexity: - /// - `O(B + M + P)` where: - /// - `B` is `proposal` size in bytes (length-fee-bounded) - /// - `M` members-count (code-bounded) - /// - `P` complexity of dispatching `proposal` - #[pallet::call_index(1)] - #[pallet::weight(( - T::WeightInfo::execute( - *length_bound, // B - T::MaxMembers::get(), // M - ).saturating_add(proposal.get_dispatch_info().call_weight), // P - DispatchClass::Operational - ))] - pub fn execute( - origin: OriginFor, - proposal: Box<>::Proposal>, - #[pallet::compact] length_bound: u32, - ) -> DispatchResultWithPostInfo { - let who = ensure_signed(origin)?; - let members = Self::members(); - ensure!(members.contains(&who), Error::::NotMember); - - let proposal_len = proposal.encoded_size(); - ensure!( - proposal_len <= length_bound as usize, - Error::::ProposalLengthBoundLessThanProposalLength - ); - - let proposal_hash = T::Hashing::hash_of(&proposal); - let result = proposal.dispatch(RawOrigin::Member(who).into()); - Self::deposit_event(Event::MemberExecuted { - proposal_hash, - result: result.map(|_| ()).map_err(|e| e.error), - }); - - Ok(get_result_weight(result) - .map(|w| { - T::WeightInfo::execute( - proposal_len as u32, // B - members.len() as u32, // M - ) - .saturating_add(w) // P - }) - .into()) - } - - /// Add a new proposal to either be voted on or executed directly. - /// - /// Requires the sender to be member. - /// - /// `threshold` determines whether `proposal` is executed directly (`threshold < 2`) - /// or put up for voting. - /// - /// ## Complexity - /// - `O(B + M + P1)` or `O(B + M + P2)` where: - /// - `B` is `proposal` size in bytes (length-fee-bounded) - /// - `M` is members-count (code- and governance-bounded) - /// - branching is influenced by `threshold` where: - /// - `P1` is proposal execution complexity (`threshold < 2`) - /// - `P2` is proposals-count (code-bounded) (`threshold >= 2`) - #[pallet::call_index(2)] - #[pallet::weight(( - T::WeightInfo::propose_proposed( - *length_bound, // B - T::MaxMembers::get(), // M - T::MaxProposals::get(), // P2 - ), - DispatchClass::Operational - ))] - pub fn propose( - origin: OriginFor, - proposal: Box<>::Proposal>, - #[pallet::compact] length_bound: u32, - duration: BlockNumberFor, - ) -> DispatchResultWithPostInfo { - let who = ensure_signed(origin.clone())?; - ensure!(T::CanPropose::can_propose(&who), Error::::NotMember); - - ensure!( - duration >= T::MotionDuration::get(), - Error::::DurationLowerThanConfiguredMotionDuration - ); - - let threshold = T::GetVotingMembers::get_count() - .checked_div(2) - .unwrap_or(0) - .saturating_add(1); - - let members = Self::members(); - let (proposal_len, active_proposals) = - Self::do_propose_proposed(who, threshold, proposal, length_bound, duration)?; - - Ok(Some(T::WeightInfo::propose_proposed( - proposal_len, // B - members.len() as u32, // M - active_proposals, // P2 - )) - .into()) - } - - /// Add an aye or nay vote for the sender to the given proposal. - /// - /// Requires the sender to be a member. - /// - /// Transaction fees will be waived if the member is voting on any particular proposal - /// for the first time and the call is successful. Subsequent vote changes will charge a - /// fee. - /// ## Complexity - /// - `O(M)` where `M` is members-count (code- and governance-bounded) - #[pallet::call_index(3)] - #[pallet::weight((T::WeightInfo::vote(T::MaxMembers::get()), DispatchClass::Operational))] - pub fn vote( - origin: OriginFor, - proposal: T::Hash, - #[pallet::compact] index: ProposalIndex, - approve: bool, - ) -> DispatchResultWithPostInfo { - let who = ensure_signed(origin.clone())?; - ensure!(T::CanVote::can_vote(&who), Error::::NotMember); - - let members = Self::members(); - // Detects first vote of the member in the motion - let is_account_voting_first_time = Self::do_vote(who, proposal, index, approve)?; - - if is_account_voting_first_time { - Ok((Some(T::WeightInfo::vote(members.len() as u32)), Pays::No).into()) - } else { - Ok((Some(T::WeightInfo::vote(members.len() as u32)), Pays::Yes).into()) - } - } - - // NOTE: call_index(4) was `close_old_weight` and was removed due to weights v1 - // deprecation - - /// Disapprove a proposal, close, and remove it from the system, regardless of its current - /// state. - /// - /// Must be called by the Root origin. - /// - /// Parameters: - /// * `proposal_hash`: The hash of the proposal that should be disapproved. - /// - /// ## Complexity - /// O(P) where P is the number of max proposals - #[pallet::call_index(5)] - #[pallet::weight(T::WeightInfo::disapprove_proposal(T::MaxProposals::get()))] - pub fn disapprove_proposal( - origin: OriginFor, - proposal_hash: T::Hash, - ) -> DispatchResultWithPostInfo { - ensure_root(origin)?; - let proposal_count = Self::do_disapprove_proposal(proposal_hash); - Ok(Some(T::WeightInfo::disapprove_proposal(proposal_count)).into()) - } - - /// Close a vote that is either approved, disapproved or whose voting period has ended. - /// - /// May be called by any signed account in order to finish voting and close the proposal. - /// - /// If called before the end of the voting period it will only close the vote if it is - /// has enough votes to be approved or disapproved. - /// - /// If called after the end of the voting period abstentions are counted as rejections - /// unless there is a prime member set and the prime member cast an approval. - /// - /// If the close operation completes successfully with disapproval, the transaction fee will - /// be waived. Otherwise execution of the approved operation will be charged to the caller. - /// - /// + `proposal_weight_bound`: The maximum amount of weight consumed by executing the closed - /// proposal. - /// + `length_bound`: The upper bound for the length of the proposal in storage. Checked via - /// `storage::read` so it is `size_of::() == 4` larger than the pure length. - /// - /// ## Complexity - /// - `O(B + M + P1 + P2)` where: - /// - `B` is `proposal` size in bytes (length-fee-bounded) - /// - `M` is members-count (code- and governance-bounded) - /// - `P1` is the complexity of `proposal` preimage. - /// - `P2` is proposal-count (code-bounded) - #[pallet::call_index(6)] - #[pallet::weight(( - { - let b = *length_bound; - let m = T::MaxMembers::get(); - let p1 = *proposal_weight_bound; - let p2 = T::MaxProposals::get(); - T::WeightInfo::close_early_approved(b, m, p2) - .max(T::WeightInfo::close_early_disapproved(m, p2)) - .max(T::WeightInfo::close_approved(b, m, p2)) - .max(T::WeightInfo::close_disapproved(m, p2)) - .saturating_add(p1) - }, - DispatchClass::Operational - ))] - pub fn close( - origin: OriginFor, - proposal_hash: T::Hash, - #[pallet::compact] index: ProposalIndex, - proposal_weight_bound: Weight, - #[pallet::compact] length_bound: u32, - ) -> DispatchResultWithPostInfo { - ensure_root(origin)?; - - Self::do_close(proposal_hash, index, proposal_weight_bound, length_bound) - } - } -} - -use frame_system::pallet_prelude::BlockNumberFor; - -/// Return the weight of a dispatch call result as an `Option`. -/// -/// Will return the weight regardless of what the state of the result is. -fn get_result_weight(result: DispatchResultWithPostInfo) -> Option { - match result { - Ok(post_info) => post_info.actual_weight, - Err(err) => err.post_info.actual_weight, - } -} - -impl, I: 'static> Pallet { - /// Check whether `who` is a member of the collective. - pub fn is_member(who: &T::AccountId) -> bool { - // Note: The dispatchables *do not* use this to check membership so make sure - // to update those if this is changed. - Self::members().contains(who) - } - - /// Add a new proposal to be voted. - pub fn do_propose_proposed( - who: T::AccountId, - threshold: MemberCount, - proposal: Box<>::Proposal>, - length_bound: MemberCount, - duration: BlockNumberFor, - ) -> Result<(u32, u32), DispatchError> { - let proposal_len = proposal.encoded_size(); - ensure!( - proposal_len <= length_bound as usize, - Error::::ProposalLengthBoundLessThanProposalLength - ); - - let proposal_hash = T::Hashing::hash_of(&proposal); - ensure!( - !>::contains_key(proposal_hash), - Error::::DuplicateProposal - ); - - let active_proposals = - >::try_mutate(|proposals| -> Result { - proposals - .try_push(proposal_hash) - .map_err(|_| Error::::TooManyActiveProposals)?; - Ok(proposals.len()) - })?; - - let index = Self::proposal_count(); - >::try_mutate(|i| { - *i = i - .checked_add(1) - .ok_or(Error::::TooManyActiveProposals)?; - Ok::<(), Error>(()) - })?; - >::insert(proposal_hash, proposal); - let votes = { - let end = frame_system::Pallet::::block_number().saturating_add(duration); - Votes { - index, - threshold, - ayes: vec![], - nays: vec![], - end, - } - }; - >::insert(proposal_hash, votes); - - Self::deposit_event(Event::Proposed { - account: who, - proposal_index: index, - proposal_hash, - threshold, - }); - Ok((proposal_len as u32, active_proposals as u32)) - } - - /// Add an aye or nay vote for the member to the given proposal, returns true if it's the first - /// vote of the member in the motion - pub fn do_vote( - who: T::AccountId, - proposal: T::Hash, - index: ProposalIndex, - approve: bool, - ) -> Result { - let mut voting = Self::voting(proposal).ok_or(Error::::ProposalNotExists)?; - ensure!( - voting.index == index, - Error::::IndexMismatchProposalHash - ); - - let position_yes = voting.ayes.iter().position(|a| a == &who); - let position_no = voting.nays.iter().position(|a| a == &who); - - // Detects first vote of the member in the motion - let is_account_voting_first_time = position_yes.is_none() && position_no.is_none(); - - if approve { - if position_yes.is_none() { - voting.ayes.push(who.clone()); - } else { - return Err(Error::::DuplicateVote.into()); - } - if let Some(pos) = position_no { - voting.nays.swap_remove(pos); - } - } else { - if position_no.is_none() { - voting.nays.push(who.clone()); - } else { - return Err(Error::::DuplicateVote.into()); - } - if let Some(pos) = position_yes { - voting.ayes.swap_remove(pos); - } - } - - let yes_votes = voting.ayes.len() as MemberCount; - let no_votes = voting.nays.len() as MemberCount; - Self::deposit_event(Event::Voted { - account: who, - proposal_hash: proposal, - voted: approve, - yes: yes_votes, - no: no_votes, - }); - - Voting::::insert(proposal, voting); - - Ok(is_account_voting_first_time) - } - - /// Close a vote that is either approved, disapproved or whose voting period has ended. - pub fn do_close( - proposal_hash: T::Hash, - index: ProposalIndex, - proposal_weight_bound: Weight, - length_bound: u32, - ) -> DispatchResultWithPostInfo { - let voting = Self::voting(proposal_hash).ok_or(Error::::ProposalNotExists)?; - ensure!( - voting.index == index, - Error::::IndexMismatchProposalHash - ); - - let mut no_votes = voting.nays.len() as MemberCount; - let mut yes_votes = voting.ayes.len() as MemberCount; - let seats = T::GetVotingMembers::get_count() as MemberCount; - let approved = yes_votes >= voting.threshold; - let disapproved = seats.saturating_sub(no_votes) < voting.threshold; - // Allow (dis-)approving the proposal as soon as there are enough votes. - if approved { - let (proposal, len) = Self::validate_and_get_proposal( - &proposal_hash, - length_bound, - proposal_weight_bound, - )?; - Self::deposit_event(Event::Closed { - proposal_hash, - yes: yes_votes, - no: no_votes, - }); - let (proposal_weight, proposal_count) = - Self::do_approve_proposal(seats, yes_votes, proposal_hash, proposal); - return Ok(( - Some( - T::WeightInfo::close_early_approved(len as u32, seats, proposal_count) - .saturating_add(proposal_weight), - ), - Pays::Yes, - ) - .into()); - } else if disapproved { - Self::deposit_event(Event::Closed { - proposal_hash, - yes: yes_votes, - no: no_votes, - }); - let proposal_count = Self::do_disapprove_proposal(proposal_hash); - return Ok(( - Some(T::WeightInfo::close_early_disapproved( - seats, - proposal_count, - )), - Pays::No, - ) - .into()); - } - - // Only allow actual closing of the proposal after the voting period has ended. - ensure!( - frame_system::Pallet::::block_number() >= voting.end, - Error::::TooEarlyToCloseProposal - ); - - let prime_vote = Self::prime().map(|who| voting.ayes.iter().any(|a| a == &who)); - - // default voting strategy. - let default = T::DefaultVote::default_vote(prime_vote, yes_votes, no_votes, seats); - - let abstentions = seats.saturating_sub(yes_votes.saturating_add(no_votes)); - match default { - true => yes_votes = yes_votes.saturating_add(abstentions), - false => no_votes = no_votes.saturating_add(abstentions), - } - let approved = yes_votes >= voting.threshold; - - if approved { - let (proposal, len) = Self::validate_and_get_proposal( - &proposal_hash, - length_bound, - proposal_weight_bound, - )?; - Self::deposit_event(Event::Closed { - proposal_hash, - yes: yes_votes, - no: no_votes, - }); - let (proposal_weight, proposal_count) = - Self::do_approve_proposal(seats, yes_votes, proposal_hash, proposal); - Ok(( - Some( - T::WeightInfo::close_approved(len as u32, seats, proposal_count) - .saturating_add(proposal_weight), - ), - Pays::Yes, - ) - .into()) - } else { - Self::deposit_event(Event::Closed { - proposal_hash, - yes: yes_votes, - no: no_votes, - }); - let proposal_count = Self::do_disapprove_proposal(proposal_hash); - Ok(( - Some(T::WeightInfo::close_disapproved(seats, proposal_count)), - Pays::No, - ) - .into()) - } - } - - /// Ensure that the right proposal bounds were passed and get the proposal from storage. - /// - /// Checks the length in storage via `storage::read` which adds an extra `size_of::() == 4` - /// to the length. - fn validate_and_get_proposal( - hash: &T::Hash, - length_bound: u32, - weight_bound: Weight, - ) -> Result<(>::Proposal, usize), DispatchError> { - let key = ProposalOf::::hashed_key_for(hash); - // read the length of the proposal storage entry directly - let proposal_len = - storage::read(&key, &mut [0; 0], 0).ok_or(Error::::ProposalNotExists)?; - ensure!( - proposal_len <= length_bound, - Error::::ProposalLengthBoundLessThanProposalLength - ); - let proposal = ProposalOf::::get(hash).ok_or(Error::::ProposalNotExists)?; - let proposal_weight = proposal.get_dispatch_info().call_weight; - ensure!( - proposal_weight.all_lte(weight_bound), - Error::::ProposalWeightLessThanDispatchCallWeight - ); - Ok((proposal, proposal_len as usize)) - } - - /// Weight: - /// If `approved`: - /// - the weight of `proposal` preimage. - /// - two events deposited. - /// - two removals, one mutation. - /// - computation and i/o `O(P + L)` where: - /// - `P` is number of active proposals, - /// - `L` is the encoded length of `proposal` preimage. - /// - /// If not `approved`: - /// - one event deposited. - /// - two removals, one mutation. - /// - computation and i/o `O(P)` where: - /// - `P` is number of active proposals - fn do_approve_proposal( - seats: MemberCount, - yes_votes: MemberCount, - proposal_hash: T::Hash, - proposal: >::Proposal, - ) -> (Weight, u32) { - Self::deposit_event(Event::Approved { proposal_hash }); - - let dispatch_weight = proposal.get_dispatch_info().call_weight; - let origin = RawOrigin::Members(yes_votes, seats).into(); - let result = proposal.dispatch(origin); - Self::deposit_event(Event::Executed { - proposal_hash, - result: result.map(|_| ()).map_err(|e| e.error), - }); - // default to the dispatch info weight for safety - let proposal_weight = get_result_weight(result).unwrap_or(dispatch_weight); // P1 - - let proposal_count = Self::remove_proposal(proposal_hash); - (proposal_weight, proposal_count) - } - - /// Removes a proposal from the pallet, and deposit the `Disapproved` event. - pub fn do_disapprove_proposal(proposal_hash: T::Hash) -> u32 { - // disapproved - Self::deposit_event(Event::Disapproved { proposal_hash }); - Self::remove_proposal(proposal_hash) - } - - // Removes a proposal from the pallet, cleaning up votes and the vector of proposals. - fn remove_proposal(proposal_hash: T::Hash) -> u32 { - // remove proposal and vote - ProposalOf::::remove(proposal_hash); - Voting::::remove(proposal_hash); - let num_proposals = Proposals::::mutate(|proposals| { - proposals.retain(|h| h != &proposal_hash); - proposals.len().saturating_add(1) // calculate weight based on original length - }); - num_proposals as u32 - } - - pub fn remove_votes(who: &T::AccountId) -> Result { - for h in Self::proposals().into_iter() { - >::mutate(h, |v| { - if let Some(mut votes) = v.take() { - votes.ayes.retain(|i| i != who); - votes.nays.retain(|i| i != who); - *v = Some(votes); - } - }); - } - - Ok(true) - } - - pub fn has_voted( - proposal: T::Hash, - index: ProposalIndex, - who: &T::AccountId, - ) -> Result { - let voting = Self::voting(proposal).ok_or(Error::::ProposalNotExists)?; - ensure!( - voting.index == index, - Error::::IndexMismatchProposalHash - ); - - let position_yes = voting.ayes.iter().position(|a| a == who); - let position_no = voting.nays.iter().position(|a| a == who); - - Ok(position_yes.is_some() || position_no.is_some()) - } -} - -impl, I: 'static> ChangeMembers for Pallet { - /// Update the members of the collective. Votes are updated and the prime is reset. - /// - /// NOTE: Does not enforce the expected `MaxMembers` limit on the amount of members, but - /// the weight estimations rely on it to estimate dispatchable weight. - /// - /// ## Complexity - /// - `O(MP + N)` - /// - where `M` old-members-count (governance-bounded) - /// - where `N` new-members-count (governance-bounded) - /// - where `P` proposals-count - fn change_members_sorted( - _incoming: &[T::AccountId], - outgoing: &[T::AccountId], - new: &[T::AccountId], - ) { - if new.len() > T::MaxMembers::get() as usize { - log::error!( - target: LOG_TARGET, - "New members count ({}) exceeds maximum amount of members expected ({}).", - new.len(), - T::MaxMembers::get(), - ); - } - // remove accounts from all current voting in motions. - let mut outgoing = outgoing.to_vec(); - outgoing.sort(); - for h in Self::proposals().into_iter() { - >::mutate(h, |v| { - if let Some(mut votes) = v.take() { - votes.ayes.retain(|i| outgoing.binary_search(i).is_err()); - votes.nays.retain(|i| outgoing.binary_search(i).is_err()); - *v = Some(votes); - } - }); - } - Members::::put(new); - Prime::::kill(); - } - - fn set_prime(prime: Option) { - Prime::::set(prime); - } - - fn get_prime() -> Option { - Prime::::get() - } -} - -impl, I: 'static> InitializeMembers for Pallet { - fn initialize_members(members: &[T::AccountId]) { - if !members.is_empty() { - assert!( - >::get().is_empty(), - "Members are already initialized!" - ); - >::put(members); - } - } -} - -/// Ensure that the origin `o` represents at least `n` members. Returns `Ok` or an `Err` -/// otherwise. -pub fn ensure_members( - o: OuterOrigin, - n: MemberCount, -) -> result::Result -where - OuterOrigin: Into, OuterOrigin>>, -{ - match o.into() { - Ok(RawOrigin::Members(x, _)) if x >= n => Ok(n), - _ => Err("bad origin: expected to be a threshold number of members"), - } -} - -pub struct EnsureMember(PhantomData<(AccountId, I)>); -impl< - O: Into, O>> + From>, - I, - AccountId: Decode, -> EnsureOrigin for EnsureMember -{ - type Success = AccountId; - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Member(id) => Ok(id), - r => Err(O::from(r)), - }) - } - - #[cfg(feature = "runtime-benchmarks")] - #[allow(clippy::expect_used)] - fn try_successful_origin() -> Result { - let zero_account_id = - AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"); - Ok(O::from(RawOrigin::Member(zero_account_id))) - } -} - -pub struct EnsureMembers(PhantomData<(AccountId, I)>); -impl< - O: Into, O>> + From>, - AccountId, - I, - const N: u32, -> EnsureOrigin for EnsureMembers -{ - type Success = (MemberCount, MemberCount); - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Members(n, m) if n >= N => Ok((n, m)), - r => Err(O::from(r)), - }) - } - - #[cfg(feature = "runtime-benchmarks")] - fn try_successful_origin() -> Result { - Ok(O::from(RawOrigin::Members(N, N))) - } -} - -pub struct EnsureProportionMoreThan( - PhantomData<(AccountId, I)>, -); -impl< - O: Into, O>> + From>, - AccountId, - I, - const N: u32, - const D: u32, -> EnsureOrigin for EnsureProportionMoreThan -{ - type Success = (); - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Members(n, m) if n.saturating_mul(D) > N.saturating_mul(m) => Ok(()), - r => Err(O::from(r)), - }) - } - - #[cfg(feature = "runtime-benchmarks")] - fn try_successful_origin() -> Result { - Ok(O::from(RawOrigin::Members(1u32, 0u32))) - } -} - -pub struct EnsureProportionAtLeast( - PhantomData<(AccountId, I)>, -); -impl< - O: Into, O>> + From>, - AccountId, - I, - const N: u32, - const D: u32, -> EnsureOrigin for EnsureProportionAtLeast -{ - type Success = (); - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Members(n, m) if n.saturating_mul(D) >= N.saturating_mul(m) => Ok(()), - r => Err(O::from(r)), - }) - } - - #[cfg(feature = "runtime-benchmarks")] - fn try_successful_origin() -> Result { - Ok(O::from(RawOrigin::Members(0u32, 0u32))) - } -} - -/// CanPropose -pub trait CanPropose { - /// Check whether or not the passed AccountId can propose a new motion - fn can_propose(account: &AccountId) -> bool; -} - -impl CanPropose for () { - fn can_propose(_: &T) -> bool { - false - } -} - -/// CanVote -pub trait CanVote { - /// Check whether or not the passed AccountId can vote on a motion - fn can_vote(account: &AccountId) -> bool; -} - -impl CanVote for () { - fn can_vote(_: &T) -> bool { - false - } -} - -pub trait GetVotingMembers { - fn get_count() -> MemberCount; -} - -impl GetVotingMembers for () { - fn get_count() -> MemberCount { - 0 - } -} diff --git a/pallets/collective/src/tests.rs b/pallets/collective/src/tests.rs deleted file mode 100644 index 5c39c3d2f4..0000000000 --- a/pallets/collective/src/tests.rs +++ /dev/null @@ -1,1587 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 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( - non_camel_case_types, - clippy::expect_used, - clippy::indexing_slicing, - clippy::unwrap_used -)] - -use super::{Event as CollectiveEvent, *}; -use crate as pallet_collective; -use frame_support::{ - Hashable, assert_noop, assert_ok, derive_impl, parameter_types, traits::ConstU64, -}; -use frame_system::{EnsureRoot, EventRecord, Phase}; -use sp_core::H256; -use sp_runtime::{ - BuildStorage, - testing::{Header, TestXt}, - traits::{BlakeTwo256, IdentityLookup}, -}; - -pub type Block = sp_runtime::generic::Block; -pub type UncheckedExtrinsic = TestXt; - -frame_support::construct_runtime!( - pub enum Test - { - System: frame_system::{Pallet, Call, Event} = 1, - Collective: pallet_collective::::{Pallet, Call, Event, Origin, Config} = 2, - CollectiveMajority: pallet_collective::::{Pallet, Call, Event, Origin, Config} = 3, - DefaultCollective: pallet_collective::{Pallet, Call, Event, Origin, Config} = 4, - Democracy: mock_democracy::{Pallet, Call, Event} = 5, - } -); -mod mock_democracy { - pub use pallet::*; - #[frame_support::pallet(dev_mode)] - 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 + Sized { - type ExternalMajorityOrigin: EnsureOrigin; - } - - #[pallet::call] - impl Pallet { - #[pallet::call_index(0)] - pub fn external_propose_majority(origin: OriginFor) -> DispatchResult { - T::ExternalMajorityOrigin::ensure_origin(origin)?; - Self::deposit_event(Event::::ExternalProposed); - Ok(()) - } - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - ExternalProposed, - } - } -} - -pub type MaxMembers = ConstU32<100>; - -parameter_types! { - pub const MotionDuration: u64 = 3; - pub const MaxProposals: u32 = 257; -} - -#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; - type Block = Block; - type Nonce = u64; -} - -pub struct CanProposeCollective; -impl CanPropose<::AccountId> for CanProposeCollective { - fn can_propose(who: &::AccountId) -> bool { - Collective::is_member(who) - } -} - -pub struct CanVoteCollective; -impl CanVote<::AccountId> for CanVoteCollective { - fn can_vote(who: &::AccountId) -> bool { - Collective::is_member(who) - } -} - -pub struct GetCollectiveCount; -impl GetVotingMembers for GetCollectiveCount { - fn get_count() -> MemberCount { - Collective::members().len() as u32 - } -} -impl Get for GetCollectiveCount { - fn get() -> MemberCount { - ::get() - } -} - -impl Config for Test { - type RuntimeOrigin = RuntimeOrigin; - type Proposal = RuntimeCall; - type MotionDuration = ConstU64<3>; - type MaxProposals = MaxProposals; - type MaxMembers = MaxMembers; - type DefaultVote = PrimeDefaultVote; - type WeightInfo = (); - type SetMembersOrigin = EnsureRoot; - type CanPropose = CanProposeCollective; - type CanVote = CanVoteCollective; - type GetVotingMembers = GetCollectiveCount; -} - -pub struct CanProposeCollectiveMajority; -impl CanPropose<::AccountId> for CanProposeCollectiveMajority { - fn can_propose(who: &::AccountId) -> bool { - CollectiveMajority::is_member(who) - } -} - -pub struct CanVoteCollectiveMajority; -impl CanVote<::AccountId> for CanVoteCollectiveMajority { - fn can_vote(who: &::AccountId) -> bool { - CollectiveMajority::is_member(who) - } -} - -pub struct GetCollectiveMajorityCount; -impl GetVotingMembers for GetCollectiveMajorityCount { - fn get_count() -> MemberCount { - CollectiveMajority::members().len() as u32 - } -} -impl Get for GetCollectiveMajorityCount { - fn get() -> MemberCount { - ::get() - } -} - -impl Config for Test { - type RuntimeOrigin = RuntimeOrigin; - type Proposal = RuntimeCall; - type MotionDuration = ConstU64<3>; - type MaxProposals = MaxProposals; - type MaxMembers = MaxMembers; - type DefaultVote = MoreThanMajorityThenPrimeDefaultVote; - type WeightInfo = (); - type SetMembersOrigin = EnsureRoot; - type CanPropose = CanProposeCollectiveMajority; - type CanVote = CanVoteCollectiveMajority; - type GetVotingMembers = GetCollectiveMajorityCount; -} -impl mock_democracy::Config for Test { - type ExternalMajorityOrigin = EnsureProportionAtLeast; -} - -pub struct CanProposeDefaultCollective; -impl CanPropose<::AccountId> for CanProposeDefaultCollective { - fn can_propose(who: &::AccountId) -> bool { - DefaultCollective::is_member(who) - } -} - -pub struct CanVoteDefaultCollective; -impl CanVote<::AccountId> for CanVoteDefaultCollective { - fn can_vote(who: &::AccountId) -> bool { - DefaultCollective::is_member(who) - } -} - -pub struct GetDefaultCollectiveCount; -impl GetVotingMembers for GetDefaultCollectiveCount { - fn get_count() -> MemberCount { - DefaultCollective::members().len() as u32 - } -} -impl Get for GetDefaultCollectiveCount { - fn get() -> MemberCount { - ::get() - } -} - -impl Config for Test { - type RuntimeOrigin = RuntimeOrigin; - type Proposal = RuntimeCall; - type MotionDuration = ConstU64<3>; - type MaxProposals = MaxProposals; - type MaxMembers = MaxMembers; - type DefaultVote = PrimeDefaultVote; - type WeightInfo = (); - type SetMembersOrigin = EnsureRoot; - type CanPropose = CanProposeDefaultCollective; - type CanVote = CanVoteDefaultCollective; - type GetVotingMembers = GetDefaultCollectiveCount; -} - -pub fn new_test_ext() -> sp_io::TestExternalities { - let mut ext: sp_io::TestExternalities = RuntimeGenesisConfig { - collective: pallet_collective::GenesisConfig { - members: vec![1, 2, 3], - phantom: Default::default(), - }, - collective_majority: pallet_collective::GenesisConfig { - members: vec![1, 2, 3, 4, 5], - phantom: Default::default(), - }, - default_collective: Default::default(), - } - .build_storage() - .unwrap() - .into(); - ext.execute_with(|| System::set_block_number(1)); - ext -} - -fn make_proposal(value: u64) -> RuntimeCall { - RuntimeCall::System(frame_system::Call::remark_with_event { - remark: value.to_be_bytes().to_vec(), - }) -} - -fn record(event: RuntimeEvent) -> EventRecord { - EventRecord { - phase: Phase::Initialization, - event, - topics: vec![], - } -} - -#[test] -fn motions_basic_environment_works() { - new_test_ext().execute_with(|| { - assert_eq!(Collective::members(), vec![1, 2, 3]); - assert_eq!(*Collective::proposals(), Vec::::new()); - }); -} - -#[test] -fn close_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash = BlakeTwo256::hash_of(&proposal); - - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); - - System::set_block_number(3); - assert_noop!( - Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - ), - Error::::TooEarlyToCloseProposal - ); - - System::set_block_number(4); - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - - assert_eq!( - System::events(), - vec![ - record(RuntimeEvent::Collective(CollectiveEvent::Proposed { - account: 1, - proposal_index: 0, - proposal_hash: hash, - threshold: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 1, - proposal_hash: hash, - voted: true, - yes: 1, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Closed { - proposal_hash: hash, - yes: 1, - no: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Disapproved { - proposal_hash: hash - })) - ] - ); - }); -} - -#[test] -fn proposal_weight_limit_works_on_approve() { - new_test_ext().execute_with(|| { - let proposal = RuntimeCall::Collective(crate::Call::set_members { - new_members: vec![1, 2, 3], - prime: None, - old_count: ::get(), - }); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash = BlakeTwo256::hash_of(&proposal); - // Set 1 as prime voter - Prime::::set(Some(1)); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); - // With 1's prime vote, this should pass - System::set_block_number(4); - assert_noop!( - Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight - Weight::from_parts(100, 0), - proposal_len - ), - Error::::ProposalWeightLessThanDispatchCallWeight - ); - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - }) -} - -#[test] -fn proposal_weight_limit_ignored_on_disapprove() { - new_test_ext().execute_with(|| { - let proposal = RuntimeCall::Collective(crate::Call::set_members { - new_members: vec![1, 2, 3], - prime: None, - old_count: ::get(), - }); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash = BlakeTwo256::hash_of(&proposal); - - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - // No votes, this proposal wont pass - System::set_block_number(4); - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight - Weight::from_parts(100, 0), - proposal_len - )); - }) -} - -#[test] -fn close_with_prime_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::set_members( - RuntimeOrigin::root(), - vec![1, 2, 3], - Some(3), - ::get() - )); - - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); - - System::set_block_number(4); - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - - assert_eq!( - System::events(), - vec![ - record(RuntimeEvent::Collective(CollectiveEvent::Proposed { - account: 1, - proposal_index: 0, - proposal_hash: hash, - threshold: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 1, - proposal_hash: hash, - voted: true, - yes: 1, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Closed { - proposal_hash: hash, - yes: 1, - no: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Disapproved { - proposal_hash: hash - })) - ] - ); - }); -} - -#[test] -fn close_with_voting_prime_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::set_members( - RuntimeOrigin::root(), - vec![1, 2, 3], - Some(1), - ::get() - )); - - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); - - System::set_block_number(4); - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - - assert_eq!( - System::events(), - vec![ - record(RuntimeEvent::Collective(CollectiveEvent::Proposed { - account: 1, - proposal_index: 0, - proposal_hash: hash, - threshold: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 1, - proposal_hash: hash, - voted: true, - yes: 1, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Closed { - proposal_hash: hash, - yes: 3, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Approved { - proposal_hash: hash - })), - record(RuntimeEvent::Collective(CollectiveEvent::Executed { - proposal_hash: hash, - result: Err(DispatchError::BadOrigin) - })) - ] - ); - }); -} - -#[test] -fn close_with_no_prime_but_majority_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(CollectiveMajority::set_members( - RuntimeOrigin::root(), - vec![1, 2, 3, 4, 5], - Some(5), - ::get() - )); - - assert_ok!(CollectiveMajority::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(CollectiveMajority::vote( - RuntimeOrigin::signed(1), - hash, - 0, - true - )); - assert_ok!(CollectiveMajority::vote( - RuntimeOrigin::signed(2), - hash, - 0, - true - )); - assert_ok!(CollectiveMajority::vote( - RuntimeOrigin::signed(3), - hash, - 0, - true - )); - - System::set_block_number(4); - assert_ok!(CollectiveMajority::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - - assert_eq!( - System::events(), - vec![ - record(RuntimeEvent::CollectiveMajority( - CollectiveEvent::Proposed { - account: 1, - proposal_index: 0, - proposal_hash: hash, - threshold: 3 - } - )), - record(RuntimeEvent::CollectiveMajority(CollectiveEvent::Voted { - account: 1, - proposal_hash: hash, - voted: true, - yes: 1, - no: 0 - })), - record(RuntimeEvent::CollectiveMajority(CollectiveEvent::Voted { - account: 2, - proposal_hash: hash, - voted: true, - yes: 2, - no: 0 - })), - record(RuntimeEvent::CollectiveMajority(CollectiveEvent::Voted { - account: 3, - proposal_hash: hash, - voted: true, - yes: 3, - no: 0 - })), - record(RuntimeEvent::CollectiveMajority(CollectiveEvent::Closed { - proposal_hash: hash, - yes: 3, - no: 0 - })), - record(RuntimeEvent::CollectiveMajority( - CollectiveEvent::Approved { - proposal_hash: hash - } - )), - record(RuntimeEvent::CollectiveMajority( - CollectiveEvent::Executed { - proposal_hash: hash, - result: Err(DispatchError::BadOrigin) - } - )) - ] - ); - }); -} - -#[test] -fn removal_of_old_voters_votes_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash = BlakeTwo256::hash_of(&proposal); - let end = 4; - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 0, true)); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 0, - threshold: 2, - ayes: vec![1, 2], - nays: vec![], - end - }) - ); - Collective::change_members_sorted(&[4], &[1], &[2, 3, 4]); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 0, - threshold: 2, - ayes: vec![2], - nays: vec![], - end - }) - ); - - let proposal = make_proposal(69); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(2), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 1, true)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(3), hash, 1, false)); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 1, - threshold: 2, - ayes: vec![2], - nays: vec![3], - end - }) - ); - Collective::change_members_sorted(&[], &[3], &[2, 4]); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 1, - threshold: 2, - ayes: vec![2], - nays: vec![], - end - }) - ); - }); -} - -#[test] -fn removal_of_old_voters_votes_works_with_set_members() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash = BlakeTwo256::hash_of(&proposal); - let end = 4; - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 0, true)); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 0, - threshold: 2, - ayes: vec![1, 2], - nays: vec![], - end - }) - ); - assert_ok!(Collective::set_members( - RuntimeOrigin::root(), - vec![2, 3, 4], - None, - ::get() - )); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 0, - threshold: 2, - ayes: vec![2], - nays: vec![], - end - }) - ); - - let proposal = make_proposal(69); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(2), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 1, true)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(3), hash, 1, false)); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 1, - threshold: 2, - ayes: vec![2], - nays: vec![3], - end - }) - ); - assert_ok!(Collective::set_members( - RuntimeOrigin::root(), - vec![2, 4], - None, - ::get() - )); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 1, - threshold: 2, - ayes: vec![2], - nays: vec![], - end - }) - ); - }); -} - -#[test] -fn propose_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash = proposal.blake2_256().into(); - let end = 4; - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_eq!(*Collective::proposals(), vec![hash]); - assert_eq!(Collective::proposal_of(hash), Some(proposal)); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 0, - threshold: 2, - ayes: vec![], - nays: vec![], - end - }) - ); - - assert_eq!( - System::events(), - vec![record(RuntimeEvent::Collective( - CollectiveEvent::Proposed { - account: 1, - proposal_index: 0, - proposal_hash: hash, - threshold: 2 - } - ))] - ); - }); -} - -#[test] -fn limit_active_proposals() { - new_test_ext().execute_with(|| { - for i in 0..::get() { - let proposal = make_proposal(i as u64); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64) - .expect("convert u64 to block number.") - )); - } - let proposal = make_proposal(::get() as u64 + 1); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - assert_noop!( - Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64) - .expect("convert u64 to block number.") - ), - Error::::TooManyActiveProposals - ); - }) -} - -#[test] -fn correct_validate_and_get_proposal() { - new_test_ext().execute_with(|| { - let proposal = RuntimeCall::Collective(crate::Call::set_members { - new_members: vec![1, 2, 3], - prime: None, - old_count: ::get(), - }); - let length = proposal.encode().len() as u32; - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - length, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - - let hash = BlakeTwo256::hash_of(&proposal); - let weight = proposal.get_dispatch_info().call_weight; - assert_noop!( - Collective::validate_and_get_proposal( - &BlakeTwo256::hash_of(&vec![3; 4]), - length, - weight - ), - Error::::ProposalNotExists - ); - assert_noop!( - Collective::validate_and_get_proposal(&hash, length - 2, weight), - Error::::ProposalLengthBoundLessThanProposalLength - ); - assert_noop!( - Collective::validate_and_get_proposal( - &hash, - length, - weight - Weight::from_parts(10, 0) - ), - Error::::ProposalWeightLessThanDispatchCallWeight - ); - let res = Collective::validate_and_get_proposal(&hash, length, weight); - assert_ok!(res.clone()); - let (retrieved_proposal, len) = res.unwrap(); - assert_eq!(length as usize, len); - assert_eq!(proposal, retrieved_proposal); - }) -} - -#[test] -fn motions_ignoring_non_collective_proposals_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - assert_noop!( - Collective::propose( - RuntimeOrigin::signed(42), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64) - .expect("convert u64 to block number.") - ), - Error::::NotMember - ); - }); -} - -#[test] -fn motions_ignoring_non_collective_votes_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_noop!( - Collective::vote(RuntimeOrigin::signed(42), hash, 0, true), - Error::::NotMember, - ); - }); -} - -#[test] -fn motions_ignoring_bad_index_collective_vote_works() { - new_test_ext().execute_with(|| { - System::set_block_number(3); - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_noop!( - Collective::vote(RuntimeOrigin::signed(2), hash, 1, true), - Error::::IndexMismatchProposalHash, - ); - }); -} - -#[test] -fn motions_vote_after_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash: H256 = proposal.blake2_256().into(); - let end = 4; - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - // Initially there a no votes when the motion is proposed. - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 0, - threshold: 2, - ayes: vec![], - nays: vec![], - end - }) - ); - // Cast first aye vote. - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 0, - threshold: 2, - ayes: vec![1], - nays: vec![], - end - }) - ); - // Try to cast a duplicate aye vote. - assert_noop!( - Collective::vote(RuntimeOrigin::signed(1), hash, 0, true), - Error::::DuplicateVote, - ); - // Cast a nay vote. - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, false)); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 0, - threshold: 2, - ayes: vec![], - nays: vec![1], - end - }) - ); - // Try to cast a duplicate nay vote. - assert_noop!( - Collective::vote(RuntimeOrigin::signed(1), hash, 0, false), - Error::::DuplicateVote, - ); - - assert_eq!( - System::events(), - vec![ - record(RuntimeEvent::Collective(CollectiveEvent::Proposed { - account: 1, - proposal_index: 0, - proposal_hash: hash, - threshold: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 1, - proposal_hash: hash, - voted: true, - yes: 1, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 1, - proposal_hash: hash, - voted: false, - yes: 0, - no: 1 - })), - ] - ); - }); -} - -#[test] -fn motions_all_first_vote_free_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash: H256 = proposal.blake2_256().into(); - let end = 4; - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_eq!( - Collective::voting(hash), - Some(Votes { - index: 0, - threshold: 2, - ayes: vec![], - nays: vec![], - end - }) - ); - - // For the motion, acc 2's first vote, expecting Ok with Pays::No. - let vote_rval: DispatchResultWithPostInfo = - Collective::vote(RuntimeOrigin::signed(2), hash, 0, true); - assert_eq!(vote_rval.unwrap().pays_fee, Pays::No); - - // Duplicate vote, expecting error with Pays::Yes. - let vote_rval: DispatchResultWithPostInfo = - Collective::vote(RuntimeOrigin::signed(2), hash, 0, true); - assert_eq!(vote_rval.unwrap_err().post_info.pays_fee, Pays::Yes); - - // Modifying vote, expecting ok with Pays::Yes. - let vote_rval: DispatchResultWithPostInfo = - Collective::vote(RuntimeOrigin::signed(2), hash, 0, false); - assert_eq!(vote_rval.unwrap().pays_fee, Pays::Yes); - - // For the motion, acc 3's first vote, expecting Ok with Pays::No. - let vote_rval: DispatchResultWithPostInfo = - Collective::vote(RuntimeOrigin::signed(3), hash, 0, true); - assert_eq!(vote_rval.unwrap().pays_fee, Pays::No); - - // acc 3 modify the vote, expecting Ok with Pays::Yes. - let vote_rval: DispatchResultWithPostInfo = - Collective::vote(RuntimeOrigin::signed(3), hash, 0, false); - assert_eq!(vote_rval.unwrap().pays_fee, Pays::Yes); - - // Test close() Extrincis | Check DispatchResultWithPostInfo with Pay Info - - let proposal_weight = proposal.get_dispatch_info().call_weight; - let close_rval: DispatchResultWithPostInfo = Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len, - ); - assert_eq!(close_rval.unwrap().pays_fee, Pays::No); - - // Trying to close the proposal, which is already closed - // Error: "ProposalNotExists" with Pays::Yes. - let close_rval: DispatchResultWithPostInfo = Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len, - ); - assert_eq!(close_rval.unwrap_err().post_info.pays_fee, Pays::Yes); - }); -} - -#[test] -fn motions_reproposing_disapproved_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, false)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 0, false)); - - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - assert_eq!(*Collective::proposals(), vec![]); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_eq!(*Collective::proposals(), vec![hash]); - }); -} - -#[test] -fn motions_approval_with_enough_votes_and_lower_voting_threshold_works() { - new_test_ext().execute_with(|| { - let proposal = RuntimeCall::Democracy(mock_democracy::Call::external_propose_majority {}); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash: H256 = proposal.blake2_256().into(); - // The voting threshold is 2, but the required votes for `ExternalMajorityOrigin` is 3. - // The proposal will be executed regardless of the voting threshold - // as long as we have enough yes votes. - // - // Failed to execute with only 2 yes votes. - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 0, true)); - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - assert_eq!( - System::events(), - vec![ - record(RuntimeEvent::Collective(CollectiveEvent::Proposed { - account: 1, - proposal_index: 0, - proposal_hash: hash, - threshold: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 1, - proposal_hash: hash, - voted: true, - yes: 1, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 2, - proposal_hash: hash, - voted: true, - yes: 2, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Closed { - proposal_hash: hash, - yes: 2, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Approved { - proposal_hash: hash - })), - record(RuntimeEvent::Collective(CollectiveEvent::Executed { - proposal_hash: hash, - result: Err(DispatchError::BadOrigin) - })), - ] - ); - - System::reset_events(); - - // Executed with 3 yes votes. - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 1, true)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 1, true)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(3), hash, 1, true)); - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 1, - proposal_weight, - proposal_len - )); - assert_eq!( - System::events(), - vec![ - record(RuntimeEvent::Collective(CollectiveEvent::Proposed { - account: 1, - proposal_index: 1, - proposal_hash: hash, - threshold: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 1, - proposal_hash: hash, - voted: true, - yes: 1, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 2, - proposal_hash: hash, - voted: true, - yes: 2, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 3, - proposal_hash: hash, - voted: true, - yes: 3, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Closed { - proposal_hash: hash, - yes: 3, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Approved { - proposal_hash: hash - })), - record(RuntimeEvent::Democracy( - mock_democracy::pallet::Event::::ExternalProposed - )), - record(RuntimeEvent::Collective(CollectiveEvent::Executed { - proposal_hash: hash, - result: Ok(()) - })), - ] - ); - }); -} - -#[test] -fn motions_disapproval_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, false)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 0, false)); - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - - assert_eq!( - System::events(), - vec![ - record(RuntimeEvent::Collective(CollectiveEvent::Proposed { - account: 1, - proposal_index: 0, - proposal_hash: hash, - threshold: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 1, - proposal_hash: hash, - voted: false, - yes: 0, - no: 1 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 2, - proposal_hash: hash, - voted: false, - yes: 0, - no: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Closed { - proposal_hash: hash, - yes: 0, - no: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Disapproved { - proposal_hash: hash - })), - ] - ); - }); -} - -#[test] -fn motions_approval_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 0, true)); - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - - assert_eq!( - System::events(), - vec![ - record(RuntimeEvent::Collective(CollectiveEvent::Proposed { - account: 1, - proposal_index: 0, - proposal_hash: hash, - threshold: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 1, - proposal_hash: hash, - voted: true, - yes: 1, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 2, - proposal_hash: hash, - voted: true, - yes: 2, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Closed { - proposal_hash: hash, - yes: 2, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Approved { - proposal_hash: hash - })), - record(RuntimeEvent::Collective(CollectiveEvent::Executed { - proposal_hash: hash, - result: Err(DispatchError::BadOrigin) - })), - ] - ); - }); -} - -#[test] -fn motion_with_no_votes_closes_with_disapproval() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - assert_eq!( - System::events()[0], - record(RuntimeEvent::Collective(CollectiveEvent::Proposed { - account: 1, - proposal_index: 0, - proposal_hash: hash, - threshold: 2 - })) - ); - - // Closing the motion too early is not possible because it has neither - // an approving or disapproving simple majority due to the lack of votes. - assert_noop!( - Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - ), - Error::::TooEarlyToCloseProposal - ); - - // Once the motion duration passes, - let closing_block = System::block_number() + ::get(); - System::set_block_number(closing_block); - // we can successfully close the motion. - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - - // Events show that the close ended in a disapproval. - assert_eq!( - System::events()[1], - record(RuntimeEvent::Collective(CollectiveEvent::Closed { - proposal_hash: hash, - yes: 0, - no: 3 - })) - ); - assert_eq!( - System::events()[2], - record(RuntimeEvent::Collective(CollectiveEvent::Disapproved { - proposal_hash: hash - })) - ); - }) -} - -#[test] -fn close_disapprove_does_not_care_about_weight_or_len() { - // This test confirms that if you close a proposal that would be disapproved, - // we do not care about the proposal length or proposal weight since it will - // not be read from storage or executed. - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - // First we make the proposal succeed - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 0, true)); - // It will not close with bad weight/len information - assert_noop!( - Collective::close(RuntimeOrigin::root(), hash, 0, Weight::zero(), 0), - Error::::ProposalLengthBoundLessThanProposalLength, - ); - assert_noop!( - Collective::close(RuntimeOrigin::root(), hash, 0, Weight::zero(), proposal_len), - Error::::ProposalWeightLessThanDispatchCallWeight, - ); - // Now we make the proposal fail - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, false)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 0, false)); - // It can close even if the weight/len information is bad - assert_ok!(Collective::close( - RuntimeOrigin::root(), - hash, - 0, - Weight::zero(), - 0 - )); - }) -} - -#[test] -fn disapprove_proposal_works() { - new_test_ext().execute_with(|| { - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(3u64).expect("convert u64 to block number.") - )); - // Proposal would normally succeed - assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); - assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 0, true)); - // But Root can disapprove and remove it anyway - assert_ok!(Collective::disapprove_proposal(RuntimeOrigin::root(), hash)); - assert_eq!( - System::events(), - vec![ - record(RuntimeEvent::Collective(CollectiveEvent::Proposed { - account: 1, - proposal_index: 0, - proposal_hash: hash, - threshold: 2 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 1, - proposal_hash: hash, - voted: true, - yes: 1, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Voted { - account: 2, - proposal_hash: hash, - voted: true, - yes: 2, - no: 0 - })), - record(RuntimeEvent::Collective(CollectiveEvent::Disapproved { - proposal_hash: hash - })), - ] - ); - }) -} - -#[test] -#[should_panic(expected = "Members cannot contain duplicate accounts.")] -fn genesis_build_panics_with_duplicate_members() { - pallet_collective::GenesisConfig:: { - members: vec![1, 2, 3, 1], - phantom: Default::default(), - } - .build_storage() - .unwrap(); -} diff --git a/pallets/collective/src/weights.rs b/pallets/collective/src/weights.rs deleted file mode 100644 index df233fc248..0000000000 --- a/pallets/collective/src/weights.rs +++ /dev/null @@ -1,554 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 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. - -//! Autogenerated weights for pallet_collective -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm2`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 - -// Executed Command: -// ./target/production/substrate -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_collective -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./frame/collective/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for pallet_collective. -pub trait WeightInfo { - fn set_members(m: u32, n: u32, p: u32, ) -> Weight; - fn execute(b: u32, m: u32, ) -> Weight; - fn propose_execute(b: u32, m: u32, ) -> Weight; - fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight; - fn vote(m: u32, ) -> Weight; - fn close_early_disapproved(m: u32, p: u32, ) -> Weight; - fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight; - fn close_disapproved(m: u32, p: u32, ) -> Weight; - fn close_approved(b: u32, m: u32, p: u32, ) -> Weight; - fn disapprove_proposal(p: u32, ) -> Weight; -} - -/// Weights for pallet_collective using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - /// Storage: Council Members (r:1 w:1) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:0) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:100 w:100) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Prime (r:0 w:1) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `m` is `[0, 100]`. - /// The range of component `n` is `[0, 100]`. - /// The range of component `p` is `[0, 100]`. - fn set_members(m: u32, _n: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + m * (3233 ±0) + p * (3223 ±0)` - // Estimated: `16586 + m * (7809 ±24) + p * (10238 ±24)` - // Minimum execution time: 17_093 nanoseconds. - Weight::from_parts(17_284_000, 16586) - // Standard Error: 64_700 - .saturating_add(Weight::from_parts(5_143_145, 0).saturating_mul(m.into())) - // Standard Error: 64_700 - .saturating_add(Weight::from_parts(7_480_941, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) - .saturating_add(Weight::from_parts(0, 7809).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 10238).saturating_mul(p.into())) - } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `b` is `[2, 1024]`. - /// The range of component `m` is `[1, 100]`. - fn execute(b: u32, m: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `234 + m * (32 ±0)` - // Estimated: `730 + m * (32 ±0)` - // Minimum execution time: 15_972 nanoseconds. - Weight::from_parts(14_971_445, 730) - // Standard Error: 32 - .saturating_add(Weight::from_parts(1_775, 0).saturating_mul(b.into())) - // Standard Error: 334 - .saturating_add(Weight::from_parts(17_052, 0).saturating_mul(m.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) - } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:0) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// The range of component `b` is `[2, 1024]`. - /// The range of component `m` is `[1, 100]`. - fn propose_execute(b: u32, m: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `234 + m * (32 ±0)` - // Estimated: `3440 + m * (64 ±0)` - // Minimum execution time: 17_950 nanoseconds. - Weight::from_parts(17_019_558, 3440) - // Standard Error: 41 - .saturating_add(Weight::from_parts(1_807, 0).saturating_mul(b.into())) - // Standard Error: 432 - .saturating_add(Weight::from_parts(27_986, 0).saturating_mul(m.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) - } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalCount (r:1 w:1) - /// Proof Skipped: Council ProposalCount (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:0 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// The range of component `b` is `[2, 1024]`. - /// The range of component `m` is `[2, 100]`. - /// The range of component `p` is `[1, 100]`. - fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `556 + m * (32 ±0) + p * (36 ±0)` - // Estimated: `6355 + m * (165 ±0) + p * (180 ±0)` - // Minimum execution time: 24_817 nanoseconds. - Weight::from_parts(24_778_955, 6355) - // Standard Error: 73 - .saturating_add(Weight::from_parts(2_355, 0).saturating_mul(b.into())) - // Standard Error: 765 - .saturating_add(Weight::from_parts(20_518, 0).saturating_mul(m.into())) - // Standard Error: 755 - .saturating_add(Weight::from_parts(85_670, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) - .saturating_add(Weight::from_parts(0, 165).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 180).saturating_mul(p.into())) - } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// The range of component `m` is `[5, 100]`. - fn vote(m: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1006 + m * (64 ±0)` - // Estimated: `4980 + m * (128 ±0)` - // Minimum execution time: 19_790 nanoseconds. - Weight::from_parts(20_528_275, 4980) - // Standard Error: 651 - .saturating_add(Weight::from_parts(48_856, 0).saturating_mul(m.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 128).saturating_mul(m.into())) - } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// The range of component `m` is `[4, 100]`. - /// The range of component `p` is `[1, 100]`. - fn close_early_disapproved(m: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `626 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `5893 + m * (260 ±0) + p * (144 ±0)` - // Minimum execution time: 25_564 nanoseconds. - Weight::from_parts(25_535_497, 5893) - // Standard Error: 610 - .saturating_add(Weight::from_parts(27_956, 0).saturating_mul(m.into())) - // Standard Error: 595 - .saturating_add(Weight::from_parts(84_835, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 260).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 144).saturating_mul(p.into())) - } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `b` is `[2, 1024]`. - /// The range of component `m` is `[4, 100]`. - /// The range of component `p` is `[1, 100]`. - fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `962 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `9164 + b * (4 ±0) + m * (264 ±0) + p * (160 ±0)` - // Minimum execution time: 36_515 nanoseconds. - Weight::from_parts(36_626_648, 9164) - // Standard Error: 98 - .saturating_add(Weight::from_parts(2_295, 0).saturating_mul(b.into())) - // Standard Error: 1_036 - .saturating_add(Weight::from_parts(22_182, 0).saturating_mul(m.into())) - // Standard Error: 1_010 - .saturating_add(Weight::from_parts(100_034, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 4).saturating_mul(b.into())) - .saturating_add(Weight::from_parts(0, 264).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 160).saturating_mul(p.into())) - } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:0) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// The range of component `m` is `[4, 100]`. - /// The range of component `p` is `[1, 100]`. - fn close_disapproved(m: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `646 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `7095 + m * (325 ±0) + p * (180 ±0)` - // Minimum execution time: 28_858 nanoseconds. - Weight::from_parts(28_050_047, 7095) - // Standard Error: 614 - .saturating_add(Weight::from_parts(34_031, 0).saturating_mul(m.into())) - // Standard Error: 599 - .saturating_add(Weight::from_parts(85_744, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 325).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 180).saturating_mul(p.into())) - } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:0) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `b` is `[2, 1024]`. - /// The range of component `m` is `[4, 100]`. - /// The range of component `p` is `[1, 100]`. - fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `982 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `10565 + b * (5 ±0) + m * (330 ±0) + p * (200 ±0)` - // Minimum execution time: 38_608 nanoseconds. - Weight::from_parts(39_948_329, 10565) - // Standard Error: 84 - .saturating_add(Weight::from_parts(2_045, 0).saturating_mul(b.into())) - // Standard Error: 895 - .saturating_add(Weight::from_parts(22_669, 0).saturating_mul(m.into())) - // Standard Error: 872 - .saturating_add(Weight::from_parts(95_525, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 5).saturating_mul(b.into())) - .saturating_add(Weight::from_parts(0, 330).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 200).saturating_mul(p.into())) - } - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:0 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// The range of component `p` is `[1, 100]`. - fn disapprove_proposal(p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `391 + p * (32 ±0)` - // Estimated: `1668 + p * (96 ±0)` - // Minimum execution time: 14_785 nanoseconds. - Weight::from_parts(16_393_818, 1668) - // Standard Error: 612 - .saturating_add(Weight::from_parts(76_786, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 96).saturating_mul(p.into())) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - /// Storage: Council Members (r:1 w:1) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:0) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:100 w:100) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Prime (r:0 w:1) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `m` is `[0, 100]`. - /// The range of component `n` is `[0, 100]`. - /// The range of component `p` is `[0, 100]`. - fn set_members(m: u32, _n: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + m * (3233 ±0) + p * (3223 ±0)` - // Estimated: `16586 + m * (7809 ±24) + p * (10238 ±24)` - // Minimum execution time: 17_093 nanoseconds. - Weight::from_parts(17_284_000, 16586) - // Standard Error: 64_700 - .saturating_add(Weight::from_parts(5_143_145, 0).saturating_mul(m.into())) - // Standard Error: 64_700 - .saturating_add(Weight::from_parts(7_480_941, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(p.into()))) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(p.into()))) - .saturating_add(Weight::from_parts(0, 7809).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 10238).saturating_mul(p.into())) - } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `b` is `[2, 1024]`. - /// The range of component `m` is `[1, 100]`. - fn execute(b: u32, m: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `234 + m * (32 ±0)` - // Estimated: `730 + m * (32 ±0)` - // Minimum execution time: 15_972 nanoseconds. - Weight::from_parts(14_971_445, 730) - // Standard Error: 32 - .saturating_add(Weight::from_parts(1_775, 0).saturating_mul(b.into())) - // Standard Error: 334 - .saturating_add(Weight::from_parts(17_052, 0).saturating_mul(m.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) - } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:0) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// The range of component `b` is `[2, 1024]`. - /// The range of component `m` is `[1, 100]`. - fn propose_execute(b: u32, m: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `234 + m * (32 ±0)` - // Estimated: `3440 + m * (64 ±0)` - // Minimum execution time: 17_950 nanoseconds. - Weight::from_parts(17_019_558, 3440) - // Standard Error: 41 - .saturating_add(Weight::from_parts(1_807, 0).saturating_mul(b.into())) - // Standard Error: 432 - .saturating_add(Weight::from_parts(27_986, 0).saturating_mul(m.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) - } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalCount (r:1 w:1) - /// Proof Skipped: Council ProposalCount (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:0 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// The range of component `b` is `[2, 1024]`. - /// The range of component `m` is `[2, 100]`. - /// The range of component `p` is `[1, 100]`. - fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `556 + m * (32 ±0) + p * (36 ±0)` - // Estimated: `6355 + m * (165 ±0) + p * (180 ±0)` - // Minimum execution time: 24_817 nanoseconds. - Weight::from_parts(24_778_955, 6355) - // Standard Error: 73 - .saturating_add(Weight::from_parts(2_355, 0).saturating_mul(b.into())) - // Standard Error: 765 - .saturating_add(Weight::from_parts(20_518, 0).saturating_mul(m.into())) - // Standard Error: 755 - .saturating_add(Weight::from_parts(85_670, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - .saturating_add(Weight::from_parts(0, 165).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 180).saturating_mul(p.into())) - } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// The range of component `m` is `[5, 100]`. - fn vote(m: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1006 + m * (64 ±0)` - // Estimated: `4980 + m * (128 ±0)` - // Minimum execution time: 19_790 nanoseconds. - Weight::from_parts(20_528_275, 4980) - // Standard Error: 651 - .saturating_add(Weight::from_parts(48_856, 0).saturating_mul(m.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 128).saturating_mul(m.into())) - } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// The range of component `m` is `[4, 100]`. - /// The range of component `p` is `[1, 100]`. - fn close_early_disapproved(m: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `626 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `5893 + m * (260 ±0) + p * (144 ±0)` - // Minimum execution time: 25_564 nanoseconds. - Weight::from_parts(25_535_497, 5893) - // Standard Error: 610 - .saturating_add(Weight::from_parts(27_956, 0).saturating_mul(m.into())) - // Standard Error: 595 - .saturating_add(Weight::from_parts(84_835, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 260).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 144).saturating_mul(p.into())) - } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `b` is `[2, 1024]`. - /// The range of component `m` is `[4, 100]`. - /// The range of component `p` is `[1, 100]`. - fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `962 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `9164 + b * (4 ±0) + m * (264 ±0) + p * (160 ±0)` - // Minimum execution time: 36_515 nanoseconds. - Weight::from_parts(36_626_648, 9164) - // Standard Error: 98 - .saturating_add(Weight::from_parts(2_295, 0).saturating_mul(b.into())) - // Standard Error: 1_036 - .saturating_add(Weight::from_parts(22_182, 0).saturating_mul(m.into())) - // Standard Error: 1_010 - .saturating_add(Weight::from_parts(100_034, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 4).saturating_mul(b.into())) - .saturating_add(Weight::from_parts(0, 264).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 160).saturating_mul(p.into())) - } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:0) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// The range of component `m` is `[4, 100]`. - /// The range of component `p` is `[1, 100]`. - fn close_disapproved(m: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `646 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `7095 + m * (325 ±0) + p * (180 ±0)` - // Minimum execution time: 28_858 nanoseconds. - Weight::from_parts(28_050_047, 7095) - // Standard Error: 614 - .saturating_add(Weight::from_parts(34_031, 0).saturating_mul(m.into())) - // Standard Error: 599 - .saturating_add(Weight::from_parts(85_744, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 325).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 180).saturating_mul(p.into())) - } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:0) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `b` is `[2, 1024]`. - /// The range of component `m` is `[4, 100]`. - /// The range of component `p` is `[1, 100]`. - fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `982 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `10565 + b * (5 ±0) + m * (330 ±0) + p * (200 ±0)` - // Minimum execution time: 38_608 nanoseconds. - Weight::from_parts(39_948_329, 10565) - // Standard Error: 84 - .saturating_add(Weight::from_parts(2_045, 0).saturating_mul(b.into())) - // Standard Error: 895 - .saturating_add(Weight::from_parts(22_669, 0).saturating_mul(m.into())) - // Standard Error: 872 - .saturating_add(Weight::from_parts(95_525, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 5).saturating_mul(b.into())) - .saturating_add(Weight::from_parts(0, 330).saturating_mul(m.into())) - .saturating_add(Weight::from_parts(0, 200).saturating_mul(p.into())) - } - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:0 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// The range of component `p` is `[1, 100]`. - fn disapprove_proposal(p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `391 + p * (32 ±0)` - // Estimated: `1668 + p * (96 ±0)` - // Minimum execution time: 14_785 nanoseconds. - Weight::from_parts(16_393_818, 1668) - // Standard Error: 612 - .saturating_add(Weight::from_parts(76_786, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 96).saturating_mul(p.into())) - } -} diff --git a/pallets/subtensor/Cargo.toml b/pallets/subtensor/Cargo.toml index 35601fe875..281f226683 100644 --- a/pallets/subtensor/Cargo.toml +++ b/pallets/subtensor/Cargo.toml @@ -44,9 +44,7 @@ runtime-common.workspace = true subtensor-runtime-common = { workspace = true, features = ["approx"] } pallet-drand.workspace = true -pallet-subtensor-collective.workspace = true pallet-commitments.workspace = true -pallet-membership.workspace = true hex-literal.workspace = true num-traits = { workspace = true, features = ["libm"] } tle.workspace = true @@ -77,13 +75,11 @@ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "pallet-membership/try-runtime", "pallet-preimage/try-runtime", "pallet-scheduler/try-runtime", "pallet-transaction-payment/try-runtime", "runtime-common/try-runtime", "sp-runtime/try-runtime", - "pallet-subtensor-collective/try-runtime", "pallet-commitments/try-runtime", "pallet-crowdloan/try-runtime", "pallet-drand/try-runtime", @@ -99,7 +95,6 @@ std = [ "frame-support/std", "frame-system/std", "pallet-balances/std", - "pallet-membership/std", "pallet-preimage/std", "pallet-scheduler/std", "pallet-transaction-payment/std", @@ -111,7 +106,6 @@ std = [ "sp-tracing/std", "sp-version/std", "subtensor-runtime-common/std", - "pallet-subtensor-collective/std", "pallet-commitments/std", "pallet-crowdloan/std", "pallet-drand/std", @@ -139,13 +133,11 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "pallet-membership/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", "pallet-transaction-payment/runtime-benchmarks", "runtime-common/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "pallet-subtensor-collective/runtime-benchmarks", "pallet-commitments/runtime-benchmarks", "pallet-crowdloan/runtime-benchmarks", "pallet-drand/runtime-benchmarks", diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index 5b73ac3f41..73c7a8beba 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -657,18 +657,6 @@ mod pallet_benchmarks { _(RawOrigin::Signed(coldkey.clone()), netuid); } - #[benchmark] - fn adjust_senate() { - let coldkey: T::AccountId = whitelisted_caller(); - let hotkey: T::AccountId = account("Alice", 0, 1); - - Subtensor::::init_new_network(NetUid::ROOT, 1); - Uids::::insert(NetUid::ROOT, &hotkey, 0u16); - - #[extrinsic_call] - _(RawOrigin::Signed(coldkey.clone()), hotkey.clone()); - } - #[benchmark] fn add_stake_limit() { let netuid = NetUid::from(1); diff --git a/pallets/subtensor/src/coinbase/root.rs b/pallets/subtensor/src/coinbase/root.rs index 6b09c9ed46..61d5860354 100644 --- a/pallets/subtensor/src/coinbase/root.rs +++ b/pallets/subtensor/src/coinbase/root.rs @@ -17,9 +17,7 @@ use super::*; use crate::CommitmentsInterface; -use frame_support::{dispatch::Pays, weights::Weight}; use safe_math::*; -use sp_core::Get; use substrate_fixed::types::{I64F64, U96F32}; use subtensor_runtime_common::{AlphaCurrency, Currency, NetUid, NetUidStorageIndex, TaoCurrency}; use subtensor_swap_interface::SwapHandler; @@ -162,16 +160,12 @@ impl Pallet { ); } - // --- 13. Join the Senate if eligible. - // Returns the replaced member, if any. - let _ = Self::join_senate_if_eligible(&hotkey)?; - - // --- 14. Force all members on root to become a delegate. + // --- 13. Force all members on root to become a delegate. if !Self::hotkey_is_delegate(&hotkey) { Self::delegate_hotkey(&hotkey, 11_796); // 18% cut defaulted. } - // --- 15. Update the registration counters for both the block and interval. + // --- 14. Update the registration counters for both the block and interval. #[allow(clippy::arithmetic_side_effects)] // note this RA + clippy false positive is a known substrate issue RegistrationsThisInterval::::mutate(NetUid::ROOT, |val| *val += 1); @@ -179,7 +173,7 @@ impl Pallet { // note this RA + clippy false positive is a known substrate issue RegistrationsThisBlock::::mutate(NetUid::ROOT, |val| *val += 1); - // --- 16. Log and announce the successful registration. + // --- 15. Log and announce the successful registration. log::debug!( "RootRegistered(netuid:{:?} uid:{:?} hotkey:{:?})", NetUid::ROOT, @@ -192,166 +186,10 @@ impl Pallet { hotkey, )); - // --- 17. Finish and return success. - Ok(()) - } - - // Checks if a hotkey should be a member of the Senate, and if so, adds them. - // - // This function is responsible for adding a hotkey to the Senate if they meet the requirements. - // The root key with the least stake is pruned in the event of a filled membership. - // - // # Arguments: - // * 'origin': Represents the origin of the call. - // * 'hotkey': The hotkey that the user wants to register to the root network. - // - // # Returns: - // * 'DispatchResult': A result type indicating success or failure of the registration. - // - pub fn do_adjust_senate(origin: T::RuntimeOrigin, hotkey: T::AccountId) -> DispatchResult { - ensure!( - Self::if_subnet_exist(NetUid::ROOT), - Error::::RootNetworkDoesNotExist - ); - - // --- 1. Ensure that the call originates from a signed source and retrieve the caller's account ID (coldkey). - let coldkey = ensure_signed(origin)?; - log::debug!("do_root_register( coldkey: {coldkey:?}, hotkey: {hotkey:?} )"); - - // --- 2. Check if the hotkey is already registered to the root network. If not, error out. - ensure!( - Uids::::contains_key(NetUid::ROOT, &hotkey), - Error::::HotKeyNotRegisteredInSubNet - ); - - // --- 3. Create a network account for the user if it doesn't exist. - Self::create_account_if_non_existent(&coldkey, &hotkey); - - // --- 4. Join the Senate if eligible. - // Returns the replaced member, if any. - let replaced = Self::join_senate_if_eligible(&hotkey)?; - - if replaced.is_none() { - // Not eligible to join the Senate, or no replacement needed. - // Check if the hotkey is *now* a member of the Senate. - // Otherwise, error out. - ensure!( - T::SenateMembers::is_member(&hotkey), - Error::::StakeTooLowForRoot, // Had less stake than the lowest stake incumbent. - ); - } - - // --- 5. Log and announce the successful Senate adjustment. - log::debug!("SenateAdjusted(old_hotkey:{replaced:?} hotkey:{hotkey:?})"); - Self::deposit_event(Event::SenateAdjusted { - old_member: replaced.cloned(), - new_member: hotkey, - }); - - // --- 6. Finish and return success. + // --- 16. Finish and return success. Ok(()) } - // Checks if a hotkey should be a member of the Senate, and if so, adds them. - // - // # Arguments: - // * 'hotkey': The hotkey that the user wants to register to the root network. - // - // # Returns: - // * 'Result, Error>': A result containing the replaced member, if any. - // - fn join_senate_if_eligible(hotkey: &T::AccountId) -> Result, Error> { - // --- 1. Check the hotkey is registered in the root network. - ensure!( - Uids::::contains_key(NetUid::ROOT, hotkey), - Error::::HotKeyNotRegisteredInSubNet - ); - - // --- 2. Verify the hotkey is NOT already a member of the Senate. - ensure!( - !T::SenateMembers::is_member(hotkey), - Error::::HotKeyAlreadyRegisteredInSubNet - ); - - // --- 3. Grab the hotkey's stake. - let current_stake = Self::get_stake_for_hotkey_on_subnet(hotkey, NetUid::ROOT); - - // Add the hotkey to the Senate. - // If we're full, we'll swap out the lowest stake member. - let members = T::SenateMembers::members(); - let last: Option<&T::AccountId> = None; - if (members.len() as u32) == T::SenateMembers::max_members() { - let mut sorted_members = members.clone(); - sorted_members.sort_by(|a, b| { - let a_stake = Self::get_stake_for_hotkey_on_subnet(a, NetUid::ROOT); - let b_stake = Self::get_stake_for_hotkey_on_subnet(b, NetUid::ROOT); - - b_stake.cmp(&a_stake) - }); - - if let Some(last) = sorted_members.last() { - let last_stake = Self::get_stake_for_hotkey_on_subnet(last, NetUid::ROOT); - - if last_stake < current_stake { - // Swap the member with the lowest stake. - T::SenateMembers::swap_member(last, hotkey) - .map_err(|_| Error::::CouldNotJoinSenate)?; - } - } - } else { - T::SenateMembers::add_member(hotkey).map_err(|_| Error::::CouldNotJoinSenate)?; - } - - // Return the swapped out member, if any. - Ok(last) - } - - pub fn do_vote_root( - origin: T::RuntimeOrigin, - hotkey: &T::AccountId, - proposal: T::Hash, - index: u32, - approve: bool, - ) -> DispatchResultWithPostInfo { - // --- 1. Ensure that the caller has signed with their coldkey. - let coldkey = ensure_signed(origin.clone())?; - - // --- 2. Ensure that the calling coldkey owns the associated hotkey. - ensure!( - Self::coldkey_owns_hotkey(&coldkey, hotkey), - Error::::NonAssociatedColdKey - ); - - // --- 3. Ensure that the calling hotkey is a member of the senate. - ensure!( - T::SenateMembers::is_member(hotkey), - Error::::NotSenateMember - ); - - // --- 4. Detects first vote of the member in the motion - let is_account_voting_first_time = - T::TriumvirateInterface::add_vote(hotkey, proposal, index, approve)?; - - // --- 5. Calculate extrinsic weight - let members = T::SenateMembers::members(); - let member_count = members.len() as u32; - let vote_weight = Weight::from_parts(20_528_275, 4980) - .saturating_add(Weight::from_parts(48_856, 0).saturating_mul(member_count.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 128).saturating_mul(member_count.into())); - - Ok(( - Some(vote_weight), - if is_account_voting_first_time { - Pays::No - } else { - Pays::Yes - }, - ) - .into()) - } - /// Facilitates the removal of a user's subnetwork. /// /// # Args: diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index c52c589ad6..ef475b1033 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -91,11 +91,6 @@ pub mod pallet { AlphaCurrency, Currency, MechId, NetUid, NetUidStorageIndex, TaoCurrency, }; - #[cfg(not(feature = "std"))] - use alloc::boxed::Box; - #[cfg(feature = "std")] - use sp_std::prelude::Box; - /// Origin for the pallet pub type PalletsOriginOf = <::RuntimeOrigin as OriginTrait>::PalletsOrigin; @@ -795,11 +790,6 @@ pub mod pallet { 4 } #[pallet::type_value] - /// Senate requirements - pub fn DefaultSenateRequiredStakePercentage() -> u64 { - T::InitialSenateRequiredStakePercentage::get() - } - #[pallet::type_value] /// -- ITEM (switches liquid alpha on) pub fn DefaultLiquidAlpha() -> bool { false @@ -939,10 +929,6 @@ pub mod pallet { pub type DissolveNetworkScheduleDuration = StorageValue<_, BlockNumberFor, ValueQuery, DefaultDissolveNetworkScheduleDuration>; - #[pallet::storage] - pub type SenateRequiredStakePercentage = - StorageValue<_, u64, ValueQuery, DefaultSenateRequiredStakePercentage>; - #[pallet::storage] /// --- DMap ( netuid, coldkey ) --> blocknumber | last hotkey swap on network. pub type LastHotkeySwapOnNetuid = StorageDoubleMap< @@ -2071,81 +2057,6 @@ use sp_std::vec; use sp_std::vec::Vec; use subtensor_macros::freeze_struct; -/// Trait for managing a membership pallet instance in the runtime -pub trait MemberManagement { - /// Add member - fn add_member(account: &AccountId) -> DispatchResultWithPostInfo; - - /// Remove a member - fn remove_member(account: &AccountId) -> DispatchResultWithPostInfo; - - /// Swap member - fn swap_member(remove: &AccountId, add: &AccountId) -> DispatchResultWithPostInfo; - - /// Get all members - fn members() -> Vec; - - /// Check if an account is apart of the set - fn is_member(account: &AccountId) -> bool; - - /// Get our maximum member count - fn max_members() -> u32; -} - -impl MemberManagement for () { - /// Add member - fn add_member(_: &T) -> DispatchResultWithPostInfo { - Ok(().into()) - } - - // Remove a member - fn remove_member(_: &T) -> DispatchResultWithPostInfo { - Ok(().into()) - } - - // Swap member - fn swap_member(_: &T, _: &T) -> DispatchResultWithPostInfo { - Ok(().into()) - } - - // Get all members - fn members() -> Vec { - vec![] - } - - // Check if an account is apart of the set - fn is_member(_: &T) -> bool { - false - } - - fn max_members() -> u32 { - 0 - } -} - -/// Trait for interacting with collective pallets -pub trait CollectiveInterface { - /// Remove vote - fn remove_votes(hotkey: &AccountId) -> Result; - - fn add_vote( - hotkey: &AccountId, - proposal: Hash, - index: ProposalIndex, - approve: bool, - ) -> Result; -} - -impl CollectiveInterface for () { - fn remove_votes(_: &T) -> Result { - Ok(true) - } - - fn add_vote(_: &T, _: H, _: P, _: bool) -> Result { - Ok(true) - } -} - #[derive(Clone)] pub struct TaoCurrencyReserve(PhantomData); diff --git a/pallets/subtensor/src/macros/config.rs b/pallets/subtensor/src/macros/config.rs index d86e743e43..c449742905 100644 --- a/pallets/subtensor/src/macros/config.rs +++ b/pallets/subtensor/src/macros/config.rs @@ -27,19 +27,10 @@ mod config { + UnfilteredDispatchable + GetDispatchInfo; - /// Origin checking for council majority - type CouncilOrigin: EnsureOrigin; - /// Currency type that will be used to place deposits on neurons type Currency: fungible::Balanced + fungible::Mutate; - /// Senate members with members management functions. - type SenateMembers: crate::MemberManagement; - - /// Interface to allow other pallets to control who can register identities - type TriumvirateInterface: crate::CollectiveInterface; - /// The scheduler type used for scheduling delayed calls. type Scheduler: ScheduleAnon< BlockNumberFor, @@ -195,9 +186,6 @@ mod config { /// Initial childkey take transaction rate limit. #[pallet::constant] type InitialTxChildKeyTakeRateLimit: Get; - /// Initial percentage of total stake required to join senate. - #[pallet::constant] - type InitialSenateRequiredStakePercentage: Get; /// Initial adjustment alpha on burn and pow. #[pallet::constant] type InitialAdjustmentAlpha: Get; diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index 78874b9f43..9f74075c20 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -1035,15 +1035,6 @@ mod dispatches { Self::do_root_register(origin, hotkey) } - /// Attempt to adjust the senate membership to include a hotkey - #[pallet::call_index(63)] - #[pallet::weight((Weight::from_parts(58_980_000, 0) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(4)), DispatchClass::Normal, Pays::Yes))] - pub fn adjust_senate(origin: OriginFor, hotkey: T::AccountId) -> DispatchResult { - Self::do_adjust_senate(origin, hotkey) - } - /// User register a new subnetwork via burning token #[pallet::call_index(7)] #[pallet::weight((Weight::from_parts(354_200_000, 0) @@ -1231,87 +1222,6 @@ mod dispatches { Self::set_max_childkey_take(take); Ok(()) } - // ================================== - // ==== Parameter Sudo calls ======== - // ================================== - // Each function sets the corresponding hyper paramter on the specified network - // Args: - // * 'origin': (Origin): - // - The caller, must be sudo. - // - // * `netuid` (u16): - // - The network identifier. - // - // * `hyperparameter value` (u16): - // - The value of the hyper parameter. - // - - /// Authenticates a council proposal and dispatches a function call with `Root` origin. - /// - /// The dispatch origin for this call must be a council majority. - /// - /// ## Complexity - /// - O(1). - #[pallet::call_index(51)] - #[pallet::weight((Weight::from_parts(111_100_000, 0), DispatchClass::Operational, Pays::Yes))] - pub fn sudo( - origin: OriginFor, - call: Box, - ) -> DispatchResultWithPostInfo { - // This is a public call, so we ensure that the origin is a council majority. - T::CouncilOrigin::ensure_origin(origin)?; - - let result = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into()); - let error = result.map(|_| ()).map_err(|e| e.error); - Self::deposit_event(Event::Sudid(error)); - - return result; - } - - /// Authenticates a council proposal and dispatches a function call with `Root` origin. - /// This function does not check the weight of the call, and instead allows the - /// user to specify the weight of the call. - /// - /// The dispatch origin for this call must be a council majority. - /// - /// ## Complexity - /// - O(1). - #[allow(deprecated)] - #[pallet::call_index(52)] - #[pallet::weight((*weight, call.get_dispatch_info().class, Pays::Yes))] - pub fn sudo_unchecked_weight( - origin: OriginFor, - call: Box, - weight: Weight, - ) -> DispatchResultWithPostInfo { - // We dont need to check the weight witness, suppress warning. - // See https://github.com/paritytech/polkadot-sdk/pull/1818. - let _ = weight; - - // This is a public call, so we ensure that the origin is a council majority. - T::CouncilOrigin::ensure_origin(origin)?; - - let result = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into()); - let error = result.map(|_| ()).map_err(|e| e.error); - Self::deposit_event(Event::Sudid(error)); - - return result; - } - - /// User vote on a proposal - #[pallet::call_index(55)] - #[pallet::weight((Weight::from_parts(111_100_000, 0) - .saturating_add(T::DbWeight::get().reads(0)) - .saturating_add(T::DbWeight::get().writes(0)), DispatchClass::Operational))] - pub fn vote( - origin: OriginFor, - hotkey: T::AccountId, - proposal: T::Hash, - #[pallet::compact] index: u32, - approve: bool, - ) -> DispatchResultWithPostInfo { - Self::do_vote_root(origin, &hotkey, proposal, index, approve) - } /// User register a new subnetwork #[pallet::call_index(59)] diff --git a/pallets/subtensor/src/macros/errors.rs b/pallets/subtensor/src/macros/errors.rs index 759e74f6e3..9d9b7a70f5 100644 --- a/pallets/subtensor/src/macros/errors.rs +++ b/pallets/subtensor/src/macros/errors.rs @@ -97,8 +97,6 @@ mod errors { TooManyRegistrationsThisInterval, /// The hotkey is required to be the origin. TransactorAccountShouldBeHotKey, - /// A hotkey is attempting to do something only senate members can do. - NotSenateMember, /// Faucet is disabled. FaucetDisabled, /// Not a subnet owner. @@ -130,8 +128,6 @@ mod errors { CommitRevealEnabled, /// Attemtping to commit/reveal weights when disabled. CommitRevealDisabled, - /// Not able to join the senate. - CouldNotJoinSenate, /// Attempting to set alpha high/low while disabled LiquidAlphaDisabled, /// Alpha high is too low: alpha_high > 0.8 diff --git a/pallets/subtensor/src/macros/events.rs b/pallets/subtensor/src/macros/events.rs index c34219d532..07232cbc14 100644 --- a/pallets/subtensor/src/macros/events.rs +++ b/pallets/subtensor/src/macros/events.rs @@ -136,8 +136,6 @@ mod events { RAORecycledForRegistrationSet(NetUid, TaoCurrency), /// min stake is set for validators to set weights. StakeThresholdSet(u64), - /// setting the minimum required stake amount for senate registration. - SenateRequiredStakePercentSet(u64), /// setting the adjustment alpha on a subnet. AdjustmentAlphaSet(NetUid, u64), /// the faucet it called on the test net. @@ -171,13 +169,6 @@ mod events { MaxDelegateTakeSet(u16), /// minimum delegate take is set by sudo/admin transaction MinDelegateTakeSet(u16), - /// a member of the senate is adjusted - SenateAdjusted { - /// the account ID of the old senate member, if any - old_member: Option, - /// the account ID of the new senate member - new_member: T::AccountId, - }, /// A coldkey has been swapped ColdkeySwapped { /// the account ID of old coldkey diff --git a/pallets/subtensor/src/migrations/migrate_create_root_network.rs b/pallets/subtensor/src/migrations/migrate_create_root_network.rs index 24e2251c38..c9d069b451 100644 --- a/pallets/subtensor/src/migrations/migrate_create_root_network.rs +++ b/pallets/subtensor/src/migrations/migrate_create_root_network.rs @@ -2,7 +2,7 @@ use super::*; use frame_support::{ pallet_prelude::{Identity, OptionQuery}, storage_alias, - traits::{DefensiveResult, Get}, + traits::Get, weights::Weight, }; use sp_std::vec::Vec; @@ -82,16 +82,9 @@ pub fn migrate_create_root_network() -> Weight { // Accrue weight for database writes weight.saturating_accrue(T::DbWeight::get().writes(8)); - // Remove all existing senate members - for hotkey_i in T::SenateMembers::members().iter() { - // Remove votes associated with the member - T::TriumvirateInterface::remove_votes(hotkey_i).defensive_ok(); - // Remove the member from the senate - T::SenateMembers::remove_member(hotkey_i).defensive_ok(); - - // Accrue weight for database operations - weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); - } + // Remove all existing triumvirate votes and senate members + remove_prefix::("Triumvirate", "Votes", &mut weight); + remove_prefix::("SenateMembers", "Members", &mut weight); log::info!("Migrated create root network"); weight diff --git a/pallets/subtensor/src/migrations/migrate_remove_unused_maps_and_values.rs b/pallets/subtensor/src/migrations/migrate_remove_unused_maps_and_values.rs index 701ab14893..df439eafe3 100644 --- a/pallets/subtensor/src/migrations/migrate_remove_unused_maps_and_values.rs +++ b/pallets/subtensor/src/migrations/migrate_remove_unused_maps_and_values.rs @@ -2,31 +2,7 @@ use super::*; use crate::HasMigrationRun; use frame_support::{traits::Get, weights::Weight}; use scale_info::prelude::string::String; -use sp_io::{ - KillStorageResult, - hashing::twox_128, - storage::{clear, clear_prefix}, -}; - -fn remove_prefix(old_map: &str, weight: &mut Weight) { - let mut prefix = Vec::new(); - prefix.extend_from_slice(&twox_128("SubtensorModule".as_bytes())); - prefix.extend_from_slice(&twox_128(old_map.as_bytes())); - - let removal_results = clear_prefix(&prefix, Some(u32::MAX)); - - let removed_entries_count = match removal_results { - KillStorageResult::AllRemoved(removed) => removed as u64, - KillStorageResult::SomeRemaining(removed) => { - log::info!("Failed To Remove Some Items During migration"); - removed as u64 - } - }; - - log::info!("Removed {removed_entries_count:?} entries from {old_map:?} map."); - - *weight = (*weight).saturating_add(T::DbWeight::get().writes(removed_entries_count)); -} +use sp_io::storage::clear; pub fn migrate_remove_unused_maps_and_values() -> Weight { let migration_name = b"migrate_remove_unused_maps_and_values".to_vec(); @@ -46,10 +22,10 @@ pub fn migrate_remove_unused_maps_and_values() -> Weight { ); // Remove EmissionValues entries - remove_prefix::("EmissionValues", &mut weight); + remove_prefix::("SubtensorModule", "EmissionValues", &mut weight); // Remove NetworkMaxStake - remove_prefix::("NetworkMaxStake", &mut weight); + remove_prefix::("SubtensorModule", "NetworkMaxStake", &mut weight); // Remove SubnetLimit clear(b"SubtensorModule::SubnetLimit"); diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index e92b86aa29..b41a66097a 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -101,3 +101,23 @@ pub(crate) fn migrate_storage( weight } + +pub(crate) fn remove_prefix(module: &str, old_map: &str, weight: &mut Weight) { + let mut prefix = Vec::new(); + prefix.extend_from_slice(&twox_128(module.as_bytes())); + prefix.extend_from_slice(&twox_128(old_map.as_bytes())); + + let removal_results = clear_prefix(&prefix, Some(u32::MAX)); + + let removed_entries_count = match removal_results { + KillStorageResult::AllRemoved(removed) => removed as u64, + KillStorageResult::SomeRemaining(removed) => { + log::info!("Failed To Remove Some Items During migration"); + removed as u64 + } + }; + + log::info!("Removed {removed_entries_count:?} entries from {old_map:?} map."); + + *weight = (*weight).saturating_add(T::DbWeight::get().writes(removed_entries_count)); +} \ No newline at end of file diff --git a/pallets/subtensor/src/swap/swap_hotkey.rs b/pallets/subtensor/src/swap/swap_hotkey.rs index ea270c1e10..681db3d4ad 100644 --- a/pallets/subtensor/src/swap/swap_hotkey.rs +++ b/pallets/subtensor/src/swap/swap_hotkey.rs @@ -131,16 +131,15 @@ impl Pallet { /// 4. Moves all stake-related data for the interval. /// 5. Updates the last transaction block for the new hotkey. /// 6. Transfers the delegate take information. - /// 7. Swaps Senate membership if applicable. - /// 8. Updates delegate information. - /// 9. For each subnet: + /// 7. Updates delegate information. + /// 8. For each subnet: /// - Updates network membership status. /// - Transfers UID and key information. /// - Moves Prometheus data. /// - Updates axon information. /// - Transfers weight commits. /// - Updates loaded emission data. - /// 10. Transfers all stake information, including updating staking hotkeys for each coldkey. + /// 9. Transfers all stake information, including updating staking hotkeys for each coldkey. /// /// Throughout the process, the function accumulates the computational weight of operations performed. /// @@ -207,14 +206,7 @@ impl Pallet { Self::remove_last_tx_block_childkey(old_hotkey); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // 9. Swap Senate members. - // Senate( hotkey ) --> ? - if T::SenateMembers::is_member(old_hotkey) { - T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } - - // 10. Swap delegates. + // 9. Swap delegates. // Delegates( hotkey ) -> take value -- the hotkey delegate take value. if Delegates::::contains_key(old_hotkey) { let old_delegate_take = Delegates::::get(old_hotkey); @@ -223,7 +215,7 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); } - // 11. Alpha already update in perform_hotkey_swap_on_one_subnet + // 10. Alpha already update in perform_hotkey_swap_on_one_subnet // Update the StakingHotkeys for the case where hotkey staked by multiple coldkeys. for ((coldkey, _netuid), _alpha) in old_alpha_values { // Swap StakingHotkeys. @@ -244,19 +236,6 @@ impl Pallet { Ok(()) } - pub fn swap_senate_member( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) -> DispatchResult { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - if T::SenateMembers::is_member(old_hotkey) { - T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } - Ok(()) - } - fn swap_hotkey_on_subnet( coldkey: &T::AccountId, old_hotkey: &T::AccountId, diff --git a/pallets/subtensor/src/tests/mock.rs b/pallets/subtensor/src/tests/mock.rs index 14ec878e77..73f8581d5e 100644 --- a/pallets/subtensor/src/tests/mock.rs +++ b/pallets/subtensor/src/tests/mock.rs @@ -8,7 +8,6 @@ use core::num::NonZeroU64; use crate::utils::rate_limiting::TransactionType; use crate::*; -use frame_support::dispatch::DispatchResultWithPostInfo; use frame_support::traits::{Contains, Everything, InherentBuilder, InsideBoth}; use frame_support::weights::Weight; use frame_support::weights::constants::RocksDbWeight; @@ -18,9 +17,7 @@ use frame_support::{ traits::{Hooks, PrivilegeCmp}, }; use frame_system as system; -use frame_system::{EnsureNever, EnsureRoot, RawOrigin, limits, offchain::CreateTransactionBase}; -use pallet_subtensor_collective as pallet_collective; -use pallet_subtensor_collective::MemberCount; +use frame_system::{EnsureRoot, RawOrigin, limits, offchain::CreateTransactionBase}; use pallet_subtensor_utility as pallet_utility; use sp_core::{ConstU64, Get, H256, U256, offchain::KeyTypeId}; use sp_runtime::Perbill; @@ -42,10 +39,6 @@ frame_support::construct_runtime!( { System: frame_system::{Pallet, Call, Config, Storage, Event} = 1, Balances: pallet_balances::{Pallet, Call, Config, Storage, Event} = 2, - Triumvirate: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 3, - TriumvirateMembers: pallet_membership::::{Pallet, Call, Storage, Event, Config} = 4, - Senate: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 5, - SenateMembers: pallet_membership::::{Pallet, Call, Storage, Event, Config} = 6, SubtensorModule: crate::{Pallet, Call, Storage, Event} = 7, Utility: pallet_utility::{Pallet, Call, Storage, Event} = 8, Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event} = 9, @@ -209,7 +202,6 @@ parameter_types! { pub const InitialMinDifficulty: u64 = 1; pub const InitialMaxDifficulty: u64 = u64::MAX; pub const InitialRAORecycledForRegistration: u64 = 0; - pub const InitialSenateRequiredStakePercentage: u64 = 2; // 2 percent of total stake pub const InitialNetworkImmunityPeriod: u64 = 1_296_000; pub const InitialNetworkMinLockCost: u64 = 100_000_000_000; pub const InitialSubnetOwnerCut: u16 = 0; // 0%. 100% of rewards go to validators + miners. @@ -235,171 +227,11 @@ parameter_types! { pub const EvmKeyAssociateRateLimit: u64 = 10; } -// Configure collective pallet for council -parameter_types! { - pub const CouncilMotionDuration: BlockNumber = 100; - pub const CouncilMaxProposals: u32 = 10; - pub const CouncilMaxMembers: u32 = 3; -} - -// Configure collective pallet for Senate -parameter_types! { - pub const SenateMaxMembers: u32 = 12; -} - -use pallet_collective::{CanPropose, CanVote, GetVotingMembers}; -pub struct CanProposeToTriumvirate; -impl CanPropose for CanProposeToTriumvirate { - fn can_propose(account: &AccountId) -> bool { - Triumvirate::is_member(account) - } -} - -pub struct CanVoteToTriumvirate; -impl CanVote for CanVoteToTriumvirate { - fn can_vote(_: &AccountId) -> bool { - //Senate::is_member(account) - false // Disable voting from pallet_collective::vote - } -} - -use crate::{CollectiveInterface, MemberManagement, StakeThreshold}; -pub struct ManageSenateMembers; -impl MemberManagement for ManageSenateMembers { - fn add_member(account: &AccountId) -> DispatchResultWithPostInfo { - let who = *account; - SenateMembers::add_member(RawOrigin::Root.into(), who) - } - - fn remove_member(account: &AccountId) -> DispatchResultWithPostInfo { - let who = *account; - SenateMembers::remove_member(RawOrigin::Root.into(), who) - } - - fn swap_member(rm: &AccountId, add: &AccountId) -> DispatchResultWithPostInfo { - let remove = *rm; - let add = *add; - - Triumvirate::remove_votes(rm)?; - SenateMembers::swap_member(RawOrigin::Root.into(), remove, add) - } - - fn is_member(account: &AccountId) -> bool { - SenateMembers::members().contains(account) - } - - fn members() -> Vec { - SenateMembers::members().into() - } - - fn max_members() -> u32 { - SenateMaxMembers::get() - } -} - -pub struct GetSenateMemberCount; -impl GetVotingMembers for GetSenateMemberCount { - fn get_count() -> MemberCount { - Senate::members().len() as u32 - } -} -impl Get for GetSenateMemberCount { - fn get() -> MemberCount { - SenateMaxMembers::get() - } -} - -pub struct TriumvirateVotes; -impl CollectiveInterface for TriumvirateVotes { - fn remove_votes(hotkey: &AccountId) -> Result { - Triumvirate::remove_votes(hotkey) - } - - fn add_vote( - hotkey: &AccountId, - proposal: H256, - index: u32, - approve: bool, - ) -> Result { - Triumvirate::do_vote(*hotkey, proposal, index, approve) - } -} - -// We call pallet_collective TriumvirateCollective -#[allow(dead_code)] -type TriumvirateCollective = pallet_collective::Instance1; -impl pallet_collective::Config for Test { - type RuntimeOrigin = RuntimeOrigin; - type Proposal = RuntimeCall; - type MotionDuration = CouncilMotionDuration; - type MaxProposals = CouncilMaxProposals; - type MaxMembers = GetSenateMemberCount; - type DefaultVote = pallet_collective::PrimeDefaultVote; - type WeightInfo = pallet_collective::weights::SubstrateWeight; - type SetMembersOrigin = EnsureNever; - type CanPropose = CanProposeToTriumvirate; - type CanVote = CanVoteToTriumvirate; - type GetVotingMembers = GetSenateMemberCount; -} - -// We call council members Triumvirate -#[allow(dead_code)] -type TriumvirateMembership = pallet_membership::Instance1; -impl pallet_membership::Config for Test { - type RuntimeEvent = RuntimeEvent; - type AddOrigin = EnsureRoot; - type RemoveOrigin = EnsureRoot; - type SwapOrigin = EnsureRoot; - type ResetOrigin = EnsureRoot; - type PrimeOrigin = EnsureRoot; - type MembershipInitialized = Triumvirate; - type MembershipChanged = Triumvirate; - type MaxMembers = CouncilMaxMembers; - type WeightInfo = pallet_membership::weights::SubstrateWeight; -} - -// This is a dummy collective instance for managing senate members -// Probably not the best solution, but fastest implementation -#[allow(dead_code)] -type SenateCollective = pallet_collective::Instance2; -impl pallet_collective::Config for Test { - type RuntimeOrigin = RuntimeOrigin; - type Proposal = RuntimeCall; - type MotionDuration = CouncilMotionDuration; - type MaxProposals = CouncilMaxProposals; - type MaxMembers = SenateMaxMembers; - type DefaultVote = pallet_collective::PrimeDefaultVote; - type WeightInfo = pallet_collective::weights::SubstrateWeight; - type SetMembersOrigin = EnsureNever; - type CanPropose = (); - type CanVote = (); - type GetVotingMembers = (); -} - -// We call our top K delegates membership Senate -#[allow(dead_code)] -type SenateMembership = pallet_membership::Instance2; -impl pallet_membership::Config for Test { - type RuntimeEvent = RuntimeEvent; - type AddOrigin = EnsureRoot; - type RemoveOrigin = EnsureRoot; - type SwapOrigin = EnsureRoot; - type ResetOrigin = EnsureRoot; - type PrimeOrigin = EnsureRoot; - type MembershipInitialized = Senate; - type MembershipChanged = Senate; - type MaxMembers = SenateMaxMembers; - type WeightInfo = pallet_membership::weights::SubstrateWeight; -} - impl crate::Config for Test { type RuntimeCall = RuntimeCall; type Currency = Balances; type InitialIssuance = InitialIssuance; type SudoRuntimeCall = TestRuntimeCall; - type CouncilOrigin = frame_system::EnsureSigned; - type SenateMembers = ManageSenateMembers; - type TriumvirateInterface = TriumvirateVotes; type Scheduler = Scheduler; type InitialMinAllowedWeights = InitialMinAllowedWeights; type InitialEmissionValue = InitialEmissionValue; @@ -442,7 +274,6 @@ impl crate::Config for Test { type MinBurnUpperBound = MinBurnUpperBound; type MaxBurnLowerBound = MaxBurnLowerBound; type InitialRAORecycledForRegistration = InitialRAORecycledForRegistration; - type InitialSenateRequiredStakePercentage = InitialSenateRequiredStakePercentage; type InitialNetworkImmunityPeriod = InitialNetworkImmunityPeriod; type InitialNetworkMinLockCost = InitialNetworkMinLockCost; type InitialSubnetOwnerCut = InitialSubnetOwnerCut; diff --git a/pallets/subtensor/src/tests/mod.rs b/pallets/subtensor/src/tests/mod.rs index fda2f90b4d..6e485b9087 100644 --- a/pallets/subtensor/src/tests/mod.rs +++ b/pallets/subtensor/src/tests/mod.rs @@ -20,7 +20,6 @@ mod networks; mod neuron_info; mod recycle_alpha; mod registration; -mod senate; mod serving; mod staking; mod staking2; diff --git a/pallets/subtensor/src/tests/senate.rs b/pallets/subtensor/src/tests/senate.rs deleted file mode 100644 index 8ad093d0ae..0000000000 --- a/pallets/subtensor/src/tests/senate.rs +++ /dev/null @@ -1,893 +0,0 @@ -#![allow(clippy::unwrap_used)] - -use approx::assert_abs_diff_eq; -use codec::Encode; -use frame_support::{assert_noop, assert_ok}; -use frame_system::Config; -use frame_system::pallet_prelude::*; -use frame_system::{EventRecord, Phase}; -use pallet_subtensor_collective as pallet_collective; -use pallet_subtensor_collective::Event as CollectiveEvent; -use sp_core::{Get, H256, U256, bounded_vec}; -use sp_runtime::{ - BuildStorage, - traits::{BlakeTwo256, Hash}, -}; -use subtensor_runtime_common::TaoCurrency; -use subtensor_swap_interface::SwapHandler; - -use super::mock; -use super::mock::*; -use crate::Delegates; -use crate::Error; -use crate::migrations; -use crate::*; - -pub fn new_test_ext() -> sp_io::TestExternalities { - sp_tracing::try_init_simple(); - - let mut ext: sp_io::TestExternalities = RuntimeGenesisConfig { - senate_members: pallet_membership::GenesisConfig:: { - members: bounded_vec![1.into(), 2.into(), 3.into(), 4.into(), 5.into()], - phantom: Default::default(), - }, - triumvirate: pallet_collective::GenesisConfig:: { - members: vec![1.into()], - phantom: Default::default(), - }, - ..Default::default() - } - .build_storage() - .unwrap() - .into(); - - ext.execute_with(|| System::set_block_number(1)); - ext -} - -fn make_proposal(value: u64) -> RuntimeCall { - RuntimeCall::System(frame_system::Call::remark_with_event { - remark: value.to_be_bytes().to_vec(), - }) -} - -fn record(event: RuntimeEvent) -> EventRecord { - EventRecord { - phase: Phase::Initialization, - event, - topics: vec![], - } -} - -#[test] -fn test_senate_join_works() { - new_test_ext().execute_with(|| { - migrations::migrate_create_root_network::migrate_create_root_network::(); - - let netuid = NetUid::from(1); - let tempo: u16 = 13; - let hotkey_account_id = U256::from(6); - let burn_cost = 1000; - let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har - let stake = DefaultMinStake::::get() * 100.into(); - - //add network - SubtensorModule::set_burn(netuid, burn_cost.into()); - add_network(netuid, tempo, 0); - // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); - - let reserve = 1_000_000_000; - mock::setup_reserves(netuid, reserve.into(), reserve.into()); - - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - hotkey_account_id - )); - // Check if balance has decreased to pay for the burn. - assert_eq!( - SubtensorModule::get_coldkey_balance(&coldkey_account_id), - (10000 - burn_cost) - ); // funds drained on reg. - // Check if neuron has added to the specified network(netuid) - assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 1); - // Check if hotkey is added to the Hotkeys - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey_account_id), - coldkey_account_id - ); - - // Lets make this new key a delegate with a 10% take. - Delegates::::insert(hotkey_account_id, u16::MAX / 10); - - let staker_coldkey = U256::from(7); - SubtensorModule::add_balance_to_coldkey_account(&staker_coldkey, stake.into()); - - assert_ok!(SubtensorModule::add_stake( - <::RuntimeOrigin>::signed(staker_coldkey), - hotkey_account_id, - netuid, - stake - )); - - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_account_id, - &staker_coldkey, - netuid - ), - AlphaCurrency::from(stake.to_u64()), - epsilon = 1.into() - ); - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - AlphaCurrency::from(stake.to_u64()), - epsilon = 1.into() - ); - - assert_ok!(SubtensorModule::root_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - hotkey_account_id - )); - assert!(Senate::is_member(&hotkey_account_id)); - }); -} - -#[test] -fn test_senate_vote_works() { - new_test_ext().execute_with(|| { - migrations::migrate_create_root_network::migrate_create_root_network::(); - - let netuid = NetUid::from(1); - let tempo: u16 = 13; - let senate_hotkey = U256::from(1); - let hotkey_account_id = U256::from(6); - let burn_cost = 1000; - let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har - - //add network - SubtensorModule::set_burn(netuid, burn_cost.into()); - add_network(netuid, tempo, 0); - // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); - - let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve.into(), reserve.into()); - - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - hotkey_account_id - )); - // Check if balance has decreased to pay for the burn. - assert_eq!( - SubtensorModule::get_coldkey_balance(&coldkey_account_id), - (10000 - burn_cost) - ); // funds drained on reg. - // Check if neuron has added to the specified network(netuid) - assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 1); - // Check if hotkey is added to the Hotkeys - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey_account_id), - coldkey_account_id - ); - - // Lets make this new key a delegate with a 10% take. - Delegates::::insert(hotkey_account_id, u16::MAX / 10); - - let staker_coldkey = U256::from(7); - let stake = DefaultMinStake::::get() * 10.into(); - SubtensorModule::add_balance_to_coldkey_account(&staker_coldkey, stake.into()); - - assert_ok!(SubtensorModule::add_stake( - <::RuntimeOrigin>::signed(staker_coldkey), - hotkey_account_id, - netuid, - stake - )); - - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_account_id, - &staker_coldkey, - netuid - ), - AlphaCurrency::from(stake.to_u64()), - epsilon = 1.into() - ); - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - AlphaCurrency::from(stake.to_u64()), - epsilon = 1.into() - ); - - assert_ok!(SubtensorModule::root_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - hotkey_account_id - )); - assert!(Senate::is_member(&hotkey_account_id)); - - System::reset_events(); - - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Triumvirate::propose( - RuntimeOrigin::signed(senate_hotkey), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(100u64) - .expect("convert u64 to block number.") - )); - - assert_ok!(SubtensorModule::do_vote_root( - <::RuntimeOrigin>::signed(coldkey_account_id), - &hotkey_account_id, - hash, - 0, - true - )); - assert_eq!( - System::events(), - vec![ - record(RuntimeEvent::Triumvirate(CollectiveEvent::Proposed { - account: senate_hotkey, - proposal_index: 0, - proposal_hash: hash, - threshold: 1 - })), - record(RuntimeEvent::Triumvirate(CollectiveEvent::Voted { - account: hotkey_account_id, - proposal_hash: hash, - voted: true, - yes: 1, - no: 0 - })) - ] - ); - }); -} - -#[test] -fn test_senate_vote_not_member() { - new_test_ext().execute_with(|| { - migrations::migrate_create_root_network::migrate_create_root_network::(); - - let netuid = NetUid::from(1); - let tempo: u16 = 13; - let senate_hotkey = U256::from(1); - let hotkey_account_id = U256::from(6); - let burn_cost = 1000; - let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har - - //add network - SubtensorModule::set_burn(netuid, burn_cost.into()); - add_network(netuid, tempo, 0); - // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); - - let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve.into(), reserve.into()); - - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - hotkey_account_id - )); - // Check if balance has decreased to pay for the burn. - assert_eq!( - SubtensorModule::get_coldkey_balance(&coldkey_account_id), - (10000 - burn_cost) - ); // funds drained on reg. - // Check if neuron has added to the specified network(netuid) - assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 1); - // Check if hotkey is added to the Hotkeys - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey_account_id), - coldkey_account_id - ); - - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Triumvirate::propose( - RuntimeOrigin::signed(senate_hotkey), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(100u64) - .expect("convert u64 to block number.") - )); - - assert_noop!( - SubtensorModule::do_vote_root( - <::RuntimeOrigin>::signed(coldkey_account_id), - &hotkey_account_id, - hash, - 0, - true - ), - Error::::NotSenateMember - ); - }); -} - -#[test] -fn test_senate_leave_works() { - new_test_ext().execute_with(|| { - migrations::migrate_create_root_network::migrate_create_root_network::(); - - let netuid = NetUid::from(1); - let tempo: u16 = 13; - let hotkey_account_id = U256::from(6); - let burn_cost = 1000; - let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har - let stake = DefaultMinStake::::get() * 10.into(); - - //add network - SubtensorModule::set_burn(netuid, burn_cost.into()); - add_network(netuid, tempo, 0); - // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); - - let reserve = stake.to_u64() * 1000; - mock::setup_reserves(netuid, reserve.into(), reserve.into()); - - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - hotkey_account_id - )); - // Check if balance has decreased to pay for the burn. - assert_eq!( - SubtensorModule::get_coldkey_balance(&coldkey_account_id), - (10000 - burn_cost) - ); // funds drained on reg. - // Check if neuron has added to the specified network(netuid) - assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 1); - // Check if hotkey is added to the Hotkeys - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey_account_id), - coldkey_account_id - ); - - // Lets make this new key a delegate with a 10% take. - Delegates::::insert(hotkey_account_id, u16::MAX / 10); - - let staker_coldkey = U256::from(7); - SubtensorModule::add_balance_to_coldkey_account(&staker_coldkey, stake.into()); - - assert_ok!(SubtensorModule::add_stake( - <::RuntimeOrigin>::signed(staker_coldkey), - hotkey_account_id, - netuid, - stake - )); - - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_account_id, - &staker_coldkey, - netuid - ), - AlphaCurrency::from(stake.to_u64()), - epsilon = 1.into() - ); - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - AlphaCurrency::from(stake.to_u64()), - epsilon = 1.into() - ); - - assert_ok!(SubtensorModule::root_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - hotkey_account_id - )); - assert!(Senate::is_member(&hotkey_account_id)); - }); -} - -#[test] -fn test_senate_leave_vote_removal() { - new_test_ext().execute_with(|| { - migrations::migrate_create_root_network::migrate_create_root_network::(); - - let netuid = NetUid::from(1); - let tempo: u16 = 13; - let senate_hotkey = U256::from(1); - let hotkey_account_id = U256::from(6); - let burn_cost = 1000; - let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har - let coldkey_origin = <::RuntimeOrigin>::signed(coldkey_account_id); - let stake = DefaultMinStake::::get() * 10.into(); - - //add network - SubtensorModule::set_burn(netuid, burn_cost.into()); - add_network(netuid, tempo, 0); - // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, stake.into()); - SubtokenEnabled::::insert(netuid, true); - - let reserve = stake.to_u64() * 1000; - mock::setup_reserves(netuid, reserve.into(), reserve.into()); - - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - coldkey_origin.clone(), - netuid, - hotkey_account_id - )); - // Check if balance has decreased to pay for the burn. - assert_eq!( - SubtensorModule::get_coldkey_balance(&coldkey_account_id), - (stake.to_u64() - burn_cost) - ); // funds drained on reg. - // Check if neuron has added to the specified network(netuid) - assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 1); - // Check if hotkey is added to the Hotkeys - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey_account_id), - coldkey_account_id - ); - - // Lets make this new key a delegate with a 10% take. - Delegates::::insert(hotkey_account_id, u16::MAX / 10); - - let staker_coldkey = U256::from(7); - SubtensorModule::add_balance_to_coldkey_account(&staker_coldkey, stake.into()); - - assert_ok!(SubtensorModule::add_stake( - <::RuntimeOrigin>::signed(staker_coldkey), - hotkey_account_id, - netuid, - stake - )); - - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_account_id, - &staker_coldkey, - netuid - ), - AlphaCurrency::from(stake.to_u64()), - epsilon = 1.into() - ); - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - AlphaCurrency::from(stake.to_u64()), - epsilon = 1.into() - ); - - assert_ok!(SubtensorModule::root_register( - coldkey_origin.clone(), - hotkey_account_id - )); - assert!(Senate::is_member(&hotkey_account_id)); - - let proposal = make_proposal(42); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Triumvirate::propose( - RuntimeOrigin::signed(senate_hotkey), - Box::new(proposal.clone()), - proposal_len, - TryInto::>::try_into(100u64) - .expect("convert u64 to block number.") - )); - - assert_ok!(SubtensorModule::do_vote_root( - coldkey_origin.clone(), - &hotkey_account_id, - hash, - 0, - true - )); - // Fill the root network with many large stake keys. - // This removes all other keys. - // Add two networks. - let other_netuid = NetUid::from(5); - add_network(other_netuid, 1, 0); - SubtensorModule::set_burn(other_netuid, TaoCurrency::ZERO); - SubtensorModule::set_max_registrations_per_block(other_netuid, 1000); - SubtensorModule::set_target_registrations_per_interval(other_netuid, 1000); - SubtensorModule::set_max_registrations_per_block(NetUid::ROOT, 1000); - SubtensorModule::set_target_registrations_per_interval(NetUid::ROOT, 1000); - - let reserve = 1_000_000_000_000; - mock::setup_reserves(other_netuid, reserve.into(), reserve.into()); - mock::setup_reserves(NetUid::ROOT, reserve.into(), reserve.into()); - SubtokenEnabled::::insert(NetUid::ROOT, true); - SubtokenEnabled::::insert(other_netuid, true); - - for i in 0..200 { - let hot = U256::from(i + 100); - let cold = U256::from(i + 100); - // Add balance - SubtensorModule::add_balance_to_coldkey_account(&cold, 100_000_000 + (i as u64)); // lots ot stake - // Register - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(cold), - other_netuid, - hot - )); - // Add stake on other network - assert_ok!(SubtensorModule::add_stake( - <::RuntimeOrigin>::signed(cold), - hot, - NetUid::ROOT, - (100_000_000 + (i as u64)).into() - )); - // Register them on the root network. - assert_ok!(SubtensorModule::root_register( - <::RuntimeOrigin>::signed(cold), - hot, - )); - // Check succesfull registration. - assert!(SubtensorModule::get_uid_for_net_and_hotkey(other_netuid, &hot).is_ok()); - assert!(SubtensorModule::get_uid_for_net_and_hotkey(NetUid::ROOT, &hot).is_ok()); - // Check that they are all delegates - assert!(SubtensorModule::hotkey_is_delegate(&hot)); - } - // No longer a root member - assert!( - SubtensorModule::get_uid_for_net_and_hotkey(NetUid::ROOT, &hotkey_account_id).is_err() - ); - // No longer a member of the senate - assert!(!Senate::is_member(&hotkey_account_id)); - assert_eq!( - // Vote is removed - Triumvirate::has_voted(hash, 0, &hotkey_account_id), - Ok(false) - ); - }); -} - -#[test] -fn test_senate_not_leave_when_stake_removed() { - new_test_ext().execute_with(|| { - migrations::migrate_create_root_network::migrate_create_root_network::(); - - let netuid = NetUid::from(1); - let tempo: u16 = 13; - let hotkey_account_id = U256::from(6); - let burn_cost = 1000; - let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har - - //add network - SubtensorModule::set_burn(netuid, burn_cost.into()); - add_network(netuid, tempo, 0); - // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); - - let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve.into(), reserve.into()); - - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - hotkey_account_id - )); - // Check if balance has decreased to pay for the burn. - assert_eq!( - SubtensorModule::get_coldkey_balance(&coldkey_account_id), - (10000 - burn_cost) - ); // funds drained on reg. - // Check if neuron has added to the specified network(netuid) - assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 1); - // Check if hotkey is added to the Hotkeys - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey_account_id), - coldkey_account_id - ); - - // Lets make this new key a delegate with a 10% take. - Delegates::::insert(hotkey_account_id, u16::MAX / 10); - - let staker_coldkey = U256::from(7); - let stake_amount = DefaultMinStake::::get() * 10.into(); - SubtensorModule::add_balance_to_coldkey_account(&staker_coldkey, stake_amount.into()); - - assert_ok!(SubtensorModule::add_stake( - <::RuntimeOrigin>::signed(staker_coldkey), - hotkey_account_id, - netuid, - stake_amount - )); - - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_account_id, - &staker_coldkey, - netuid - ), - AlphaCurrency::from(stake_amount.to_u64()), - epsilon = 1.into() - ); - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - AlphaCurrency::from(stake_amount.to_u64()), - epsilon = 1.into() - ); - - assert_ok!(SubtensorModule::root_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - hotkey_account_id - )); - assert!(Senate::is_member(&hotkey_account_id)); - - step_block(100); - - assert_ok!(SubtensorModule::remove_stake( - <::RuntimeOrigin>::signed(staker_coldkey), - hotkey_account_id, - netuid, - (stake_amount - 1.into()).to_u64().into() - )); - assert!(Senate::is_member(&hotkey_account_id)); - }); -} - -#[test] -fn test_senate_join_current_delegate() { - // Test that a current delegate can join the senate - new_test_ext().execute_with(|| { - migrations::migrate_create_root_network::migrate_create_root_network::(); - - let netuid = NetUid::from(1); - let tempo: u16 = 13; - let hotkey_account_id = U256::from(6); - let burn_cost = 1000; - let coldkey_account_id = U256::from(667); - - //add network - SubtensorModule::set_burn(netuid, burn_cost.into()); - add_network(netuid, tempo, 0); - // Give some coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); - - let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve.into(), reserve.into()); - - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - hotkey_account_id - )); - // Check if balance has decreased to pay for the burn. - assert_eq!( - SubtensorModule::get_coldkey_balance(&coldkey_account_id), - (10000 - burn_cost) - ); // funds drained on reg. - // Check if neuron has added to the specified network(netuid) - assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 1); - // Check if hotkey is added to the Hotkeys - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey_account_id), - coldkey_account_id - ); - - // Register in the root network - assert_ok!(SubtensorModule::root_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - hotkey_account_id - )); - // But, remove from the senate - assert_ok!(SenateMembers::remove_member( - <::RuntimeOrigin>::root(), - hotkey_account_id - )); - - // Should *NOT* be a member of the senate now - assert!(!Senate::is_member(&hotkey_account_id)); - - System::reset_events(); - - // We can call now to adjust the senate - assert_ok!(SubtensorModule::adjust_senate( - <::RuntimeOrigin>::signed(coldkey_account_id), - hotkey_account_id - )); - - // This should make the hotkey a member of the senate - assert!(Senate::is_member(&hotkey_account_id)); - - // Check the events - assert!( - System::events().contains(&record(RuntimeEvent::SubtensorModule( - SubtensorEvent::SenateAdjusted { - old_member: None, - new_member: hotkey_account_id - } - ))) - ); - }); -} - -#[test] -fn test_adjust_senate_events() { - // Test the events emitted after adjusting the senate successfully - new_test_ext().execute_with(|| { - migrations::migrate_create_root_network::migrate_create_root_network::(); - - let netuid = NetUid::from(1); - let tempo: u16 = 13; - let hotkey_account_id = U256::from(6); - let burn_cost = 1000; - let coldkey_account_id = U256::from(667); - - let max_senate_size: u16 = SenateMaxMembers::get() as u16; - let stake_threshold = { - let default_stake = DefaultMinStake::::get(); - let fee = - ::SwapInterface::approx_fee_amount(netuid, default_stake); - (default_stake + fee).to_u64() - }; - - // We will be registering MaxMembers hotkeys and two more to try a replace - let balance_to_add = DefaultMinStake::::get().to_u64() * 10 - + 50_000 - + (stake_threshold + burn_cost) * (max_senate_size + 2) as u64; - - let replacement_hotkey_account_id = U256::from(7); // Will be added to the senate to replace hotkey_account_id - - //add network - SubtensorModule::set_burn(netuid, burn_cost.into()); - add_network(netuid, tempo, 0); - // Give some coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, balance_to_add); - - // Allow all registrations in netuid in same block. Same for root network. - SubtensorModule::set_max_registrations_per_block(netuid, max_senate_size + 1); - SubtensorModule::set_target_registrations_per_interval(netuid, max_senate_size + 1); - SubtensorModule::set_max_registrations_per_block(NetUid::ROOT, max_senate_size + 1); - SubtensorModule::set_target_registrations_per_interval(NetUid::ROOT, max_senate_size + 1); - SubtokenEnabled::::insert(netuid, true); - SubtokenEnabled::::insert(NetUid::ROOT, true); - - let reserve = 100_000_000_000_000; - mock::setup_reserves(netuid, reserve.into(), reserve.into()); - - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - hotkey_account_id - )); - // Check if balance has decreased to pay for the burn. - assert_eq!( - SubtensorModule::get_coldkey_balance(&coldkey_account_id), - (balance_to_add - burn_cost) - ); // funds drained on reg. - // Check if neuron has added to the specified network(netuid) - assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 1); - // Check if hotkey is added to the Hotkeys - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey_account_id), - coldkey_account_id - ); - - // Should *NOT* be a member of the senate - assert!(!Senate::is_member(&hotkey_account_id)); - - // root register - assert_ok!(SubtensorModule::root_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - hotkey_account_id - )); // Has no stake, but is now a senate member - - // Check if they are a member of the senate - assert!(Senate::is_member(&hotkey_account_id)); - - // Register MaxMembers - 1 more hotkeys, add stake and join the senate - for i in 0..(max_senate_size - 1) { - let new_hotkey_account_id = U256::from(8 + i); - - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - new_hotkey_account_id - )); - // Check if this hotkey is added to the Hotkeys - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkey_account_id), - coldkey_account_id - ); - // Add/delegate enough stake to join the senate - // +1 to be above hotkey_account_id - assert_ok!(SubtensorModule::add_stake( - <::RuntimeOrigin>::signed(coldkey_account_id), - new_hotkey_account_id, - netuid, - (stake_threshold + 1 + i as u64).into() // Increasing with i to make them ordered - )); - // Join senate - assert_ok!(SubtensorModule::root_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - new_hotkey_account_id - )); - // Check if they are a member of the senate - assert!(Senate::is_member(&new_hotkey_account_id)); - } - - // Verify we are at max senate size - assert_eq!(Senate::members().len(), max_senate_size as usize); - - // Verify the replacement hotkey is not a member of the senate - assert!(!Senate::is_member(&replacement_hotkey_account_id)); - - // Register - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - replacement_hotkey_account_id - )); - - // Register in root network - assert_ok!(SubtensorModule::root_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - replacement_hotkey_account_id - )); - - // Check if they are a member of the senate, should not be, - // as they have no stake - assert!(!Senate::is_member(&replacement_hotkey_account_id)); - // Add/delegate enough stake to join the senate - let stake = DefaultMinStake::::get() * 10.into(); - - let reserve = 100_000_000_000_000; - mock::setup_reserves(NetUid::ROOT, reserve.into(), reserve.into()); - - let (_, fee) = mock::swap_tao_to_alpha(NetUid::ROOT, stake); - - assert_ok!(SubtensorModule::add_stake( - <::RuntimeOrigin>::signed(coldkey_account_id), - replacement_hotkey_account_id, - NetUid::ROOT, - stake // Will be more than the last one in the senate by stake (has 0 stake) - )); - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &replacement_hotkey_account_id, - &coldkey_account_id, - NetUid::ROOT - ), - AlphaCurrency::from(stake.to_u64() - fee), - epsilon = (stake.to_u64() / 1000).into() - ); - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_on_subnet( - &replacement_hotkey_account_id, - NetUid::ROOT - ), - AlphaCurrency::from(stake.to_u64() - fee), - epsilon = (stake.to_u64() / 1000).into() - ); - - System::reset_events(); - - // We can call now to adjust the senate - assert_ok!(SubtensorModule::adjust_senate( - <::RuntimeOrigin>::signed(coldkey_account_id), - replacement_hotkey_account_id - )); - - // This should make the hotkey a member of the senate - assert!(Senate::is_member(&replacement_hotkey_account_id)); - - // Check the events - assert!( - System::events().contains(&record(RuntimeEvent::SubtensorModule( - SubtensorEvent::SenateAdjusted { - old_member: None, - new_member: replacement_hotkey_account_id - } - ))) - ); - }); -} diff --git a/pallets/subtensor/src/tests/swap_coldkey.rs b/pallets/subtensor/src/tests/swap_coldkey.rs index 4c683671ae..9d3bdbfc62 100644 --- a/pallets/subtensor/src/tests/swap_coldkey.rs +++ b/pallets/subtensor/src/tests/swap_coldkey.rs @@ -1616,51 +1616,6 @@ fn test_coldkey_swap_total() { ); }); } -// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test swap_coldkey -- test_swap_senate_member --exact --nocapture -#[test] -fn test_swap_senate_member() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let non_member_hotkey = U256::from(3); - let mut weight = Weight::zero(); - - // Setup: Add old_hotkey as a Senate member - assert_ok!(SenateMembers::add_member( - RawOrigin::Root.into(), - old_hotkey - )); - - // Test 1: Successful swap - assert_ok!(SubtensorModule::swap_senate_member( - &old_hotkey, - &new_hotkey, - &mut weight - )); - assert!(Senate::is_member(&new_hotkey)); - assert!(!Senate::is_member(&old_hotkey)); - - // Verify weight update - let expected_weight = ::DbWeight::get().reads_writes(2, 2); - assert_eq!(weight, expected_weight); - - // Reset weight for next test - weight = Weight::zero(); - - // Test 2: Swap with non-member (should not change anything) - assert_ok!(SubtensorModule::swap_senate_member( - &non_member_hotkey, - &new_hotkey, - &mut weight - )); - assert!(Senate::is_member(&new_hotkey)); - assert!(!Senate::is_member(&non_member_hotkey)); - - // Verify weight update (should only have read operations) - let expected_weight = ::DbWeight::get().reads(1); - assert_eq!(weight, expected_weight); - }); -} // SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --package pallet-subtensor --lib -- tests::swap_coldkey::test_coldkey_delegations --exact --show-output #[test] diff --git a/pallets/subtensor/src/tests/swap_hotkey.rs b/pallets/subtensor/src/tests/swap_hotkey.rs index a31c238e8a..be67859f5f 100644 --- a/pallets/subtensor/src/tests/swap_hotkey.rs +++ b/pallets/subtensor/src/tests/swap_hotkey.rs @@ -120,34 +120,6 @@ fn test_swap_total_hotkey_stake() { }); } -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_senate_members --exact --nocapture -#[test] -fn test_swap_senate_members() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let mut weight = Weight::zero(); - - assert_ok!(SenateMembers::add_member(RuntimeOrigin::root(), old_hotkey)); - let members = SenateMembers::members(); - assert!(members.contains(&old_hotkey)); - assert!(!members.contains(&new_hotkey)); - - assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( - &old_hotkey, - &new_hotkey, - &coldkey, - &mut weight - )); - - // Assert that the old_hotkey is no longer a member and new_hotkey is now a member - let members = SenateMembers::members(); - assert!(!members.contains(&old_hotkey)); - assert!(members.contains(&new_hotkey)); - }); -} - // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_delegates --exact --nocapture #[test] fn test_swap_delegates() { diff --git a/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs b/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs index 740f3e97fa..219bfe1e37 100644 --- a/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs +++ b/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs @@ -122,33 +122,6 @@ fn test_swap_total_hotkey_stake() { }); } -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_senate_members --exact --nocapture -#[test] -fn test_swap_senate_members() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - - let netuid = add_dynamic_network(&old_hotkey, &coldkey); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); - - assert_ok!(SenateMembers::add_member(RuntimeOrigin::root(), old_hotkey)); - - System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); - assert_ok!(SubtensorModule::do_swap_hotkey( - RuntimeOrigin::signed(coldkey), - &old_hotkey, - &new_hotkey, - Some(netuid) - )); - - let members = SenateMembers::members(); - assert!(members.contains(&old_hotkey)); - assert!(!members.contains(&new_hotkey)); - }); -} - // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_delegates --exact --nocapture #[test] fn test_swap_delegates() { diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index a4d4755e5d..bb51eccd01 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -779,25 +779,6 @@ impl Pallet { Self::set_rao_recycled(netuid, rao_recycled); } - pub fn set_senate_required_stake_perc(required_percent: u64) { - SenateRequiredStakePercentage::::put(required_percent); - } - - pub fn is_senate_member(hotkey: &T::AccountId) -> bool { - T::SenateMembers::is_member(hotkey) - } - - pub fn do_set_senate_required_stake_perc( - origin: T::RuntimeOrigin, - required_percent: u64, - ) -> DispatchResult { - ensure_root(origin)?; - - Self::set_senate_required_stake_perc(required_percent); - Self::deposit_event(Event::SenateRequiredStakePercentSet(required_percent)); - Ok(()) - } - pub fn is_subnet_owner(address: &T::AccountId) -> bool { SubnetOwner::::iter_values().any(|owner| *address == owner) } diff --git a/pallets/transaction-fee/src/tests/mock.rs b/pallets/transaction-fee/src/tests/mock.rs index de5d13e346..8e48c2e4fc 100644 --- a/pallets/transaction-fee/src/tests/mock.rs +++ b/pallets/transaction-fee/src/tests/mock.rs @@ -9,7 +9,7 @@ use frame_support::{ weights::IdentityFee, }; use frame_system::{ - self as system, EnsureNever, EnsureRoot, RawOrigin, limits, offchain::CreateTransactionBase, + self as system, EnsureRoot, RawOrigin, limits, offchain::CreateTransactionBase, }; pub use pallet_subtensor::*; pub use sp_core::U256; @@ -193,7 +193,6 @@ parameter_types! { pub const InitialMinDifficulty: u64 = 1; pub const InitialMaxDifficulty: u64 = u64::MAX; pub const InitialRAORecycledForRegistration: u64 = 0; - pub const InitialSenateRequiredStakePercentage: u64 = 2; // 2 percent of total stake pub const InitialNetworkImmunityPeriod: u64 = 7200 * 7; pub const InitialNetworkMinLockCost: u64 = 100_000_000_000; pub const InitialSubnetOwnerCut: u16 = 0; // 0%. 100% of rewards go to validators + miners. @@ -225,9 +224,6 @@ impl pallet_subtensor::Config for Test { type Currency = Balances; type InitialIssuance = InitialIssuance; type SudoRuntimeCall = RuntimeCall; - type CouncilOrigin = EnsureNever; - type SenateMembers = (); - type TriumvirateInterface = (); type Scheduler = Scheduler; type InitialMinAllowedWeights = InitialMinAllowedWeights; type InitialEmissionValue = InitialEmissionValue; @@ -270,7 +266,6 @@ impl pallet_subtensor::Config for Test { type MinBurnUpperBound = MinBurnUpperBound; type MaxBurnLowerBound = MaxBurnLowerBound; type InitialRAORecycledForRegistration = InitialRAORecycledForRegistration; - type InitialSenateRequiredStakePercentage = InitialSenateRequiredStakePercentage; type InitialNetworkImmunityPeriod = InitialNetworkImmunityPeriod; type InitialNetworkMinLockCost = InitialNetworkMinLockCost; type InitialSubnetOwnerCut = InitialSubnetOwnerCut; diff --git a/pallets/utility/Cargo.toml b/pallets/utility/Cargo.toml index a61327e4b7..5bb38fcf82 100644 --- a/pallets/utility/Cargo.toml +++ b/pallets/utility/Cargo.toml @@ -25,7 +25,6 @@ subtensor-macros.workspace = true [dev-dependencies] pallet-balances = { workspace = true, default-features = true } -pallet-subtensor-collective = { workspace = true, default-features = true } pallet-root-testing = { workspace = true, default-features = true } pallet-timestamp = { workspace = true, default-features = true } sp-core = { workspace = true, default-features = true } @@ -47,7 +46,6 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "pallet-subtensor-collective/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] @@ -55,7 +53,6 @@ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "pallet-subtensor-collective/try-runtime", "pallet-root-testing/try-runtime", "pallet-timestamp/try-runtime", "sp-runtime/try-runtime", diff --git a/pallets/utility/src/tests.rs b/pallets/utility/src/tests.rs index 8a3b198c4b..8b0a9274c2 100644 --- a/pallets/utility/src/tests.rs +++ b/pallets/utility/src/tests.rs @@ -34,11 +34,9 @@ use frame_support::{ traits::{ConstU64, Contains}, weights::Weight, }; -use pallet_subtensor_collective as pallet_collective; -use pallet_subtensor_collective::{EnsureProportionAtLeast, Instance1}; use sp_runtime::{ BuildStorage, DispatchError, TokenError, - traits::{BadOrigin, BlakeTwo256, Dispatchable, Hash}, + traits::{BadOrigin, Dispatchable}, }; type BlockNumber = u64; @@ -93,40 +91,6 @@ pub mod example { } } -mod mock_democracy { - pub use pallet::*; - #[frame_support::pallet(dev_mode)] - 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 + Sized { - type ExternalMajorityOrigin: EnsureOrigin; - } - - #[pallet::call] - impl Pallet { - #[pallet::call_index(3)] - #[pallet::weight(0)] - pub fn external_propose_majority(origin: OriginFor) -> DispatchResult { - T::ExternalMajorityOrigin::ensure_origin(origin)?; - Self::deposit_event(Event::::ExternalProposed); - Ok(()) - } - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - ExternalProposed, - } - } -} - type Block = frame_system::mocking::MockBlock; frame_support::construct_runtime!( @@ -136,10 +100,8 @@ frame_support::construct_runtime!( Timestamp: pallet_timestamp = 2, Balances: pallet_balances = 3, RootTesting: pallet_root_testing = 4, - Council: pallet_collective:: = 5, Utility: utility = 6, Example: example = 7, - Democracy: mock_democracy = 8, } ); @@ -182,42 +144,6 @@ parameter_types! { pub MaxProposalWeight: Weight = BlockWeights::get().max_block.saturating_div(2); } -pub struct MemberProposals; -impl pallet_collective::CanPropose for MemberProposals { - fn can_propose(who: &u64) -> bool { - [1, 2, 3].contains(who) - } -} - -pub struct MemberVotes; -impl pallet_collective::CanVote for MemberVotes { - fn can_vote(who: &u64) -> bool { - [1, 2, 3].contains(who) - } -} - -pub struct StoredVotingMembers; -impl pallet_collective::GetVotingMembers for StoredVotingMembers { - fn get_count() -> u32 { - 3 - } -} - -type CouncilCollective = pallet_collective::Instance1; -impl pallet_collective::Config for Test { - type RuntimeOrigin = RuntimeOrigin; - type Proposal = RuntimeCall; - type MotionDuration = MotionDuration; - type MaxProposals = MaxProposals; - type MaxMembers = MaxMembers; - type DefaultVote = pallet_collective::PrimeDefaultVote; - type WeightInfo = (); - type SetMembersOrigin = frame_system::EnsureRoot; - type CanPropose = MemberProposals; - type CanVote = MemberVotes; - type GetVotingMembers = StoredVotingMembers; -} - impl example::Config for Test {} pub struct TestBaseCallFilter; @@ -231,15 +157,11 @@ impl Contains for TestBaseCallFilter { RuntimeCall::System(frame_system::Call::remark { .. }) => true, // For tests RuntimeCall::Example(_) => true, - // For council origin tests. - RuntimeCall::Democracy(_) => true, _ => false, } } } -impl mock_democracy::Config for Test { - type ExternalMajorityOrigin = EnsureProportionAtLeast; -} + impl Config for Test { type RuntimeCall = RuntimeCall; type PalletsOrigin = OriginCaller; @@ -265,13 +187,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities { .assimilate_storage(&mut t) .unwrap(); - pallet_collective::GenesisConfig:: { - members: vec![1, 2, 3], - phantom: Default::default(), - } - .assimilate_storage(&mut t) - .unwrap(); - let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); ext @@ -897,97 +812,6 @@ fn batch_all_doesnt_work_with_inherents() { }) } -#[test] -fn batch_works_with_council_origin() { - new_test_ext().execute_with(|| { - let proposal = RuntimeCall::Utility(UtilityCall::batch { - calls: vec![RuntimeCall::Democracy( - mock_democracy::Call::external_propose_majority {}, - )], - }); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash = BlakeTwo256::hash_of(&proposal); - - assert_ok!(Council::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - 3, - )); - - assert_ok!(Council::vote(RuntimeOrigin::signed(1), hash, 0, true)); - assert_ok!(Council::vote(RuntimeOrigin::signed(2), hash, 0, true)); - assert_ok!(Council::vote(RuntimeOrigin::signed(3), hash, 0, true)); - - System::set_block_number(4); - - assert_ok!(Council::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - - System::assert_last_event(RuntimeEvent::Council(pallet_collective::Event::Executed { - proposal_hash: hash, - result: Ok(()), - })); - }) -} - -#[test] -fn force_batch_works_with_council_origin() { - new_test_ext().execute_with(|| { - let proposal = RuntimeCall::Utility(UtilityCall::force_batch { - calls: vec![RuntimeCall::Democracy( - mock_democracy::Call::external_propose_majority {}, - )], - }); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().call_weight; - let hash = BlakeTwo256::hash_of(&proposal); - - assert_ok!(Council::propose( - RuntimeOrigin::signed(1), - Box::new(proposal.clone()), - proposal_len, - 3, - )); - - assert_ok!(Council::vote(RuntimeOrigin::signed(1), hash, 0, true)); - assert_ok!(Council::vote(RuntimeOrigin::signed(2), hash, 0, true)); - assert_ok!(Council::vote(RuntimeOrigin::signed(3), hash, 0, true)); - - System::set_block_number(4); - assert_ok!(Council::close( - RuntimeOrigin::root(), - hash, - 0, - proposal_weight, - proposal_len - )); - - System::assert_last_event(RuntimeEvent::Council(pallet_collective::Event::Executed { - proposal_hash: hash, - result: Ok(()), - })); - }) -} - -#[test] -fn batch_all_works_with_council_origin() { - new_test_ext().execute_with(|| { - assert_ok!(Utility::batch_all( - RuntimeOrigin::from(pallet_collective::RawOrigin::Members(3, 3)), - vec![RuntimeCall::Democracy( - mock_democracy::Call::external_propose_majority {} - )] - )); - }) -} - #[test] fn with_weight_works() { new_test_ext().execute_with(|| { diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 0c4353d630..b5fa4bf83b 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -64,10 +64,6 @@ pallet-sudo.workspace = true pallet-admin-utils.workspace = true -# Used for sudo decentralization -pallet-subtensor-collective.workspace = true -pallet-membership.workspace = true - # Multisig pallet-multisig.workspace = true @@ -205,8 +201,6 @@ std = [ "sp-transaction-pool/std", "sp-version/std", "substrate-wasm-builder", - "pallet-subtensor-collective/std", - "pallet-membership/std", "pallet-registry/std", "pallet-admin-utils/std", "subtensor-custom-rpc-runtime-api/std", @@ -283,8 +277,6 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "pallet-safe-mode/runtime-benchmarks", "pallet-subtensor/runtime-benchmarks", - "pallet-subtensor-collective/runtime-benchmarks", - "pallet-membership/runtime-benchmarks", "pallet-subtensor-proxy/runtime-benchmarks", "pallet-registry/runtime-benchmarks", "pallet-commitments/runtime-benchmarks", @@ -331,8 +323,6 @@ try-runtime = [ "pallet-subtensor-utility/try-runtime", "pallet-safe-mode/try-runtime", "pallet-subtensor/try-runtime", - "pallet-subtensor-collective/try-runtime", - "pallet-membership/try-runtime", "pallet-subtensor-proxy/try-runtime", "pallet-multisig/try-runtime", "pallet-scheduler/try-runtime", diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 5654def01c..f3dba0eb41 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -20,12 +20,12 @@ use codec::{Compact, Decode, Encode}; use ethereum::AuthorizationList; use frame_support::{ PalletId, - dispatch::{DispatchResult, DispatchResultWithPostInfo}, + dispatch::DispatchResult, genesis_builder_helper::{build_state, get_preset}, pallet_prelude::Get, traits::{Contains, InsideBoth, LinearStoragePrice, fungible::HoldConsideration}, }; -use frame_system::{EnsureNever, EnsureRoot, EnsureRootWithSuccess, RawOrigin}; +use frame_system::{EnsureRoot, EnsureRootWithSuccess}; use pallet_commitments::{CanCommit, OnMetadataCommitment}; use pallet_grandpa::{AuthorityId as GrandpaId, fg_primitives}; use pallet_registry::CanRegisterIdentity; @@ -38,7 +38,7 @@ use pallet_subtensor::rpc_info::{ stake_info::StakeInfo, subnet_info::{SubnetHyperparams, SubnetHyperparamsV2, SubnetInfo, SubnetInfov2}, }; -use pallet_subtensor_collective as pallet_collective; +use pallet_subtensor::{CommitmentsInterface, ProxyInterface}; use pallet_subtensor_proxy as pallet_proxy; use pallet_subtensor_swap_runtime_api::SimSwapResult; use pallet_subtensor_utility as pallet_utility; @@ -175,9 +175,6 @@ impl frame_system::offchain::CreateSignedTransaction pub use pallet_scheduler; pub use pallet_subtensor; -// Member type for membership -type MemberCount = u32; - // Method used to calculate the fee of an extrinsic pub const fn deposit(items: u32, bytes: u32) -> Balance { pub const ITEMS_FEE: Balance = 2_000 * 10_000; @@ -489,149 +486,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; } -// Configure collective pallet for council -parameter_types! { - pub const CouncilMotionDuration: BlockNumber = 12 * HOURS; - pub const CouncilMaxProposals: u32 = 10; - pub const CouncilMaxMembers: u32 = 3; -} - -// Configure collective pallet for Senate -parameter_types! { - pub const SenateMaxMembers: u32 = 12; -} - -use pallet_collective::{CanPropose, CanVote, GetVotingMembers}; -pub struct CanProposeToTriumvirate; -impl CanPropose for CanProposeToTriumvirate { - fn can_propose(account: &AccountId) -> bool { - Triumvirate::is_member(account) - } -} - -pub struct CanVoteToTriumvirate; -impl CanVote for CanVoteToTriumvirate { - fn can_vote(_: &AccountId) -> bool { - //Senate::is_member(account) - false // Disable voting from pallet_collective::vote - } -} - -use pallet_subtensor::{ - CollectiveInterface, CommitmentsInterface, MemberManagement, ProxyInterface, -}; -pub struct ManageSenateMembers; -impl MemberManagement for ManageSenateMembers { - fn add_member(account: &AccountId) -> DispatchResultWithPostInfo { - let who = Address::Id(account.clone()); - SenateMembers::add_member(RawOrigin::Root.into(), who) - } - - fn remove_member(account: &AccountId) -> DispatchResultWithPostInfo { - let who = Address::Id(account.clone()); - SenateMembers::remove_member(RawOrigin::Root.into(), who) - } - - fn swap_member(rm: &AccountId, add: &AccountId) -> DispatchResultWithPostInfo { - let remove = Address::Id(rm.clone()); - let add = Address::Id(add.clone()); - - Triumvirate::remove_votes(rm)?; - SenateMembers::swap_member(RawOrigin::Root.into(), remove, add) - } - - fn is_member(account: &AccountId) -> bool { - SenateMembers::members().contains(account) - } - - fn members() -> Vec { - SenateMembers::members().into() - } - - fn max_members() -> u32 { - SenateMaxMembers::get() - } -} - -pub struct GetSenateMemberCount; -impl GetVotingMembers for GetSenateMemberCount { - fn get_count() -> MemberCount { - SenateMembers::members().len() as u32 - } -} -impl Get for GetSenateMemberCount { - fn get() -> MemberCount { - SenateMaxMembers::get() - } -} - -pub struct TriumvirateVotes; -impl CollectiveInterface for TriumvirateVotes { - fn remove_votes(hotkey: &AccountId) -> Result { - Triumvirate::remove_votes(hotkey) - } - - fn add_vote( - hotkey: &AccountId, - proposal: Hash, - index: u32, - approve: bool, - ) -> Result { - Triumvirate::do_vote(hotkey.clone(), proposal, index, approve) - } -} - -type EnsureMajoritySenate = - pallet_collective::EnsureProportionMoreThan; - -// We call pallet_collective TriumvirateCollective -type TriumvirateCollective = pallet_collective::Instance1; -impl pallet_collective::Config for Runtime { - type RuntimeOrigin = RuntimeOrigin; - type Proposal = RuntimeCall; - type MotionDuration = CouncilMotionDuration; - type MaxProposals = CouncilMaxProposals; - type MaxMembers = GetSenateMemberCount; - type DefaultVote = pallet_collective::PrimeDefaultVote; - type WeightInfo = pallet_collective::weights::SubstrateWeight; - type SetMembersOrigin = EnsureNever; - type CanPropose = CanProposeToTriumvirate; - type CanVote = CanVoteToTriumvirate; - type GetVotingMembers = GetSenateMemberCount; -} - -// We call council members Triumvirate -#[allow(dead_code)] -type TriumvirateMembership = pallet_membership::Instance1; -impl pallet_membership::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type AddOrigin = EnsureRoot; - type RemoveOrigin = EnsureRoot; - type SwapOrigin = EnsureRoot; - type ResetOrigin = EnsureRoot; - type PrimeOrigin = EnsureRoot; - type MembershipInitialized = Triumvirate; - type MembershipChanged = Triumvirate; - type MaxMembers = CouncilMaxMembers; - type WeightInfo = pallet_membership::weights::SubstrateWeight; -} - -// We call our top K delegates membership Senate -#[allow(dead_code)] -type SenateMembership = pallet_membership::Instance2; -impl pallet_membership::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type AddOrigin = EnsureRoot; - type RemoveOrigin = EnsureRoot; - type SwapOrigin = EnsureRoot; - type ResetOrigin = EnsureRoot; - type PrimeOrigin = EnsureRoot; - type MembershipInitialized = (); - type MembershipChanged = (); - type MaxMembers = SenateMaxMembers; - type WeightInfo = pallet_membership::weights::SubstrateWeight; -} - impl pallet_sudo::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; @@ -759,20 +613,11 @@ impl InstanceFilter for ProxyType { RuntimeCall::SubtensorModule(pallet_subtensor::Call::dissolve_network { .. }) | RuntimeCall::SubtensorModule(pallet_subtensor::Call::root_register { .. }) | RuntimeCall::SubtensorModule(pallet_subtensor::Call::burned_register { .. }) - | RuntimeCall::Triumvirate(..) | RuntimeCall::Sudo(..) ), - ProxyType::Triumvirate => matches!( - c, - RuntimeCall::Triumvirate(..) | RuntimeCall::TriumvirateMembers(..) - ), - ProxyType::Senate => matches!(c, RuntimeCall::SenateMembers(..)), - ProxyType::Governance => matches!( - c, - RuntimeCall::SenateMembers(..) - | RuntimeCall::Triumvirate(..) - | RuntimeCall::TriumvirateMembers(..) - ), + ProxyType::Triumvirate => false, // deprecated + ProxyType::Senate => false, // deprecated + ProxyType::Governance => false, // deprecated ProxyType::Staking => matches!( c, RuntimeCall::SubtensorModule(pallet_subtensor::Call::add_stake { .. }) @@ -892,7 +737,6 @@ impl InstanceFilter for ProxyType { // NonTransfer is NOT a superset of Transfer or SmallTransfer !matches!(o, ProxyType::Transfer | ProxyType::SmallTransfer) } - (ProxyType::Governance, ProxyType::Triumvirate | ProxyType::Senate) => true, (ProxyType::Transfer, ProxyType::SmallTransfer) => true, _ => false, } @@ -964,21 +808,6 @@ impl PrivilegeCmp for OriginPrivilegeCmp { match (left, right) { // Root is greater than anything. (OriginCaller::system(frame_system::RawOrigin::Root), _) => Some(Ordering::Greater), - // Check which one has more yes votes. - ( - OriginCaller::Triumvirate(pallet_collective::RawOrigin::Members( - l_yes_votes, - l_count, - )), - OriginCaller::Triumvirate(pallet_collective::RawOrigin::Members( - r_yes_votes, - r_count, - )), // Equivalent to (l_yes_votes / l_count).cmp(&(r_yes_votes / r_count)) - ) => Some( - l_yes_votes - .saturating_mul(*r_count) - .cmp(&r_yes_votes.saturating_mul(*l_count)), - ), // For every other origin we don't care, as they are not used for `ScheduleOrigin`. _ => None, } @@ -1185,7 +1014,7 @@ parameter_types! { pub const SubtensorInitialTxDelegateTakeRateLimit: u64 = 216000; // 30 days at 12 seconds per block pub const SubtensorInitialTxChildKeyTakeRateLimit: u64 = INITIAL_CHILDKEY_TAKE_RATELIMIT; pub const SubtensorInitialRAORecycledForRegistration: u64 = 0; // 0 rao - pub const SubtensorInitialSenateRequiredStakePercentage: u64 = 1; // 1 percent of total stake + pub const SubtensorInitialRequiredStakePercentage: u64 = 1; // 1 percent of total stake pub const SubtensorInitialNetworkImmunity: u64 = 1_296_000; pub const SubtensorInitialMinAllowedUids: u16 = 64; pub const SubtensorInitialMinLockCost: u64 = 1_000_000_000_000; // 1000 TAO @@ -1217,9 +1046,6 @@ impl pallet_subtensor::Config for Runtime { type RuntimeCall = RuntimeCall; type SudoRuntimeCall = RuntimeCall; type Currency = Balances; - type CouncilOrigin = EnsureMajoritySenate; - type SenateMembers = ManageSenateMembers; - type TriumvirateInterface = TriumvirateVotes; type Scheduler = Scheduler; type InitialRho = SubtensorInitialRho; type InitialAlphaSigmoidSteepness = SubtensorInitialAlphaSigmoidSteepness; @@ -1263,7 +1089,6 @@ impl pallet_subtensor::Config for Runtime { type InitialTxChildKeyTakeRateLimit = SubtensorInitialTxChildKeyTakeRateLimit; type InitialMaxChildKeyTake = SubtensorInitialMaxChildKeyTake; type InitialRAORecycledForRegistration = SubtensorInitialRAORecycledForRegistration; - type InitialSenateRequiredStakePercentage = SubtensorInitialSenateRequiredStakePercentage; type InitialNetworkImmunityPeriod = SubtensorInitialNetworkImmunity; type InitialNetworkMinLockCost = SubtensorInitialMinLockCost; type InitialNetworkLockReductionInterval = SubtensorInitialNetworkLockReductionInterval; @@ -1637,9 +1462,9 @@ construct_runtime!( Balances: pallet_balances = 5, TransactionPayment: pallet_transaction_payment = 6, SubtensorModule: pallet_subtensor = 7, - Triumvirate: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 8, - TriumvirateMembers: pallet_membership::::{Pallet, Call, Storage, Event, Config} = 9, - SenateMembers: pallet_membership::::{Pallet, Call, Storage, Event, Config} = 10, + // pallet_collective:: (triumvirate) was 8 + // pallet_membership:: (triumvirate members) was 9 + // pallet_membership:: (senate members) was 10 Utility: pallet_utility = 11, Sudo: pallet_sudo = 12, Multisig: pallet_multisig = 13, @@ -1685,12 +1510,23 @@ pub type TransactionExtensions = ( frame_metadata_hash_extension::CheckMetadataHash, ); +parameter_types! { + pub const TriumviratePalletStr: &'static str = "Triumvirate"; + pub const TriumvirateMembersPalletStr: &'static str = "TriumvirateMembers"; + pub const SenateMembersPalletStr: &'static str = "SenateMembers"; +} + type Migrations = ( // Leave this migration in the runtime, so every runtime upgrade tiny rounding errors (fractions of fractions // of a cent) are cleaned up. These tiny rounding errors occur due to floating point coversion. pallet_subtensor::migrations::migrate_init_total_issuance::initialise_total_issuance::Migration< Runtime, >, + + // Remove storage from removed governance pallets + frame_support::migrations::RemovePallet, + frame_support::migrations::RemovePallet, + frame_support::migrations::RemovePallet, ); // Unchecked extrinsic type as expected by this runtime. diff --git a/runtime/tests/pallet_proxy.rs b/runtime/tests/pallet_proxy.rs index e2a9fea415..016c8192bc 100644 --- a/runtime/tests/pallet_proxy.rs +++ b/runtime/tests/pallet_proxy.rs @@ -1,12 +1,10 @@ #![allow(clippy::unwrap_used)] -use codec::Encode; -use frame_support::{BoundedVec, assert_ok, traits::InstanceFilter}; +use frame_support::{assert_ok, traits::InstanceFilter}; use node_subtensor_runtime::{ BalancesCall, BuildStorage, Proxy, Runtime, RuntimeCall, RuntimeEvent, RuntimeGenesisConfig, RuntimeOrigin, SubtensorModule, System, SystemCall, }; -use pallet_subtensor_collective as pallet_collective; use pallet_subtensor_proxy as pallet_proxy; use subtensor_runtime_common::{AccountId, NetUid, ProxyType}; @@ -28,15 +26,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities { ], dev_accounts: None, }, - - triumvirate: pallet_collective::GenesisConfig { - members: vec![AccountId::from(ACCOUNT)], - phantom: Default::default(), - }, - senate_members: pallet_membership::GenesisConfig { - members: BoundedVec::try_from(vec![AccountId::from(ACCOUNT)]).unwrap(), - phantom: Default::default(), - }, ..Default::default() } .build_storage() @@ -105,18 +94,6 @@ fn call_update_symbol() -> RuntimeCall { }) } -// critical call for Subtensor -fn call_propose() -> RuntimeCall { - let proposal = call_remark(); - let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - - RuntimeCall::Triumvirate(pallet_collective::Call::propose { - proposal: Box::new(call_remark()), - length_bound: proposal_len, - duration: 100_000_000_u32, - }) -} - // critical call for Subtensor fn call_root_register() -> RuntimeCall { RuntimeCall::SubtensorModule(pallet_subtensor::Call::root_register { @@ -124,20 +101,6 @@ fn call_root_register() -> RuntimeCall { }) } -// triumvirate call -fn call_triumvirate() -> RuntimeCall { - RuntimeCall::TriumvirateMembers(pallet_membership::Call::change_key { - new: AccountId::from(ACCOUNT).into(), - }) -} - -// senate call -fn call_senate() -> RuntimeCall { - RuntimeCall::SenateMembers(pallet_membership::Call::change_key { - new: AccountId::from(ACCOUNT).into(), - }) -} - // staking call fn call_add_stake() -> RuntimeCall { let netuid = NetUid::from(1); @@ -205,10 +168,7 @@ fn test_proxy_pallet() { ProxyType::Owner, ProxyType::NonCritical, ProxyType::NonTransfer, - ProxyType::Senate, ProxyType::NonFungibile, - ProxyType::Triumvirate, - ProxyType::Governance, ProxyType::Staking, ProxyType::Registration, ]; @@ -217,10 +177,7 @@ fn test_proxy_pallet() { call_transfer, call_remark, call_owner_util, - call_propose, call_root_register, - call_triumvirate, - call_senate, call_add_stake, call_register, ]; diff --git a/support/linting/src/pallet_index.rs b/support/linting/src/pallet_index.rs index 069c96f628..e14617be24 100644 --- a/support/linting/src/pallet_index.rs +++ b/support/linting/src/pallet_index.rs @@ -168,9 +168,6 @@ mod tests { Balances : pallet_balances = 5, TransactionPayment : pallet_transaction_payment = 6, SubtensorModule : pallet_subtensor = 7, - Triumvirate : pallet_subtensor_collective::::{ Pallet, Call, Storage, Origin, Event, Config } = 8, - TriumvirateMembers : pallet_membership::::{ Pallet, Call, Storage, Event, Config } = 9, - SenateMembers : pallet_membership::::{ Pallet, Call, Storage, Event, Config } = 10, Utility : pallet_subtensor_utility = 11, Sudo : pallet_sudo = 12, Multisig : pallet_multisig = 13, @@ -195,10 +192,6 @@ mod tests { pub enum Test { System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Config, Storage, Event}, - Triumvirate: pallet_subtensor_collective::::{Pallet, Call, Storage, Origin, Event, Config}, - TriumvirateMembers: pallet_membership::::{Pallet, Call, Storage, Event, Config}, - Senate: pallet_subtensor_collective::::{Pallet, Call, Storage, Origin, Event, Config}, - SenateMembers: pallet_membership::::{Pallet, Call, Storage, Event, Config}, SubtensorModule: pallet_subtensor::{Pallet, Call, Storage, Event}, Utility: pallet_utility::{Pallet, Call, Storage, Event}, Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event}, @@ -284,10 +277,6 @@ mod tests { pub enum Test { System: frame_system::{Pallet, Call, Config, Storage, Event} = 1, Balances: pallet_balances::{Pallet, Call, Config, Storage, Event}, - Triumvirate: pallet_subtensor_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 3, - TriumvirateMembers: pallet_membership::::{Pallet, Call, Storage, Event, Config} = 4, - Senate: pallet_subtensor_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 5, - SenateMembers: pallet_membership::::{Pallet, Call, Storage, Event, Config} = 6, SubtensorModule: pallet_subtensor::{Pallet, Call, Storage, Event} = 7, Utility: pallet_utility::{Pallet, Call, Storage, Event} = 8, Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event} = 9, diff --git a/support/procedural-fork/src/runtime/parse/pallet_decl.rs b/support/procedural-fork/src/runtime/parse/pallet_decl.rs index fab826eee7..ddc9a7ffe7 100644 --- a/support/procedural-fork/src/runtime/parse/pallet_decl.rs +++ b/support/procedural-fork/src/runtime/parse/pallet_decl.rs @@ -29,8 +29,7 @@ pub struct PalletDeclaration { /// The runtime parameter of the pallet, e.g. `Runtime` in /// `pub type System = frame_system::Pallet`. pub runtime_param: Option, - /// The instance of the pallet, e.g. `Instance1` in `pub type Council = - /// pallet_collective`. + /// The instance of the pallet, e.g. `Instance1` in `pub type Council = pallet_collective`. pub instance: Option, } diff --git a/support/tools/src/bump_version.rs b/support/tools/src/bump_version.rs index a16293c304..24e267f234 100644 --- a/support/tools/src/bump_version.rs +++ b/support/tools/src/bump_version.rs @@ -7,10 +7,9 @@ use std::{ }; use toml_edit::{DocumentMut, Item, Value}; -const TOML_PATHS: [&str; 9] = [ +const TOML_PATHS: [&str; 8] = [ "support/macros", "pallets/commitments", - "pallets/collective", "pallets/registry", "pallets/subtensor", "pallets/subtensor/runtime-api", From 514b354bb6a44ebd0d7d6c4e904f9a22ff83bc88 Mon Sep 17 00:00:00 2001 From: Loris Moulin Date: Tue, 14 Oct 2025 19:15:44 -0300 Subject: [PATCH 2/3] cargo fmt --- pallets/subtensor/src/migrations/mod.rs | 2 +- runtime/src/lib.rs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index b41a66097a..db0b290661 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -120,4 +120,4 @@ pub(crate) fn remove_prefix(module: &str, old_map: &str, weight: &mut log::info!("Removed {removed_entries_count:?} entries from {old_map:?} map."); *weight = (*weight).saturating_add(T::DbWeight::get().writes(removed_entries_count)); -} \ No newline at end of file +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index f3dba0eb41..389a01a983 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -616,8 +616,8 @@ impl InstanceFilter for ProxyType { | RuntimeCall::Sudo(..) ), ProxyType::Triumvirate => false, // deprecated - ProxyType::Senate => false, // deprecated - ProxyType::Governance => false, // deprecated + ProxyType::Senate => false, // deprecated + ProxyType::Governance => false, // deprecated ProxyType::Staking => matches!( c, RuntimeCall::SubtensorModule(pallet_subtensor::Call::add_stake { .. }) @@ -1522,7 +1522,6 @@ type Migrations = ( pallet_subtensor::migrations::migrate_init_total_issuance::initialise_total_issuance::Migration< Runtime, >, - // Remove storage from removed governance pallets frame_support::migrations::RemovePallet, frame_support::migrations::RemovePallet, From 87e344996ab67224728a1a59cbe501e519e9dd06 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Oct 2025 20:32:26 +0000 Subject: [PATCH 3/3] auto-update benchmark weights --- pallets/subtensor/src/macros/dispatches.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index ab778ea109..fd63d5bdf1 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -1029,8 +1029,8 @@ mod dispatches { /// Register the hotkey to root network #[pallet::call_index(62)] #[pallet::weight((Weight::from_parts(135_900_000, 0) - .saturating_add(T::DbWeight::get().reads(24_u64)) - .saturating_add(T::DbWeight::get().writes(20)), DispatchClass::Normal, Pays::Yes))] + .saturating_add(T::DbWeight::get().reads(22_u64)) + .saturating_add(T::DbWeight::get().writes(19_u64)), DispatchClass::Normal, Pays::Yes))] pub fn root_register(origin: OriginFor, hotkey: T::AccountId) -> DispatchResult { Self::do_root_register(origin, hotkey) } @@ -1051,7 +1051,7 @@ mod dispatches { /// The extrinsic for user to change its hotkey in subnet or all subnets. #[pallet::call_index(70)] #[pallet::weight((Weight::from_parts(275_300_000, 0) - .saturating_add(T::DbWeight::get().reads(53_u64)) + .saturating_add(T::DbWeight::get().reads(52_u64)) .saturating_add(T::DbWeight::get().writes(37)), DispatchClass::Normal, Pays::No))] pub fn swap_hotkey( origin: OriginFor,