From e37fe07d876914369be2ec4f5374261c03d2dc3b Mon Sep 17 00:00:00 2001 From: Daniel Olano Date: Sat, 28 Oct 2023 16:15:07 +0200 Subject: [PATCH] Change TracksInfo::tracks to return an iterator Using an iterator instead of a static slice allows for more flexible implementations of `TracksInfo` that can use the chain storage without compromising a lot on the performance/memory penalty if we were to return an owned `Vec` instead. --- .../src/ambassador/tracks.rs | 286 ++++++++++ .../src/fellowship/tracks.rs | 536 ++++++++++++++++++ .../src/ambassador/tracks.rs | 140 ++--- .../src/fellowship/tracks.rs | 266 ++++----- .../rococo/src/governance/fellowship.rs | 116 ++-- .../runtime/rococo/src/governance/tracks.rs | 162 +++--- .../runtime/westend/src/governance/tracks.rs | 162 +++--- substrate/bin/node/runtime/src/lib.rs | 86 +-- substrate/frame/referenda/src/benchmarking.rs | 3 +- substrate/frame/referenda/src/lib.rs | 99 ++-- substrate/frame/referenda/src/mock.rs | 31 +- substrate/frame/referenda/src/tests.rs | 5 +- substrate/frame/referenda/src/types.rs | 119 ++-- 13 files changed, 1451 insertions(+), 560 deletions(-) create mode 100644 cumulus/parachains/runtimes/collectives/collectives-polkadot/src/ambassador/tracks.rs create mode 100644 cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/tracks.rs diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/ambassador/tracks.rs b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/ambassador/tracks.rs new file mode 100644 index 0000000000000..faef99a496499 --- /dev/null +++ b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/ambassador/tracks.rs @@ -0,0 +1,286 @@ +// Copyright (C) 2022 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. + +//! The Ambassador Program's referenda voting tracks. + +use super::Origin; +use crate::{Balance, BlockNumber, RuntimeOrigin, DAYS, DOLLARS, HOURS}; +use pallet_referenda::{StaticTracksIter, Track}; +use sp_runtime::{str_array as s, Perbill}; +use sp_std::borrow::Cow::Borrowed; + +/// Referendum `TrackId` type. +pub type TrackId = u16; + +/// Referendum track IDs. +pub mod constants { + use super::TrackId; + + pub const AMBASSADOR_TIER_1: TrackId = 1; + pub const AMBASSADOR_TIER_2: TrackId = 2; + pub const SENIOR_AMBASSADOR_TIER_3: TrackId = 3; + pub const SENIOR_AMBASSADOR_TIER_4: TrackId = 4; + pub const HEAD_AMBASSADOR_TIER_5: TrackId = 5; + pub const HEAD_AMBASSADOR_TIER_6: TrackId = 6; + pub const HEAD_AMBASSADOR_TIER_7: TrackId = 7; + pub const MASTER_AMBASSADOR_TIER_8: TrackId = 8; + pub const MASTER_AMBASSADOR_TIER_9: TrackId = 9; +} + +/// The type implementing the [`pallet_referenda::TracksInfo`] trait for referenda pallet. +pub struct TracksInfo; + +/// Information on the voting tracks. +impl pallet_referenda::TracksInfo for TracksInfo { + type Id = TrackId; + + type RuntimeOrigin = ::PalletsOrigin; + + type TracksIter = StaticTracksIter; + + /// Return the array of available tracks and their information. + fn tracks() -> Self::TracksIter { + static DATA: [Track; 9] = [ + Track { + id: constants::AMBASSADOR_TIER_1, + info: pallet_referenda::TrackInfo { + name: s("ambassador tier 1"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 24 * HOURS, + decision_period: 7 * DAYS, + confirm_period: 24 * HOURS, + min_enactment_period: 1 * HOURS, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(10), + ceil: Perbill::from_percent(50), + }, + }, + }, + Track { + id: constants::AMBASSADOR_TIER_2, + info: pallet_referenda::TrackInfo { + name: s("ambassador tier 2"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 24 * HOURS, + decision_period: 7 * DAYS, + confirm_period: 24 * HOURS, + min_enactment_period: 1 * HOURS, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(10), + ceil: Perbill::from_percent(50), + }, + }, + }, + Track { + id: constants::SENIOR_AMBASSADOR_TIER_3, + info: pallet_referenda::TrackInfo { + name: s("senior ambassador tier 3"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 24 * HOURS, + decision_period: 7 * DAYS, + confirm_period: 24 * HOURS, + min_enactment_period: 1 * HOURS, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(10), + ceil: Perbill::from_percent(50), + }, + }, + }, + Track { + id: constants::SENIOR_AMBASSADOR_TIER_4, + info: pallet_referenda::TrackInfo { + name: s("senior ambassador tier 4"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 24 * HOURS, + decision_period: 7 * DAYS, + confirm_period: 24 * HOURS, + min_enactment_period: 1 * HOURS, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(10), + ceil: Perbill::from_percent(50), + }, + }, + }, + Track { + id: constants::HEAD_AMBASSADOR_TIER_5, + info: pallet_referenda::TrackInfo { + name: s("head ambassador tier 5"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 24 * HOURS, + decision_period: 7 * DAYS, + confirm_period: 24 * HOURS, + min_enactment_period: 1 * HOURS, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(10), + ceil: Perbill::from_percent(50), + }, + }, + }, + Track { + id: constants::HEAD_AMBASSADOR_TIER_6, + info: pallet_referenda::TrackInfo { + name: s("head ambassador tier 6"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 24 * HOURS, + decision_period: 7 * DAYS, + confirm_period: 24 * HOURS, + min_enactment_period: 1 * HOURS, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(10), + ceil: Perbill::from_percent(50), + }, + }, + }, + Track { + id: constants::HEAD_AMBASSADOR_TIER_7, + info: pallet_referenda::TrackInfo { + name: s("head ambassador tier 7"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 24 * HOURS, + decision_period: 7 * DAYS, + confirm_period: 24 * HOURS, + min_enactment_period: 1 * HOURS, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(10), + ceil: Perbill::from_percent(50), + }, + }, + }, + Track { + id: constants::MASTER_AMBASSADOR_TIER_8, + info: pallet_referenda::TrackInfo { + name: s("master ambassador tier 8"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 24 * HOURS, + decision_period: 7 * DAYS, + confirm_period: 24 * HOURS, + min_enactment_period: 1 * HOURS, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(10), + ceil: Perbill::from_percent(50), + }, + }, + }, + Track { + id: constants::MASTER_AMBASSADOR_TIER_9, + info: pallet_referenda::TrackInfo { + name: s("master ambassador tier 9"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 24 * HOURS, + decision_period: 7 * DAYS, + confirm_period: 24 * HOURS, + min_enactment_period: 1 * HOURS, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(10), + ceil: Perbill::from_percent(50), + }, + }, + }, + ]; + DATA.iter().map(Borrowed) + } + + /// Determine the voting track for the given `origin`. + fn track_for(id: &Self::RuntimeOrigin) -> Result { + #[cfg(feature = "runtime-benchmarks")] + { + // For benchmarks, we enable a root origin. + // It is important that this is not available in production! + let root: Self::RuntimeOrigin = frame_system::RawOrigin::Root.into(); + if &root == id { + return Ok(constants::MASTER_AMBASSADOR_TIER_9); + } + } + + match Origin::try_from(id.clone()) { + Ok(Origin::Ambassadors) => Ok(constants::AMBASSADOR_TIER_1), + Ok(Origin::AmbassadorsTier2) => Ok(constants::AMBASSADOR_TIER_2), + Ok(Origin::SeniorAmbassadors) => Ok(constants::SENIOR_AMBASSADOR_TIER_3), + Ok(Origin::SeniorAmbassadorsTier4) => Ok(constants::SENIOR_AMBASSADOR_TIER_4), + Ok(Origin::HeadAmbassadors) => Ok(constants::HEAD_AMBASSADOR_TIER_5), + Ok(Origin::HeadAmbassadorsTier6) => Ok(constants::HEAD_AMBASSADOR_TIER_6), + Ok(Origin::HeadAmbassadorsTier7) => Ok(constants::HEAD_AMBASSADOR_TIER_7), + Ok(Origin::MasterAmbassadors) => Ok(constants::MASTER_AMBASSADOR_TIER_8), + Ok(Origin::MasterAmbassadorsTier9) => Ok(constants::MASTER_AMBASSADOR_TIER_9), + _ => Err(()), + } + } +} + +// implements [`frame_support::traits::Get`] for [`TracksInfo`] +pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber); diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/tracks.rs b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/tracks.rs new file mode 100644 index 0000000000000..2af7dc629dfa9 --- /dev/null +++ b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/tracks.rs @@ -0,0 +1,536 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Track configurations for Fellowship. + +use crate::{Balance, BlockNumber, RuntimeOrigin, DAYS, DOLLARS, HOURS, MINUTES}; +use pallet_ranked_collective::Rank; +use pallet_referenda::{StaticTracksIter, Track}; +use sp_runtime::{str_array as s, traits::Convert, Perbill}; +use sp_std::borrow::Cow::Borrowed; + +/// Referendum `TrackId` type. +pub type TrackId = u16; + +/// Referendum track IDs. +pub mod constants { + use super::TrackId; + + // Regular tracks (7 days) used for general operations. The required rank for voting is the + // same as that which is named (and also the track ID). + pub const MEMBERS: TrackId = 1; + pub const PROFICIENTS: TrackId = 2; + pub const FELLOWS: TrackId = 3; + pub const ARCHITECTS: TrackId = 4; + pub const ARCHITECTS_ADEPT: TrackId = 5; + pub const GRAND_ARCHITECTS: TrackId = 6; + pub const MASTERS: TrackId = 7; + pub const MASTERS_CONSTANT: TrackId = 8; + pub const GRAND_MASTERS: TrackId = 9; + + // Longer tracks (14 days) used for rank retention. These require a rank of two more than the + // grade at which they retain (as per the whitepaper). This works out as the track ID minus 8. + pub const RETAIN_AT_1DAN: TrackId = 11; + pub const RETAIN_AT_2DAN: TrackId = 12; + pub const RETAIN_AT_3DAN: TrackId = 13; + pub const RETAIN_AT_4DAN: TrackId = 14; + pub const RETAIN_AT_5DAN: TrackId = 15; + pub const RETAIN_AT_6DAN: TrackId = 16; + + // Longest tracks (30 days) used for promotions. These require a rank of two more than the + // grade to which they promote (as per the whitepaper). This works out as the track ID minus 18. + pub const PROMOTE_TO_1DAN: TrackId = 21; + pub const PROMOTE_TO_2DAN: TrackId = 22; + pub const PROMOTE_TO_3DAN: TrackId = 23; + pub const PROMOTE_TO_4DAN: TrackId = 24; + pub const PROMOTE_TO_5DAN: TrackId = 25; + pub const PROMOTE_TO_6DAN: TrackId = 26; +} + +/// Convert the track ID (defined above) into the minimum rank (i.e. fellowship Dan grade) required +/// to vote on the track. +pub struct MinRankOfClass; +impl Convert for MinRankOfClass { + fn convert(a: TrackId) -> Rank { + match a { + // Just a regular vote: the track ID is conveniently the same as the minimum rank. + regular @ 1..=9 => regular, + // A retention vote; the track ID turns out to be 8 more than the minimum required rank. + retention @ 11..=16 => retention - 8, + // A promotion vote; the track ID turns out to be 18 more than the minimum required + // rank. + promotion @ 21..=26 => promotion - 18, + _ => Rank::max_value(), + } + } +} + +const RETAIN_MAX_DECIDING: u32 = 25; +const RETAIN_DECISION_DEPOSIT: Balance = 5 * DOLLARS; +const RETAIN_PREPARE_PERIOD: BlockNumber = 0; +const RETAIN_DECISION_PERIOD: BlockNumber = 14 * DAYS; +const RETAIN_CONFIRM_PERIOD: BlockNumber = 1 * HOURS; +const RETAIN_MIN_ENACTMENT_PERIOD: BlockNumber = 0; +const RETAIN_MIN_APPROVAL: pallet_referenda::Curve = pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(60), + ceil: Perbill::from_percent(100), +}; +const RETAIN_MIN_SUPPORT: pallet_referenda::Curve = pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(10), + ceil: Perbill::from_percent(100), +}; + +const PROMOTE_MAX_DECIDING: u32 = 10; +const PROMOTE_DECISION_DEPOSIT: Balance = 5 * DOLLARS; +const PROMOTE_PREPARE_PERIOD: BlockNumber = 0; +const PROMOTE_DECISION_PERIOD: BlockNumber = 30 * DAYS; +const PROMOTE_CONFIRM_PERIOD: BlockNumber = 1 * HOURS; +const PROMOTE_MIN_ENACTMENT_PERIOD: BlockNumber = 0; +const PROMOTE_MIN_APPROVAL: pallet_referenda::Curve = pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(60), + ceil: Perbill::from_percent(100), +}; +const PROMOTE_MIN_SUPPORT: pallet_referenda::Curve = pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(10), + ceil: Perbill::from_percent(100), +}; + +pub struct TracksInfo; +impl pallet_referenda::TracksInfo for TracksInfo { + type Id = TrackId; + type RuntimeOrigin = ::PalletsOrigin; + type TracksIter = StaticTracksIter; + + fn tracks() -> Self::TracksIter { + use constants as tracks; + static DATA: [Track; 21] = [ + Track { + id: tracks::MEMBERS, + info: pallet_referenda::TrackInfo { + name: s("members"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 30 * MINUTES, + decision_period: 7 * DAYS, + confirm_period: 30 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(0), + ceil: Perbill::from_percent(100), + }, + }, + }, + Track { + id: tracks::PROFICIENTS, + info: pallet_referenda::TrackInfo { + name: s("proficient members"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 30 * MINUTES, + decision_period: 7 * DAYS, + confirm_period: 30 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(0), + ceil: Perbill::from_percent(100), + }, + }, + }, + Track { + id: tracks::FELLOWS, + info: pallet_referenda::TrackInfo { + name: s("fellows"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 30 * MINUTES, + decision_period: 7 * DAYS, + confirm_period: 30 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(0), + ceil: Perbill::from_percent(100), + }, + }, + }, + Track { + id: tracks::ARCHITECTS, + info: pallet_referenda::TrackInfo { + name: s("architects"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 30 * MINUTES, + decision_period: 7 * DAYS, + confirm_period: 30 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(0), + ceil: Perbill::from_percent(100), + }, + }, + }, + Track { + id: tracks::ARCHITECTS_ADEPT, + info: pallet_referenda::TrackInfo { + name: s("architects adept"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 30 * MINUTES, + decision_period: 7 * DAYS, + confirm_period: 30 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(0), + ceil: Perbill::from_percent(100), + }, + }, + }, + Track { + id: tracks::GRAND_ARCHITECTS, + info: pallet_referenda::TrackInfo { + name: s("grand architects"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 30 * MINUTES, + decision_period: 7 * DAYS, + confirm_period: 30 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(0), + ceil: Perbill::from_percent(100), + }, + }, + }, + Track { + id: tracks::MASTERS, + info: pallet_referenda::TrackInfo { + name: s("masters"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 30 * MINUTES, + decision_period: 7 * DAYS, + confirm_period: 30 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(0), + ceil: Perbill::from_percent(100), + }, + }, + }, + Track { + id: tracks::MASTERS_CONSTANT, + info: pallet_referenda::TrackInfo { + name: s("masters constant"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 30 * MINUTES, + decision_period: 7 * DAYS, + confirm_period: 30 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(0), + ceil: Perbill::from_percent(100), + }, + }, + }, + Track { + id: tracks::GRAND_MASTERS, + info: pallet_referenda::TrackInfo { + name: s("grand masters"), + max_deciding: 10, + decision_deposit: 5 * DOLLARS, + prepare_period: 30 * MINUTES, + decision_period: 7 * DAYS, + confirm_period: 30 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(0), + ceil: Perbill::from_percent(100), + }, + }, + }, + Track { + id: tracks::RETAIN_AT_1DAN, + info: pallet_referenda::TrackInfo { + name: s("retain at I Dan"), + max_deciding: RETAIN_MAX_DECIDING, + decision_deposit: RETAIN_DECISION_DEPOSIT, + prepare_period: RETAIN_PREPARE_PERIOD, + decision_period: RETAIN_DECISION_PERIOD, + confirm_period: RETAIN_CONFIRM_PERIOD, + min_enactment_period: RETAIN_MIN_ENACTMENT_PERIOD, + min_approval: RETAIN_MIN_APPROVAL, + min_support: RETAIN_MIN_SUPPORT, + }, + }, + Track { + id: tracks::RETAIN_AT_2DAN, + info: pallet_referenda::TrackInfo { + name: s("retain at II Dan"), + max_deciding: RETAIN_MAX_DECIDING, + decision_deposit: RETAIN_DECISION_DEPOSIT, + prepare_period: RETAIN_PREPARE_PERIOD, + decision_period: RETAIN_DECISION_PERIOD, + confirm_period: RETAIN_CONFIRM_PERIOD, + min_enactment_period: RETAIN_MIN_ENACTMENT_PERIOD, + min_approval: RETAIN_MIN_APPROVAL, + min_support: RETAIN_MIN_SUPPORT, + }, + }, + Track { + id: tracks::RETAIN_AT_3DAN, + info: pallet_referenda::TrackInfo { + name: s("retain at III Dan"), + max_deciding: RETAIN_MAX_DECIDING, + decision_deposit: RETAIN_DECISION_DEPOSIT, + prepare_period: RETAIN_PREPARE_PERIOD, + decision_period: RETAIN_DECISION_PERIOD, + confirm_period: RETAIN_CONFIRM_PERIOD, + min_enactment_period: RETAIN_MIN_ENACTMENT_PERIOD, + min_approval: RETAIN_MIN_APPROVAL, + min_support: RETAIN_MIN_SUPPORT, + }, + }, + Track { + id: tracks::RETAIN_AT_4DAN, + info: pallet_referenda::TrackInfo { + name: s("retain at IV Dan"), + max_deciding: RETAIN_MAX_DECIDING, + decision_deposit: RETAIN_DECISION_DEPOSIT, + prepare_period: RETAIN_PREPARE_PERIOD, + decision_period: RETAIN_DECISION_PERIOD, + confirm_period: RETAIN_CONFIRM_PERIOD, + min_enactment_period: RETAIN_MIN_ENACTMENT_PERIOD, + min_approval: RETAIN_MIN_APPROVAL, + min_support: RETAIN_MIN_SUPPORT, + }, + }, + Track { + id: tracks::RETAIN_AT_5DAN, + info: pallet_referenda::TrackInfo { + name: s("retain at V Dan"), + max_deciding: RETAIN_MAX_DECIDING, + decision_deposit: RETAIN_DECISION_DEPOSIT, + prepare_period: RETAIN_PREPARE_PERIOD, + decision_period: RETAIN_DECISION_PERIOD, + confirm_period: RETAIN_CONFIRM_PERIOD, + min_enactment_period: RETAIN_MIN_ENACTMENT_PERIOD, + min_approval: RETAIN_MIN_APPROVAL, + min_support: RETAIN_MIN_SUPPORT, + }, + }, + Track { + id: tracks::RETAIN_AT_6DAN, + info: pallet_referenda::TrackInfo { + name: s("retain at VI Dan"), + max_deciding: RETAIN_MAX_DECIDING, + decision_deposit: RETAIN_DECISION_DEPOSIT, + prepare_period: RETAIN_PREPARE_PERIOD, + decision_period: RETAIN_DECISION_PERIOD, + confirm_period: RETAIN_CONFIRM_PERIOD, + min_enactment_period: RETAIN_MIN_ENACTMENT_PERIOD, + min_approval: RETAIN_MIN_APPROVAL, + min_support: RETAIN_MIN_SUPPORT, + }, + }, + Track { + id: tracks::PROMOTE_TO_1DAN, + info: pallet_referenda::TrackInfo { + name: s("promote to I Dan"), + max_deciding: PROMOTE_MAX_DECIDING, + decision_deposit: PROMOTE_DECISION_DEPOSIT, + prepare_period: PROMOTE_PREPARE_PERIOD, + decision_period: PROMOTE_DECISION_PERIOD, + confirm_period: PROMOTE_CONFIRM_PERIOD, + min_enactment_period: PROMOTE_MIN_ENACTMENT_PERIOD, + min_approval: PROMOTE_MIN_APPROVAL, + min_support: PROMOTE_MIN_SUPPORT, + }, + }, + Track { + id: tracks::PROMOTE_TO_2DAN, + info: pallet_referenda::TrackInfo { + name: s("promote to II Dan"), + max_deciding: PROMOTE_MAX_DECIDING, + decision_deposit: PROMOTE_DECISION_DEPOSIT, + prepare_period: PROMOTE_PREPARE_PERIOD, + decision_period: PROMOTE_DECISION_PERIOD, + confirm_period: PROMOTE_CONFIRM_PERIOD, + min_enactment_period: PROMOTE_MIN_ENACTMENT_PERIOD, + min_approval: PROMOTE_MIN_APPROVAL, + min_support: PROMOTE_MIN_SUPPORT, + }, + }, + Track { + id: tracks::PROMOTE_TO_3DAN, + info: pallet_referenda::TrackInfo { + name: s("promote to III Dan"), + max_deciding: PROMOTE_MAX_DECIDING, + decision_deposit: PROMOTE_DECISION_DEPOSIT, + prepare_period: PROMOTE_PREPARE_PERIOD, + decision_period: PROMOTE_DECISION_PERIOD, + confirm_period: PROMOTE_CONFIRM_PERIOD, + min_enactment_period: PROMOTE_MIN_ENACTMENT_PERIOD, + min_approval: PROMOTE_MIN_APPROVAL, + min_support: PROMOTE_MIN_SUPPORT, + }, + }, + Track { + id: tracks::PROMOTE_TO_4DAN, + info: pallet_referenda::TrackInfo { + name: s("promote to IV Dan"), + max_deciding: PROMOTE_MAX_DECIDING, + decision_deposit: PROMOTE_DECISION_DEPOSIT, + prepare_period: PROMOTE_PREPARE_PERIOD, + decision_period: PROMOTE_DECISION_PERIOD, + confirm_period: PROMOTE_CONFIRM_PERIOD, + min_enactment_period: PROMOTE_MIN_ENACTMENT_PERIOD, + min_approval: PROMOTE_MIN_APPROVAL, + min_support: PROMOTE_MIN_SUPPORT, + }, + }, + Track { + id: tracks::PROMOTE_TO_5DAN, + info: pallet_referenda::TrackInfo { + name: s("promote to V Dan"), + max_deciding: PROMOTE_MAX_DECIDING, + decision_deposit: PROMOTE_DECISION_DEPOSIT, + prepare_period: PROMOTE_PREPARE_PERIOD, + decision_period: PROMOTE_DECISION_PERIOD, + confirm_period: PROMOTE_CONFIRM_PERIOD, + min_enactment_period: PROMOTE_MIN_ENACTMENT_PERIOD, + min_approval: PROMOTE_MIN_APPROVAL, + min_support: PROMOTE_MIN_SUPPORT, + }, + }, + Track { + id: tracks::PROMOTE_TO_6DAN, + info: pallet_referenda::TrackInfo { + name: s("promote to VI Dan"), + max_deciding: PROMOTE_MAX_DECIDING, + decision_deposit: PROMOTE_DECISION_DEPOSIT, + prepare_period: PROMOTE_PREPARE_PERIOD, + decision_period: PROMOTE_DECISION_PERIOD, + confirm_period: PROMOTE_CONFIRM_PERIOD, + min_enactment_period: PROMOTE_MIN_ENACTMENT_PERIOD, + min_approval: PROMOTE_MIN_APPROVAL, + min_support: PROMOTE_MIN_SUPPORT, + }, + }, + ]; + DATA.iter().map(Borrowed) + } + fn track_for(id: &Self::RuntimeOrigin) -> Result { + use super::origins::Origin; + use constants as tracks; + + #[cfg(feature = "runtime-benchmarks")] + { + // For benchmarks, we enable a root origin. + // It is important that this is not available in production! + let root: Self::RuntimeOrigin = frame_system::RawOrigin::Root.into(); + if &root == id { + return Ok(tracks::GRAND_MASTERS) + } + } + + match Origin::try_from(id.clone()) { + Ok(Origin::Members) => Ok(tracks::MEMBERS), + Ok(Origin::Fellowship2Dan) => Ok(tracks::PROFICIENTS), + Ok(Origin::Fellows) => Ok(tracks::FELLOWS), + Ok(Origin::Architects) => Ok(tracks::ARCHITECTS), + Ok(Origin::Fellowship5Dan) => Ok(tracks::ARCHITECTS_ADEPT), + Ok(Origin::Fellowship6Dan) => Ok(tracks::GRAND_ARCHITECTS), + Ok(Origin::Masters) => Ok(tracks::MASTERS), + Ok(Origin::Fellowship8Dan) => Ok(tracks::MASTERS_CONSTANT), + Ok(Origin::Fellowship9Dan) => Ok(tracks::GRAND_MASTERS), + + Ok(Origin::RetainAt1Dan) => Ok(tracks::RETAIN_AT_1DAN), + Ok(Origin::RetainAt2Dan) => Ok(tracks::RETAIN_AT_2DAN), + Ok(Origin::RetainAt3Dan) => Ok(tracks::RETAIN_AT_3DAN), + Ok(Origin::RetainAt4Dan) => Ok(tracks::RETAIN_AT_4DAN), + Ok(Origin::RetainAt5Dan) => Ok(tracks::RETAIN_AT_5DAN), + Ok(Origin::RetainAt6Dan) => Ok(tracks::RETAIN_AT_6DAN), + + Ok(Origin::PromoteTo1Dan) => Ok(tracks::PROMOTE_TO_1DAN), + Ok(Origin::PromoteTo2Dan) => Ok(tracks::PROMOTE_TO_2DAN), + Ok(Origin::PromoteTo3Dan) => Ok(tracks::PROMOTE_TO_3DAN), + Ok(Origin::PromoteTo4Dan) => Ok(tracks::PROMOTE_TO_4DAN), + Ok(Origin::PromoteTo5Dan) => Ok(tracks::PROMOTE_TO_5DAN), + Ok(Origin::PromoteTo6Dan) => Ok(tracks::PROMOTE_TO_6DAN), + + _ => Err(()), + } + } +} +pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber); diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/tracks.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/tracks.rs index d4a2d3bbf1c7b..f948a9cb27789 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/tracks.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/tracks.rs @@ -17,7 +17,9 @@ use super::Origin; use crate::{Balance, BlockNumber, RuntimeOrigin, DAYS, DOLLARS, HOURS}; -use sp_runtime::Perbill; +use pallet_referenda::{Curve, StaticTracksIter, Track, TrackInfo}; +use sp_runtime::{str_array as s, Perbill}; +use sp_std::borrow::Cow::Borrowed; /// Referendum `TrackId` type. pub type TrackId = u16; @@ -46,209 +48,211 @@ impl pallet_referenda::TracksInfo for TracksInfo { type RuntimeOrigin = ::PalletsOrigin; - /// Return the array of available tracks and their information. - fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { - static DATA: [(TrackId, pallet_referenda::TrackInfo); 9] = [ - ( - constants::AMBASSADOR_TIER_1, - pallet_referenda::TrackInfo { - name: "ambassador tier 1", + type TracksIter = StaticTracksIter; + + /// Return the list of available tracks and their information. + fn tracks() -> Self::TracksIter { + static DATA: [Track; 9] = [ + Track { + id: constants::AMBASSADOR_TIER_1, + info: TrackInfo { + name: s("ambassador tier 1"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, decision_period: 1 * DAYS, confirm_period: 24 * HOURS, min_enactment_period: 1 * HOURS, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(10), ceil: Perbill::from_percent(50), }, }, - ), - ( - constants::AMBASSADOR_TIER_2, - pallet_referenda::TrackInfo { - name: "ambassador tier 2", + }, + Track { + id: constants::AMBASSADOR_TIER_2, + info: TrackInfo { + name: s("ambassador tier 2"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, decision_period: 1 * DAYS, confirm_period: 24 * HOURS, min_enactment_period: 1 * HOURS, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(10), ceil: Perbill::from_percent(50), }, }, - ), - ( - constants::SENIOR_AMBASSADOR_TIER_3, - pallet_referenda::TrackInfo { - name: "senior ambassador tier 3", + }, + Track { + id: constants::SENIOR_AMBASSADOR_TIER_3, + info: TrackInfo { + name: s("senior ambassador tier 3"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, decision_period: 1 * DAYS, confirm_period: 24 * HOURS, min_enactment_period: 1 * HOURS, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(10), ceil: Perbill::from_percent(50), }, }, - ), - ( - constants::SENIOR_AMBASSADOR_TIER_4, - pallet_referenda::TrackInfo { - name: "senior ambassador tier 4", + }, + Track { + id: constants::SENIOR_AMBASSADOR_TIER_4, + info: TrackInfo { + name: s("senior ambassador tier 4"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, decision_period: 1 * DAYS, confirm_period: 24 * HOURS, min_enactment_period: 1 * HOURS, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(10), ceil: Perbill::from_percent(50), }, }, - ), - ( - constants::HEAD_AMBASSADOR_TIER_5, - pallet_referenda::TrackInfo { - name: "head ambassador tier 5", + }, + Track { + id: constants::HEAD_AMBASSADOR_TIER_5, + info: TrackInfo { + name: s("head ambassador tier 5"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, decision_period: 1 * DAYS, confirm_period: 24 * HOURS, min_enactment_period: 1 * HOURS, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(10), ceil: Perbill::from_percent(50), }, }, - ), - ( - constants::HEAD_AMBASSADOR_TIER_6, - pallet_referenda::TrackInfo { - name: "head ambassador tier 6", + }, + Track { + id: constants::HEAD_AMBASSADOR_TIER_6, + info: TrackInfo { + name: s("head ambassador tier 6"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, decision_period: 1 * DAYS, confirm_period: 24 * HOURS, min_enactment_period: 1 * HOURS, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(10), ceil: Perbill::from_percent(50), }, }, - ), - ( - constants::HEAD_AMBASSADOR_TIER_7, - pallet_referenda::TrackInfo { - name: "head ambassador tier 7", + }, + Track { + id: constants::HEAD_AMBASSADOR_TIER_7, + info: TrackInfo { + name: s("head ambassador tier 7"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, decision_period: 1 * DAYS, confirm_period: 24 * HOURS, min_enactment_period: 1 * HOURS, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(10), ceil: Perbill::from_percent(50), }, }, - ), - ( - constants::MASTER_AMBASSADOR_TIER_8, - pallet_referenda::TrackInfo { - name: "master ambassador tier 8", + }, + Track { + id: constants::MASTER_AMBASSADOR_TIER_8, + info: TrackInfo { + name: s("master ambassador tier 8"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, decision_period: 1 * DAYS, confirm_period: 24 * HOURS, min_enactment_period: 1 * HOURS, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(10), ceil: Perbill::from_percent(50), }, }, - ), - ( - constants::MASTER_AMBASSADOR_TIER_9, - pallet_referenda::TrackInfo { - name: "master ambassador tier 9", + }, + Track { + id: constants::MASTER_AMBASSADOR_TIER_9, + info: TrackInfo { + name: s("master ambassador tier 9"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, decision_period: 1 * DAYS, confirm_period: 24 * HOURS, min_enactment_period: 1 * HOURS, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(10), ceil: Perbill::from_percent(50), }, }, - ), + }, ]; - &DATA[..] + DATA.iter().map(Borrowed) } /// Determine the voting track for the given `origin`. diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/tracks.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/tracks.rs index 099bdf4cf7539..5bc690c3c3787 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/tracks.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/tracks.rs @@ -18,7 +18,9 @@ use crate::{Balance, BlockNumber, RuntimeOrigin, DAYS, DOLLARS, HOURS, MINUTES}; use pallet_ranked_collective::Rank; -use sp_runtime::{traits::Convert, Perbill}; +use pallet_referenda::{Curve, StaticTracksIter, Track, TrackInfo}; +use sp_runtime::{str_array as s, traits::Convert, Perbill}; +use sp_std::borrow::Cow::Borrowed; /// Referendum `TrackId` type. pub type TrackId = u16; @@ -82,12 +84,12 @@ const RETAIN_PREPARE_PERIOD: BlockNumber = 0; const RETAIN_DECISION_PERIOD: BlockNumber = 14 * DAYS; const RETAIN_CONFIRM_PERIOD: BlockNumber = 1 * HOURS; const RETAIN_MIN_ENACTMENT_PERIOD: BlockNumber = 0; -const RETAIN_MIN_APPROVAL: pallet_referenda::Curve = pallet_referenda::Curve::LinearDecreasing { +const RETAIN_MIN_APPROVAL: Curve = Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(60), ceil: Perbill::from_percent(100), }; -const RETAIN_MIN_SUPPORT: pallet_referenda::Curve = pallet_referenda::Curve::LinearDecreasing { +const RETAIN_MIN_SUPPORT: Curve = Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(10), ceil: Perbill::from_percent(100), @@ -99,12 +101,12 @@ const PROMOTE_PREPARE_PERIOD: BlockNumber = 0; const PROMOTE_DECISION_PERIOD: BlockNumber = 30 * DAYS; const PROMOTE_CONFIRM_PERIOD: BlockNumber = 1 * HOURS; const PROMOTE_MIN_ENACTMENT_PERIOD: BlockNumber = 0; -const PROMOTE_MIN_APPROVAL: pallet_referenda::Curve = pallet_referenda::Curve::LinearDecreasing { +const PROMOTE_MIN_APPROVAL: Curve = Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(60), ceil: Perbill::from_percent(100), }; -const PROMOTE_MIN_SUPPORT: pallet_referenda::Curve = pallet_referenda::Curve::LinearDecreasing { +const PROMOTE_MIN_SUPPORT: Curve = Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(10), ceil: Perbill::from_percent(100), @@ -114,211 +116,213 @@ pub struct TracksInfo; impl pallet_referenda::TracksInfo for TracksInfo { type Id = TrackId; type RuntimeOrigin = ::PalletsOrigin; - fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { + type TracksIter = StaticTracksIter; + + fn tracks() -> Self::TracksIter { use constants as tracks; - static DATA: [(TrackId, pallet_referenda::TrackInfo); 21] = [ - ( - tracks::MEMBERS, - pallet_referenda::TrackInfo { - name: "members", + static DATA: [Track; 21] = [ + Track { + id: tracks::MEMBERS, + info: TrackInfo { + name: s("members"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, decision_period: 1 * DAYS, confirm_period: 30 * MINUTES, min_enactment_period: 5 * MINUTES, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(0), ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::PROFICIENTS, - pallet_referenda::TrackInfo { - name: "proficient members", + }, + Track { + id: tracks::PROFICIENTS, + info: TrackInfo { + name: s("proficient members"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, decision_period: 1 * DAYS, confirm_period: 30 * MINUTES, min_enactment_period: 5 * MINUTES, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(0), ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::FELLOWS, - pallet_referenda::TrackInfo { - name: "fellows", + }, + Track { + id: tracks::FELLOWS, + info: TrackInfo { + name: s("fellows"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, decision_period: 1 * DAYS, confirm_period: 30 * MINUTES, min_enactment_period: 5 * MINUTES, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(0), ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::ARCHITECTS, - pallet_referenda::TrackInfo { - name: "architects", + }, + Track { + id: tracks::ARCHITECTS, + info: TrackInfo { + name: s("architects"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, decision_period: 1 * DAYS, confirm_period: 30 * MINUTES, min_enactment_period: 5 * MINUTES, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(0), ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::ARCHITECTS_ADEPT, - pallet_referenda::TrackInfo { - name: "architects adept", + }, + Track { + id: tracks::ARCHITECTS_ADEPT, + info: TrackInfo { + name: s("architects adept"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, decision_period: 1 * DAYS, confirm_period: 30 * MINUTES, min_enactment_period: 5 * MINUTES, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(0), ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::GRAND_ARCHITECTS, - pallet_referenda::TrackInfo { - name: "grand architects", + }, + Track { + id: tracks::GRAND_ARCHITECTS, + info: TrackInfo { + name: s("grand architects"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, decision_period: 1 * DAYS, confirm_period: 30 * MINUTES, min_enactment_period: 5 * MINUTES, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(0), ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::MASTERS, - pallet_referenda::TrackInfo { - name: "masters", + }, + Track { + id: tracks::MASTERS, + info: TrackInfo { + name: s("masters"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, decision_period: 1 * DAYS, confirm_period: 30 * MINUTES, min_enactment_period: 5 * MINUTES, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(0), ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::MASTERS_CONSTANT, - pallet_referenda::TrackInfo { - name: "masters constant", + }, + Track { + id: tracks::MASTERS_CONSTANT, + info: TrackInfo { + name: s("masters constant"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, decision_period: 1 * DAYS, confirm_period: 30 * MINUTES, min_enactment_period: 5 * MINUTES, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(0), ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::GRAND_MASTERS, - pallet_referenda::TrackInfo { - name: "grand masters", + }, + Track { + id: tracks::GRAND_MASTERS, + info: TrackInfo { + name: s("grand masters"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, decision_period: 1 * DAYS, confirm_period: 30 * MINUTES, min_enactment_period: 5 * MINUTES, - min_approval: pallet_referenda::Curve::LinearDecreasing { + min_approval: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), ceil: Perbill::from_percent(100), }, - min_support: pallet_referenda::Curve::LinearDecreasing { + min_support: Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(0), ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::RETAIN_AT_1DAN, - pallet_referenda::TrackInfo { - name: "retain at I Dan", + }, + Track { + id: tracks::RETAIN_AT_1DAN, + info: TrackInfo { + name: s("retain at I Dan"), max_deciding: RETAIN_MAX_DECIDING, decision_deposit: RETAIN_DECISION_DEPOSIT, prepare_period: RETAIN_PREPARE_PERIOD, @@ -328,11 +332,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: RETAIN_MIN_APPROVAL, min_support: RETAIN_MIN_SUPPORT, }, - ), - ( - tracks::RETAIN_AT_2DAN, - pallet_referenda::TrackInfo { - name: "retain at II Dan", + }, + Track { + id: tracks::RETAIN_AT_2DAN, + info: TrackInfo { + name: s("retain at II Dan"), max_deciding: RETAIN_MAX_DECIDING, decision_deposit: RETAIN_DECISION_DEPOSIT, prepare_period: RETAIN_PREPARE_PERIOD, @@ -342,11 +346,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: RETAIN_MIN_APPROVAL, min_support: RETAIN_MIN_SUPPORT, }, - ), - ( - tracks::RETAIN_AT_3DAN, - pallet_referenda::TrackInfo { - name: "retain at III Dan", + }, + Track { + id: tracks::RETAIN_AT_3DAN, + info: TrackInfo { + name: s("retain at III Dan"), max_deciding: RETAIN_MAX_DECIDING, decision_deposit: RETAIN_DECISION_DEPOSIT, prepare_period: RETAIN_PREPARE_PERIOD, @@ -356,11 +360,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: RETAIN_MIN_APPROVAL, min_support: RETAIN_MIN_SUPPORT, }, - ), - ( - tracks::RETAIN_AT_4DAN, - pallet_referenda::TrackInfo { - name: "retain at IV Dan", + }, + Track { + id: tracks::RETAIN_AT_4DAN, + info: TrackInfo { + name: s("retain at IV Dan"), max_deciding: RETAIN_MAX_DECIDING, decision_deposit: RETAIN_DECISION_DEPOSIT, prepare_period: RETAIN_PREPARE_PERIOD, @@ -370,11 +374,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: RETAIN_MIN_APPROVAL, min_support: RETAIN_MIN_SUPPORT, }, - ), - ( - tracks::RETAIN_AT_5DAN, - pallet_referenda::TrackInfo { - name: "retain at V Dan", + }, + Track { + id: tracks::RETAIN_AT_5DAN, + info: TrackInfo { + name: s("retain at V Dan"), max_deciding: RETAIN_MAX_DECIDING, decision_deposit: RETAIN_DECISION_DEPOSIT, prepare_period: RETAIN_PREPARE_PERIOD, @@ -384,11 +388,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: RETAIN_MIN_APPROVAL, min_support: RETAIN_MIN_SUPPORT, }, - ), - ( - tracks::RETAIN_AT_6DAN, - pallet_referenda::TrackInfo { - name: "retain at VI Dan", + }, + Track { + id: tracks::RETAIN_AT_6DAN, + info: TrackInfo { + name: s("retain at VI Dan"), max_deciding: RETAIN_MAX_DECIDING, decision_deposit: RETAIN_DECISION_DEPOSIT, prepare_period: RETAIN_PREPARE_PERIOD, @@ -398,11 +402,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: RETAIN_MIN_APPROVAL, min_support: RETAIN_MIN_SUPPORT, }, - ), - ( - tracks::PROMOTE_TO_1DAN, - pallet_referenda::TrackInfo { - name: "promote to I Dan", + }, + Track { + id: tracks::PROMOTE_TO_1DAN, + info: TrackInfo { + name: s("promote to I Dan"), max_deciding: PROMOTE_MAX_DECIDING, decision_deposit: PROMOTE_DECISION_DEPOSIT, prepare_period: PROMOTE_PREPARE_PERIOD, @@ -412,11 +416,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: PROMOTE_MIN_APPROVAL, min_support: PROMOTE_MIN_SUPPORT, }, - ), - ( - tracks::PROMOTE_TO_2DAN, - pallet_referenda::TrackInfo { - name: "promote to II Dan", + }, + Track { + id: tracks::PROMOTE_TO_2DAN, + info: TrackInfo { + name: s("promote to II Dan"), max_deciding: PROMOTE_MAX_DECIDING, decision_deposit: PROMOTE_DECISION_DEPOSIT, prepare_period: PROMOTE_PREPARE_PERIOD, @@ -426,11 +430,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: PROMOTE_MIN_APPROVAL, min_support: PROMOTE_MIN_SUPPORT, }, - ), - ( - tracks::PROMOTE_TO_3DAN, - pallet_referenda::TrackInfo { - name: "promote to III Dan", + }, + Track { + id: tracks::PROMOTE_TO_3DAN, + info: TrackInfo { + name: s("promote to III Dan"), max_deciding: PROMOTE_MAX_DECIDING, decision_deposit: PROMOTE_DECISION_DEPOSIT, prepare_period: PROMOTE_PREPARE_PERIOD, @@ -440,11 +444,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: PROMOTE_MIN_APPROVAL, min_support: PROMOTE_MIN_SUPPORT, }, - ), - ( - tracks::PROMOTE_TO_4DAN, - pallet_referenda::TrackInfo { - name: "promote to IV Dan", + }, + Track { + id: tracks::PROMOTE_TO_4DAN, + info: TrackInfo { + name: s("promote to IV Dan"), max_deciding: PROMOTE_MAX_DECIDING, decision_deposit: PROMOTE_DECISION_DEPOSIT, prepare_period: PROMOTE_PREPARE_PERIOD, @@ -454,11 +458,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: PROMOTE_MIN_APPROVAL, min_support: PROMOTE_MIN_SUPPORT, }, - ), - ( - tracks::PROMOTE_TO_5DAN, - pallet_referenda::TrackInfo { - name: "promote to V Dan", + }, + Track { + id: tracks::PROMOTE_TO_5DAN, + info: TrackInfo { + name: s("promote to V Dan"), max_deciding: PROMOTE_MAX_DECIDING, decision_deposit: PROMOTE_DECISION_DEPOSIT, prepare_period: PROMOTE_PREPARE_PERIOD, @@ -468,11 +472,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: PROMOTE_MIN_APPROVAL, min_support: PROMOTE_MIN_SUPPORT, }, - ), - ( - tracks::PROMOTE_TO_6DAN, - pallet_referenda::TrackInfo { - name: "promote to VI Dan", + }, + Track { + id: tracks::PROMOTE_TO_6DAN, + info: TrackInfo { + name: s("promote to VI Dan"), max_deciding: PROMOTE_MAX_DECIDING, decision_deposit: PROMOTE_DECISION_DEPOSIT, prepare_period: PROMOTE_PREPARE_PERIOD, @@ -482,9 +486,9 @@ impl pallet_referenda::TracksInfo for TracksInfo { min_approval: PROMOTE_MIN_APPROVAL, min_support: PROMOTE_MIN_SUPPORT, }, - ), + }, ]; - &DATA[..] + DATA.iter().map(Borrowed) } fn track_for(id: &Self::RuntimeOrigin) -> Result { use super::origins::Origin; diff --git a/polkadot/runtime/rococo/src/governance/fellowship.rs b/polkadot/runtime/rococo/src/governance/fellowship.rs index a589b768afde2..7211e6b466323 100644 --- a/polkadot/runtime/rococo/src/governance/fellowship.rs +++ b/polkadot/runtime/rococo/src/governance/fellowship.rs @@ -17,7 +17,12 @@ //! Elements of governance concerning the Rococo Fellowship. use frame_support::traits::{MapSuccess, TryMapSuccess}; -use sp_runtime::traits::{CheckedReduceBy, ConstU16, Replace, ReplaceWithDefault}; +use pallet_referenda::{Track, TrackInfo}; +use sp_runtime::{ + str_array as s, + traits::{CheckedReduceBy, ConstU16, Replace, ReplaceWithDefault}, +}; +use sp_std::borrow::Cow; use super::*; use crate::{CENTS, DAYS}; @@ -32,12 +37,13 @@ pub struct TracksInfo; impl pallet_referenda::TracksInfo for TracksInfo { type Id = u16; type RuntimeOrigin = ::PalletsOrigin; - fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { - static DATA: [(u16, pallet_referenda::TrackInfo); 10] = [ - ( - 0u16, - pallet_referenda::TrackInfo { - name: "candidates", + + fn tracks() -> impl Iterator>> { + static DATA: [Track; 10] = [ + Track { + id: 0u16, + info: TrackInfo { + name: s("candidates"), max_deciding: 10, decision_deposit: 100 * 3 * CENTS, prepare_period: 30 * MINUTES, @@ -55,11 +61,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), - ( - 1u16, - pallet_referenda::TrackInfo { - name: "members", + }, + Track { + id: 1u16, + info: TrackInfo { + name: s("members"), max_deciding: 10, decision_deposit: 10 * 3 * CENTS, prepare_period: 30 * MINUTES, @@ -77,11 +83,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), - ( - 2u16, - pallet_referenda::TrackInfo { - name: "proficients", + }, + Track { + id: 2u16, + info: TrackInfo { + name: s("proficients"), max_deciding: 10, decision_deposit: 10 * 3 * CENTS, prepare_period: 30 * MINUTES, @@ -99,11 +105,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), - ( - 3u16, - pallet_referenda::TrackInfo { - name: "fellows", + }, + Track { + id: 3u16, + info: TrackInfo { + name: s("fellows"), max_deciding: 10, decision_deposit: 10 * 3 * CENTS, prepare_period: 30 * MINUTES, @@ -121,11 +127,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), - ( - 4u16, - pallet_referenda::TrackInfo { - name: "senior fellows", + }, + Track { + id: 4u16, + info: TrackInfo { + name: s("senior fellows"), max_deciding: 10, decision_deposit: 10 * 3 * CENTS, prepare_period: 30 * MINUTES, @@ -143,11 +149,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), - ( - 5u16, - pallet_referenda::TrackInfo { - name: "experts", + }, + Track { + id: 5u16, + info: TrackInfo { + name: s("experts"), max_deciding: 10, decision_deposit: 1 * 3 * CENTS, prepare_period: 30 * MINUTES, @@ -165,11 +171,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), - ( - 6u16, - pallet_referenda::TrackInfo { - name: "senior experts", + }, + Track { + id: 6u16, + info: TrackInfo { + name: s("senior experts"), max_deciding: 10, decision_deposit: 1 * 3 * CENTS, prepare_period: 30 * MINUTES, @@ -187,11 +193,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), - ( - 7u16, - pallet_referenda::TrackInfo { - name: "masters", + }, + Track { + id: 7u16, + info: TrackInfo { + name: s("masters"), max_deciding: 10, decision_deposit: 1 * 3 * CENTS, prepare_period: 30 * MINUTES, @@ -209,11 +215,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), - ( - 8u16, - pallet_referenda::TrackInfo { - name: "senior masters", + }, + Track { + id: 8u16, + info: TrackInfo { + name: s("senior masters"), max_deciding: 10, decision_deposit: 1 * 3 * CENTS, prepare_period: 30 * MINUTES, @@ -231,11 +237,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), - ( - 9u16, - pallet_referenda::TrackInfo { - name: "grand masters", + }, + Track { + id: 9u16, + info: TrackInfo { + name: s("grand masters"), max_deciding: 10, decision_deposit: 1 * 3 * CENTS, prepare_period: 30 * MINUTES, @@ -253,9 +259,9 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), + }, ]; - &DATA[..] + DATA.iter().map(Cow::Borrowed) } fn track_for(id: &Self::RuntimeOrigin) -> Result { use super::origins::Origin; @@ -266,7 +272,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { // It is important that this is not available in production! let root: Self::RuntimeOrigin = frame_system::RawOrigin::Root.into(); if &root == id { - return Ok(9) + return Ok(9); } } diff --git a/polkadot/runtime/rococo/src/governance/tracks.rs b/polkadot/runtime/rococo/src/governance/tracks.rs index 3765569f183e0..ac3ce54b8b6c8 100644 --- a/polkadot/runtime/rococo/src/governance/tracks.rs +++ b/polkadot/runtime/rococo/src/governance/tracks.rs @@ -18,10 +18,13 @@ use super::*; +use pallet_referenda::{Curve, Track, TrackInfo}; +use sp_runtime::str_array as s; +use sp_std::borrow::Cow; + const fn percent(x: i32) -> sp_arithmetic::FixedI64 { sp_arithmetic::FixedI64::from_rational(x as u128, 100) } -use pallet_referenda::Curve; const APP_ROOT: Curve = Curve::make_reciprocal(4, 28, percent(80), percent(50), percent(100)); const SUP_ROOT: Curve = Curve::make_linear(28, 28, percent(0), percent(50)); const APP_STAKING_ADMIN: Curve = Curve::make_linear(17, 28, percent(50), percent(100)); @@ -65,11 +68,11 @@ const APP_WHITELISTED_CALLER: Curve = const SUP_WHITELISTED_CALLER: Curve = Curve::make_reciprocal(1, 28, percent(20), percent(5), percent(50)); -const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15] = [ - ( - 0, - pallet_referenda::TrackInfo { - name: "root", +const TRACKS_DATA: [Track; 15] = [ + Track { + id: 0, + info: TrackInfo { + name: s("root"), max_deciding: 1, decision_deposit: 100 * GRAND, prepare_period: 8 * MINUTES, @@ -79,11 +82,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_ROOT, min_support: SUP_ROOT, }, - ), - ( - 1, - pallet_referenda::TrackInfo { - name: "whitelisted_caller", + }, + Track { + id: 1, + info: TrackInfo { + name: s("whitelisted_caller"), max_deciding: 100, decision_deposit: 10 * GRAND, prepare_period: 6 * MINUTES, @@ -93,11 +96,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_WHITELISTED_CALLER, min_support: SUP_WHITELISTED_CALLER, }, - ), - ( - 10, - pallet_referenda::TrackInfo { - name: "staking_admin", + }, + Track { + id: 10, + info: TrackInfo { + name: s("staking_admin"), max_deciding: 10, decision_deposit: 5 * GRAND, prepare_period: 8 * MINUTES, @@ -107,11 +110,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_STAKING_ADMIN, min_support: SUP_STAKING_ADMIN, }, - ), - ( - 11, - pallet_referenda::TrackInfo { - name: "treasurer", + }, + Track { + id: 11, + info: TrackInfo { + name: s("treasurer"), max_deciding: 10, decision_deposit: 1 * GRAND, prepare_period: 8 * MINUTES, @@ -121,11 +124,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_TREASURER, min_support: SUP_TREASURER, }, - ), - ( - 12, - pallet_referenda::TrackInfo { - name: "lease_admin", + }, + Track { + id: 12, + info: TrackInfo { + name: s("lease_admin"), max_deciding: 10, decision_deposit: 5 * GRAND, prepare_period: 8 * MINUTES, @@ -135,11 +138,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_LEASE_ADMIN, min_support: SUP_LEASE_ADMIN, }, - ), - ( - 13, - pallet_referenda::TrackInfo { - name: "fellowship_admin", + }, + Track { + id: 13, + info: TrackInfo { + name: s("fellowship_admin"), max_deciding: 10, decision_deposit: 5 * GRAND, prepare_period: 8 * MINUTES, @@ -149,11 +152,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_FELLOWSHIP_ADMIN, min_support: SUP_FELLOWSHIP_ADMIN, }, - ), - ( - 14, - pallet_referenda::TrackInfo { - name: "general_admin", + }, + Track { + id: 14, + info: TrackInfo { + name: s("general_admin"), max_deciding: 10, decision_deposit: 5 * GRAND, prepare_period: 8 * MINUTES, @@ -163,11 +166,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_GENERAL_ADMIN, min_support: SUP_GENERAL_ADMIN, }, - ), - ( - 15, - pallet_referenda::TrackInfo { - name: "auction_admin", + }, + Track { + id: 15, + info: TrackInfo { + name: s("auction_admin"), max_deciding: 10, decision_deposit: 5 * GRAND, prepare_period: 8 * MINUTES, @@ -177,11 +180,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_AUCTION_ADMIN, min_support: SUP_AUCTION_ADMIN, }, - ), - ( - 20, - pallet_referenda::TrackInfo { - name: "referendum_canceller", + }, + Track { + id: 20, + info: TrackInfo { + name: s("referendum_canceller"), max_deciding: 1_000, decision_deposit: 10 * GRAND, prepare_period: 8 * MINUTES, @@ -191,11 +194,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_REFERENDUM_CANCELLER, min_support: SUP_REFERENDUM_CANCELLER, }, - ), - ( - 21, - pallet_referenda::TrackInfo { - name: "referendum_killer", + }, + Track { + id: 21, + info: TrackInfo { + name: s("referendum_killer"), max_deciding: 1_000, decision_deposit: 50 * GRAND, prepare_period: 8 * MINUTES, @@ -205,11 +208,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_REFERENDUM_KILLER, min_support: SUP_REFERENDUM_KILLER, }, - ), - ( - 30, - pallet_referenda::TrackInfo { - name: "small_tipper", + }, + Track { + id: 30, + info: TrackInfo { + name: s("small_tipper"), max_deciding: 200, decision_deposit: 1 * 3 * CENTS, prepare_period: 1 * MINUTES, @@ -219,11 +222,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_SMALL_TIPPER, min_support: SUP_SMALL_TIPPER, }, - ), - ( - 31, - pallet_referenda::TrackInfo { - name: "big_tipper", + }, + Track { + id: 31, + info: TrackInfo { + name: s("big_tipper"), max_deciding: 100, decision_deposit: 10 * 3 * CENTS, prepare_period: 4 * MINUTES, @@ -233,11 +236,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_BIG_TIPPER, min_support: SUP_BIG_TIPPER, }, - ), - ( - 32, - pallet_referenda::TrackInfo { - name: "small_spender", + }, + Track { + id: 32, + info: TrackInfo { + name: s("small_spender"), max_deciding: 50, decision_deposit: 100 * 3 * CENTS, prepare_period: 10 * MINUTES, @@ -247,11 +250,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_SMALL_SPENDER, min_support: SUP_SMALL_SPENDER, }, - ), - ( - 33, - pallet_referenda::TrackInfo { - name: "medium_spender", + }, + Track { + id: 33, + info: TrackInfo { + name: s("medium_spender"), max_deciding: 50, decision_deposit: 200 * 3 * CENTS, prepare_period: 10 * MINUTES, @@ -261,11 +264,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_MEDIUM_SPENDER, min_support: SUP_MEDIUM_SPENDER, }, - ), - ( - 34, - pallet_referenda::TrackInfo { - name: "big_spender", + }, + Track { + id: 34, + info: TrackInfo { + name: s("big_spender"), max_deciding: 50, decision_deposit: 400 * 3 * CENTS, prepare_period: 10 * MINUTES, @@ -275,15 +278,16 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_BIG_SPENDER, min_support: SUP_BIG_SPENDER, }, - ), + }, ]; pub struct TracksInfo; impl pallet_referenda::TracksInfo for TracksInfo { type Id = u16; type RuntimeOrigin = ::PalletsOrigin; - fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { - &TRACKS_DATA[..] + + fn tracks() -> impl Iterator>> { + TRACKS_DATA.iter().map(Cow::Borrowed) } fn track_for(id: &Self::RuntimeOrigin) -> Result { if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { diff --git a/polkadot/runtime/westend/src/governance/tracks.rs b/polkadot/runtime/westend/src/governance/tracks.rs index 3765569f183e0..d3701440b3104 100644 --- a/polkadot/runtime/westend/src/governance/tracks.rs +++ b/polkadot/runtime/westend/src/governance/tracks.rs @@ -18,10 +18,13 @@ use super::*; +use pallet_referenda::{Curve, Track, TrackInfo}; +use sp_runtime::str_array as s; +use sp_std::borrow::Cow::{self, Borrowed}; + const fn percent(x: i32) -> sp_arithmetic::FixedI64 { sp_arithmetic::FixedI64::from_rational(x as u128, 100) } -use pallet_referenda::Curve; const APP_ROOT: Curve = Curve::make_reciprocal(4, 28, percent(80), percent(50), percent(100)); const SUP_ROOT: Curve = Curve::make_linear(28, 28, percent(0), percent(50)); const APP_STAKING_ADMIN: Curve = Curve::make_linear(17, 28, percent(50), percent(100)); @@ -65,11 +68,11 @@ const APP_WHITELISTED_CALLER: Curve = const SUP_WHITELISTED_CALLER: Curve = Curve::make_reciprocal(1, 28, percent(20), percent(5), percent(50)); -const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15] = [ - ( - 0, - pallet_referenda::TrackInfo { - name: "root", +const TRACKS_DATA: [Track; 15] = [ + Track { + id: 0, + info: TrackInfo { + name: s("root"), max_deciding: 1, decision_deposit: 100 * GRAND, prepare_period: 8 * MINUTES, @@ -79,11 +82,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_ROOT, min_support: SUP_ROOT, }, - ), - ( - 1, - pallet_referenda::TrackInfo { - name: "whitelisted_caller", + }, + Track { + id: 1, + info: TrackInfo { + name: s("whitelisted_caller"), max_deciding: 100, decision_deposit: 10 * GRAND, prepare_period: 6 * MINUTES, @@ -93,11 +96,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_WHITELISTED_CALLER, min_support: SUP_WHITELISTED_CALLER, }, - ), - ( - 10, - pallet_referenda::TrackInfo { - name: "staking_admin", + }, + Track { + id: 10, + info: TrackInfo { + name: s("staking_admin"), max_deciding: 10, decision_deposit: 5 * GRAND, prepare_period: 8 * MINUTES, @@ -107,11 +110,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_STAKING_ADMIN, min_support: SUP_STAKING_ADMIN, }, - ), - ( - 11, - pallet_referenda::TrackInfo { - name: "treasurer", + }, + Track { + id: 11, + info: TrackInfo { + name: s("treasurer"), max_deciding: 10, decision_deposit: 1 * GRAND, prepare_period: 8 * MINUTES, @@ -121,11 +124,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_TREASURER, min_support: SUP_TREASURER, }, - ), - ( - 12, - pallet_referenda::TrackInfo { - name: "lease_admin", + }, + Track { + id: 12, + info: TrackInfo { + name: s("lease_admin"), max_deciding: 10, decision_deposit: 5 * GRAND, prepare_period: 8 * MINUTES, @@ -135,11 +138,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_LEASE_ADMIN, min_support: SUP_LEASE_ADMIN, }, - ), - ( - 13, - pallet_referenda::TrackInfo { - name: "fellowship_admin", + }, + Track { + id: 13, + info: TrackInfo { + name: s("fellowship_admin"), max_deciding: 10, decision_deposit: 5 * GRAND, prepare_period: 8 * MINUTES, @@ -149,11 +152,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_FELLOWSHIP_ADMIN, min_support: SUP_FELLOWSHIP_ADMIN, }, - ), - ( - 14, - pallet_referenda::TrackInfo { - name: "general_admin", + }, + Track { + id: 14, + info: TrackInfo { + name: s("general_admin"), max_deciding: 10, decision_deposit: 5 * GRAND, prepare_period: 8 * MINUTES, @@ -163,11 +166,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_GENERAL_ADMIN, min_support: SUP_GENERAL_ADMIN, }, - ), - ( - 15, - pallet_referenda::TrackInfo { - name: "auction_admin", + }, + Track { + id: 15, + info: TrackInfo { + name: s("auction_admin"), max_deciding: 10, decision_deposit: 5 * GRAND, prepare_period: 8 * MINUTES, @@ -177,11 +180,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_AUCTION_ADMIN, min_support: SUP_AUCTION_ADMIN, }, - ), - ( - 20, - pallet_referenda::TrackInfo { - name: "referendum_canceller", + }, + Track { + id: 20, + info: TrackInfo { + name: s("referendum_canceller"), max_deciding: 1_000, decision_deposit: 10 * GRAND, prepare_period: 8 * MINUTES, @@ -191,11 +194,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_REFERENDUM_CANCELLER, min_support: SUP_REFERENDUM_CANCELLER, }, - ), - ( - 21, - pallet_referenda::TrackInfo { - name: "referendum_killer", + }, + Track { + id: 21, + info: TrackInfo { + name: s("referendum_killer"), max_deciding: 1_000, decision_deposit: 50 * GRAND, prepare_period: 8 * MINUTES, @@ -205,11 +208,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_REFERENDUM_KILLER, min_support: SUP_REFERENDUM_KILLER, }, - ), - ( - 30, - pallet_referenda::TrackInfo { - name: "small_tipper", + }, + Track { + id: 30, + info: TrackInfo { + name: s("small_tipper"), max_deciding: 200, decision_deposit: 1 * 3 * CENTS, prepare_period: 1 * MINUTES, @@ -219,11 +222,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_SMALL_TIPPER, min_support: SUP_SMALL_TIPPER, }, - ), - ( - 31, - pallet_referenda::TrackInfo { - name: "big_tipper", + }, + Track { + id: 31, + info: TrackInfo { + name: s("big_tipper"), max_deciding: 100, decision_deposit: 10 * 3 * CENTS, prepare_period: 4 * MINUTES, @@ -233,11 +236,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_BIG_TIPPER, min_support: SUP_BIG_TIPPER, }, - ), - ( - 32, - pallet_referenda::TrackInfo { - name: "small_spender", + }, + Track { + id: 32, + info: TrackInfo { + name: s("small_spender"), max_deciding: 50, decision_deposit: 100 * 3 * CENTS, prepare_period: 10 * MINUTES, @@ -247,11 +250,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_SMALL_SPENDER, min_support: SUP_SMALL_SPENDER, }, - ), - ( - 33, - pallet_referenda::TrackInfo { - name: "medium_spender", + }, + Track { + id: 33, + info: TrackInfo { + name: s("medium_spender"), max_deciding: 50, decision_deposit: 200 * 3 * CENTS, prepare_period: 10 * MINUTES, @@ -261,11 +264,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_MEDIUM_SPENDER, min_support: SUP_MEDIUM_SPENDER, }, - ), - ( - 34, - pallet_referenda::TrackInfo { - name: "big_spender", + }, + Track { + id: 34, + info: TrackInfo { + name: s("big_spender"), max_deciding: 50, decision_deposit: 400 * 3 * CENTS, prepare_period: 10 * MINUTES, @@ -275,15 +278,16 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 min_approval: APP_BIG_SPENDER, min_support: SUP_BIG_SPENDER, }, - ), + }, ]; pub struct TracksInfo; impl pallet_referenda::TracksInfo for TracksInfo { type Id = u16; type RuntimeOrigin = ::PalletsOrigin; - fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { - &TRACKS_DATA[..] + + fn tracks() -> impl Iterator>> { + TRACKS_DATA.iter().map(Borrowed) } fn track_for(id: &Self::RuntimeOrigin) -> Result { if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 24c8f6f48e96e..3802909930898 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -86,7 +86,7 @@ use sp_inherents::{CheckInherentsResult, InherentData}; use sp_runtime::{ create_runtime_str, curve::PiecewiseLinear, - generic, impl_opaque_keys, + generic, impl_opaque_keys, str_array as s, traits::{ self, AccountIdConversion, BlakeTwo256, Block as BlockT, Bounded, ConvertInto, NumberFor, OpaqueKeys, SaturatedConversion, StaticLookup, @@ -95,7 +95,7 @@ use sp_runtime::{ ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perbill, Percent, Permill, Perquintill, RuntimeDebug, }; -use sp_std::prelude::*; +use sp_std::{borrow::Cow, prelude::*}; #[cfg(any(feature = "std", test))] use sp_version::NativeVersion; use sp_version::RuntimeVersion; @@ -383,21 +383,21 @@ impl InstanceFilter for ProxyType { ProxyType::Any => true, ProxyType::NonTransfer => !matches!( c, - RuntimeCall::Balances(..) | - RuntimeCall::Assets(..) | - RuntimeCall::Uniques(..) | - RuntimeCall::Nfts(..) | - RuntimeCall::Vesting(pallet_vesting::Call::vested_transfer { .. }) | - RuntimeCall::Indices(pallet_indices::Call::transfer { .. }) + RuntimeCall::Balances(..) + | RuntimeCall::Assets(..) + | RuntimeCall::Uniques(..) + | RuntimeCall::Nfts(..) + | RuntimeCall::Vesting(pallet_vesting::Call::vested_transfer { .. }) + | RuntimeCall::Indices(pallet_indices::Call::transfer { .. }) ), ProxyType::Governance => matches!( c, - RuntimeCall::Democracy(..) | - RuntimeCall::Council(..) | - RuntimeCall::Society(..) | - RuntimeCall::TechnicalCommittee(..) | - RuntimeCall::Elections(..) | - RuntimeCall::Treasury(..) + RuntimeCall::Democracy(..) + | RuntimeCall::Council(..) + | RuntimeCall::Society(..) + | RuntimeCall::TechnicalCommittee(..) + | RuntimeCall::Elections(..) + | RuntimeCall::Treasury(..) ), ProxyType::Staking => { matches!(c, RuntimeCall::Staking(..) | RuntimeCall::FastUnstake(..)) @@ -784,8 +784,8 @@ impl Get> for OffchainRandomBalancing { max => { let seed = sp_io::offchain::random_seed(); let random = ::decode(&mut TrailingZeroInput::new(&seed)) - .expect("input is padded with zeroes; qed") % - max.saturating_add(1); + .expect("input is padded with zeroes; qed") + % max.saturating_add(1); random as usize }, }; @@ -934,30 +934,34 @@ pub struct TracksInfo; impl pallet_referenda::TracksInfo for TracksInfo { type Id = u16; type RuntimeOrigin = ::PalletsOrigin; - fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { - static DATA: [(u16, pallet_referenda::TrackInfo); 1] = [( - 0u16, - pallet_referenda::TrackInfo { - name: "root", - max_deciding: 1, - decision_deposit: 10, - prepare_period: 4, - decision_period: 4, - confirm_period: 2, - min_enactment_period: 4, - min_approval: pallet_referenda::Curve::LinearDecreasing { - length: Perbill::from_percent(100), - floor: Perbill::from_percent(50), - ceil: Perbill::from_percent(100), - }, - min_support: pallet_referenda::Curve::LinearDecreasing { - length: Perbill::from_percent(100), - floor: Perbill::from_percent(0), - ceil: Perbill::from_percent(100), + + fn tracks( + ) -> impl Iterator>> + { + static DATA: [pallet_referenda::Track; 1] = + [pallet_referenda::Track { + id: 0u16, + info: pallet_referenda::TrackInfo { + name: s("root"), + max_deciding: 1, + decision_deposit: 10, + prepare_period: 4, + decision_period: 4, + confirm_period: 2, + min_enactment_period: 4, + min_approval: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(50), + ceil: Perbill::from_percent(100), + }, + min_support: pallet_referenda::Curve::LinearDecreasing { + length: Perbill::from_percent(100), + floor: Perbill::from_percent(0), + ceil: Perbill::from_percent(100), + }, }, - }, - )]; - &DATA[..] + }]; + DATA.iter().map(Cow::Borrowed) } fn track_for(id: &Self::RuntimeOrigin) -> Result { if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { @@ -2140,11 +2144,11 @@ impl EnsureOriginWithArg for DynamicParamet match key { RuntimeParametersKey::Storage(_) => { frame_system::ensure_root(origin.clone()).map_err(|_| origin)?; - return Ok(()) + return Ok(()); }, RuntimeParametersKey::Contract(_) => { frame_system::ensure_root(origin.clone()).map_err(|_| origin)?; - return Ok(()) + return Ok(()); }, } } diff --git a/substrate/frame/referenda/src/benchmarking.rs b/substrate/frame/referenda/src/benchmarking.rs index 47d43cc0600c0..bb746b4754e82 100644 --- a/substrate/frame/referenda/src/benchmarking.rs +++ b/substrate/frame/referenda/src/benchmarking.rs @@ -29,6 +29,7 @@ use frame_support::{ }; use frame_system::RawOrigin; use sp_runtime::traits::Bounded as ArithBounded; +use sp_std::borrow::Cow; const SEED: u32 = 0; @@ -105,7 +106,7 @@ fn fill_queue, I: 'static>( others } -fn info, I: 'static>(index: ReferendumIndex) -> &'static TrackInfoOf { +fn info, I: 'static>(index: ReferendumIndex) -> Cow<'static, TrackInfoOf> { let status = Referenda::::ensure_ongoing(index).unwrap(); T::Tracks::info(status.track).expect("Id value returned from T::Tracks") } diff --git a/substrate/frame/referenda/src/lib.rs b/substrate/frame/referenda/src/lib.rs index c5bf2266e6725..8d459ed116f77 100644 --- a/substrate/frame/referenda/src/lib.rs +++ b/substrate/frame/referenda/src/lib.rs @@ -97,7 +97,7 @@ pub use self::{ types::{ BalanceOf, BoundedCallOf, CallOf, Curve, DecidingStatus, DecidingStatusOf, Deposit, InsertSorted, NegativeImbalanceOf, PalletsOriginOf, ReferendumIndex, ReferendumInfo, - ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf, + ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf, Track, TrackIdOf, TrackInfo, TrackInfoOf, TracksInfo, VotesOf, }, weights::WeightInfo, @@ -119,17 +119,25 @@ macro_rules! impl_tracksinfo_get { ($tracksinfo:ty, $balance:ty, $blocknumber:ty) => { impl $crate::Get< - $crate::Vec<( - <$tracksinfo as $crate::TracksInfo<$balance, $blocknumber>>::Id, - $crate::TrackInfo<$balance, $blocknumber>, - )>, + $crate::Vec< + $crate::Track< + <$tracksinfo as $crate::TracksInfo<$balance, $blocknumber>>::Id, + $balance, + $blocknumber, + >, + >, > for $tracksinfo { - fn get() -> $crate::Vec<( - <$tracksinfo as $crate::TracksInfo<$balance, $blocknumber>>::Id, - $crate::TrackInfo<$balance, $blocknumber>, - )> { - <$tracksinfo as $crate::TracksInfo<$balance, $blocknumber>>::tracks().to_vec() + fn get() -> $crate::Vec< + $crate::Track< + <$tracksinfo as $crate::TracksInfo<$balance, $blocknumber>>::Id, + $balance, + $blocknumber, + >, + > { + <$tracksinfo as $crate::TracksInfo<$balance, $blocknumber>>::tracks() + .map(|t: sp_std::borrow::Cow<'static, $crate::Track<_, _, _>>| t.into_owned()) + .collect() } } }; @@ -224,10 +232,13 @@ pub mod pallet { /// Information concerning the different referendum tracks. #[pallet::constant] type Tracks: Get< - Vec<( - , BlockNumberFor>>::Id, - TrackInfo, BlockNumberFor>, - )>, + Vec< + Track< + , BlockNumberFor>>::Id, + BalanceOf, + BlockNumberFor, + >, + >, > + TracksInfo< BalanceOf, BlockNumberFor, @@ -509,7 +520,7 @@ pub mod pallet { let who = ensure_signed(origin)?; let mut status = Self::ensure_ongoing(index)?; ensure!(status.decision_deposit.is_none(), Error::::HasDeposit); - let track = Self::track(status.track).ok_or(Error::::NoTrack)?; + let track = T::Tracks::info(status.track).ok_or(Error::::NoTrack)?; status.decision_deposit = Some(Self::take_deposit(who.clone(), track.decision_deposit)?); let now = frame_system::Pallet::::block_number(); @@ -645,7 +656,7 @@ pub mod pallet { if let Some((index, mut status)) = Self::next_for_deciding(&mut track_queue) { let now = frame_system::Pallet::::block_number(); let (maybe_alarm, branch) = - Self::begin_deciding(&mut status, index, now, track_info); + Self::begin_deciding(&mut status, index, now, &track_info); if let Some(set_alarm) = maybe_alarm { Self::ensure_alarm_at(&mut status, index, set_alarm); } @@ -733,7 +744,7 @@ impl, I: 'static> Polling for Pallet { type Class = TrackIdOf; fn classes() -> Vec { - T::Tracks::tracks().iter().map(|x| x.0).collect() + T::Tracks::tracks_ids() } fn access_poll( @@ -826,10 +837,9 @@ impl, I: 'static> Polling for Pallet { #[cfg(feature = "runtime-benchmarks")] fn max_ongoing() -> (Self::Class, u32) { let r = T::Tracks::tracks() - .iter() - .max_by_key(|(_, info)| info.max_deciding) + .max_by_key(|t| t.info.max_deciding) .expect("Always one class"); - (r.0, r.1.max_deciding) + (r.id, r.info.max_deciding) } } @@ -851,7 +861,7 @@ impl, I: 'static> Pallet { let info = ReferendumInfoFor::::get(ref_index).ok_or(Error::::BadReferendum)?; match info { ReferendumInfo::Ongoing(status) => { - let track = Self::track(status.track).ok_or(Error::::NoTrack)?; + let track = T::Tracks::info(status.track).ok_or(Error::::NoTrack)?; let elapsed = if let Some(deciding) = status.deciding { frame_system::Pallet::::block_number().saturating_sub(deciding.since) } else { @@ -901,8 +911,8 @@ impl, I: 'static> Pallet { let alarm_interval = T::AlarmInterval::get().max(One::one()); // Alarm must go off no earlier than `when`. // This rounds `when` upwards to the next multiple of `alarm_interval`. - let when = (when.saturating_add(alarm_interval.saturating_sub(One::one())) / - alarm_interval) + let when = (when.saturating_add(alarm_interval.saturating_sub(One::one())) + / alarm_interval) .saturating_mul(alarm_interval); let result = T::Scheduler::schedule( DispatchTime::At(when), @@ -1015,7 +1025,7 @@ impl, I: 'static> Pallet { Ok(c) => c, Err(_) => { debug_assert!(false, "Unable to create a bounded call from `one_fewer_deciding`??",); - return + return; }, }; Self::set_alarm(call, next_block); @@ -1042,7 +1052,7 @@ impl, I: 'static> Pallet { false, "Unable to create a bounded call from `nudge_referendum`??", ); - return false + return false; }, }; status.alarm = Self::set_alarm(call, alarm); @@ -1080,7 +1090,7 @@ impl, I: 'static> Pallet { ) -> (ReferendumInfoOf, bool, ServiceBranch) { let mut dirty = false; // Should it begin being decided? - let track = match Self::track(status.track) { + let track = match T::Tracks::info(status.track) { Some(x) => x, None => return (ReferendumInfo::Ongoing(status), false, ServiceBranch::Fail), }; @@ -1116,7 +1126,7 @@ impl, I: 'static> Pallet { let prepare_end = status.submitted.saturating_add(track.prepare_period); if now >= prepare_end { let (maybe_alarm, branch) = - Self::ready_for_deciding(now, track, index, &mut status); + Self::ready_for_deciding(now, &track, index, &mut status); if let Some(set_alarm) = maybe_alarm { alarm = alarm.min(set_alarm); } @@ -1144,7 +1154,7 @@ impl, I: 'static> Pallet { ), true, ServiceBranch::TimedOut, - ) + ); } }, Some(deciding) => { @@ -1163,7 +1173,7 @@ impl, I: 'static> Pallet { Self::ensure_no_alarm(&mut status); Self::note_one_fewer_deciding(status.track); let (desired, call) = (status.enactment, status.proposal); - Self::schedule_enactment(index, track, desired, status.origin, call); + Self::schedule_enactment(index, &track, desired, status.origin, call); Self::deposit_event(Event::::Confirmed { index, tally: status.tally, @@ -1176,7 +1186,7 @@ impl, I: 'static> Pallet { ), true, ServiceBranch::Approved, - ) + ); }, Some(_) => ServiceBranch::ContinueConfirming, None => { @@ -1201,7 +1211,7 @@ impl, I: 'static> Pallet { ), true, ServiceBranch::Rejected, - ) + ); } if deciding.confirming.is_some() { // Stop confirming @@ -1213,7 +1223,7 @@ impl, I: 'static> Pallet { ServiceBranch::ContinueNotConfirming } }; - alarm = Self::decision_time(deciding, &status.tally, status.track, track); + alarm = Self::decision_time(deciding, &status.tally, status.track, &track); }, } @@ -1279,13 +1289,6 @@ impl, I: 'static> Pallet { } } - /// Get the track info value for the track `id`. - fn track(id: TrackIdOf) -> Option<&'static TrackInfoOf> { - let tracks = T::Tracks::tracks(); - let index = tracks.binary_search_by_key(&id, |x| x.0).unwrap_or_else(|x| x); - Some(&tracks[index].1) - } - /// Determine whether the given `tally` would result in a referendum passing at `elapsed` blocks /// into a total decision `period`, given the two curves for `support_needed` and /// `approval_needed`. @@ -1298,8 +1301,8 @@ impl, I: 'static> Pallet { id: TrackIdOf, ) -> bool { let x = Perbill::from_rational(elapsed.min(period), period); - support_needed.passing(x, tally.support(id)) && - approval_needed.passing(x, tally.approval(id)) + support_needed.passing(x, tally.support(id)) + && approval_needed.passing(x, tally.approval(id)) } /// Clear metadata if exist for a given referendum index. @@ -1321,8 +1324,8 @@ impl, I: 'static> Pallet { #[cfg(any(feature = "try-runtime", test))] fn do_try_state() -> Result<(), sp_runtime::TryRuntimeError> { ensure!( - ReferendumCount::::get() as usize == - ReferendumInfoFor::::iter_keys().count(), + ReferendumCount::::get() as usize + == ReferendumInfoFor::::iter_keys().count(), "Number of referenda in `ReferendumInfoFor` is different than `ReferendumCount`" ); @@ -1354,14 +1357,14 @@ impl, I: 'static> Pallet { match referendum { ReferendumInfo::Ongoing(status) => { ensure!( - Self::track(status.track).is_some(), + T::Tracks::info(status.track).is_some(), "No track info for the track of the referendum." ); if let Some(deciding) = status.deciding { ensure!( - deciding.since < - deciding.confirming.unwrap_or(BlockNumberFor::::max_value()), + deciding.since + < deciding.confirming.unwrap_or(BlockNumberFor::::max_value()), "Deciding status cannot begin before confirming stage." ) } @@ -1378,8 +1381,8 @@ impl, I: 'static> Pallet { /// [`ReferendumInfoFor`] storage map. #[cfg(any(feature = "try-runtime", test))] fn try_state_tracks() -> Result<(), sp_runtime::TryRuntimeError> { - T::Tracks::tracks().iter().try_for_each(|track| { - TrackQueue::::get(track.0).iter().try_for_each( + T::Tracks::tracks().try_for_each(|track| { + TrackQueue::::get(track.id).iter().try_for_each( |(referendum_index, _)| -> Result<(), sp_runtime::TryRuntimeError> { ensure!( ReferendumInfoFor::::contains_key(referendum_index), diff --git a/substrate/frame/referenda/src/mock.rs b/substrate/frame/referenda/src/mock.rs index bfafc107c28bc..f9b47d144ca63 100644 --- a/substrate/frame/referenda/src/mock.rs +++ b/substrate/frame/referenda/src/mock.rs @@ -18,7 +18,7 @@ //! The crate's tests. use super::*; -use crate as pallet_referenda; +use crate::{self as pallet_referenda, types::Track}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ assert_ok, derive_impl, ord_parameter_types, parameter_types, @@ -30,9 +30,11 @@ use frame_support::{ }; use frame_system::{EnsureRoot, EnsureSignedBy}; use sp_runtime::{ + str_array as s, traits::{BlakeTwo256, Hash}, BuildStorage, DispatchResult, Perbill, }; +use sp_std::borrow::Cow; type Block = frame_system::mocking::MockBlock; @@ -122,12 +124,13 @@ pub struct TestTracksInfo; impl TracksInfo for TestTracksInfo { type Id = u8; type RuntimeOrigin = ::PalletsOrigin; - fn tracks() -> &'static [(Self::Id, TrackInfo)] { - static DATA: [(u8, TrackInfo); 2] = [ - ( - 0u8, - TrackInfo { - name: "root", + + fn tracks() -> impl Iterator>> { + static DATA: [Track; 2] = [ + Track { + id: 0u8, + info: TrackInfo { + name: s("root"), max_deciding: 1, decision_deposit: 10, prepare_period: 4, @@ -145,11 +148,11 @@ impl TracksInfo for TestTracksInfo { ceil: Perbill::from_percent(100), }, }, - ), - ( - 1u8, - TrackInfo { - name: "none", + }, + Track { + id: 1u8, + info: TrackInfo { + name: s("none"), max_deciding: 3, decision_deposit: 1, prepare_period: 2, @@ -167,9 +170,9 @@ impl TracksInfo for TestTracksInfo { ceil: Perbill::from_percent(100), }, }, - ), + }, ]; - &DATA[..] + DATA.iter().map(Cow::Borrowed) } fn track_for(id: &Self::RuntimeOrigin) -> Result { if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { diff --git a/substrate/frame/referenda/src/tests.rs b/substrate/frame/referenda/src/tests.rs index 8f51136de0bfd..d8166fd270230 100644 --- a/substrate/frame/referenda/src/tests.rs +++ b/substrate/frame/referenda/src/tests.rs @@ -289,11 +289,12 @@ fn alarm_interval_works() { fn decision_time_is_correct() { ExtBuilder::default().build_and_execute(|| { let decision_time = |since: u64| { + let track = TestTracksInfo::tracks().into_iter().next().unwrap(); Pallet::::decision_time( &DecidingStatus { since: since.into(), confirming: None }, &Tally { ayes: 100, nays: 5 }, - TestTracksInfo::tracks()[0].0, - &TestTracksInfo::tracks()[0].1, + track.id, + &track.info, ) }; diff --git a/substrate/frame/referenda/src/types.rs b/substrate/frame/referenda/src/types.rs index b3c583322cce3..47a6a1774dd2f 100644 --- a/substrate/frame/referenda/src/types.rs +++ b/substrate/frame/referenda/src/types.rs @@ -19,7 +19,6 @@ use super::*; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; -use core::fmt::Debug; use frame_support::{ traits::{schedule::v3::Anon, Bounded}, Parameter, @@ -27,6 +26,7 @@ use frame_support::{ use scale_info::TypeInfo; use sp_arithmetic::{Rounding::*, SignedRounding::*}; use sp_runtime::{FixedI64, PerThing, RuntimeDebug}; +use sp_std::{borrow::Cow, fmt::Debug}; pub type BalanceOf = <>::Currency as Currency<::AccountId>>::Balance; @@ -111,10 +111,12 @@ pub struct Deposit { pub amount: Balance, } -#[derive(Clone, Encode, TypeInfo)] -pub struct TrackInfo { +const DEFAULT_MAX_TRACK_NAME_LEN: usize = 25; + +#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo)] +pub struct TrackInfo { /// Name of this track. - pub name: &'static str, + pub name: [u8; N], /// A limit for the number of referenda on this track that can be being decided at once. /// For Root origin this should generally be just one. pub max_deciding: u32, @@ -136,29 +138,44 @@ pub struct TrackInfo { pub min_support: Curve, } +#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo)] +pub struct Track { + pub id: Id, + pub info: TrackInfo, +} + /// Information on the voting tracks. -pub trait TracksInfo { +pub trait TracksInfo +where + Balance: Clone + 'static, + Moment: Clone + 'static, +{ /// The identifier for a track. type Id: Copy + Parameter + Ord + PartialOrd + Send + Sync + 'static + MaxEncodedLen; /// The origin type from which a track is implied. type RuntimeOrigin; - /// Sorted array of known tracks and their information. + /// Return the sorted iterable list of known tracks and their information. /// - /// The array MUST be sorted by `Id`. Consumers of this trait are advised to assert + /// The iterator MUST be sorted by `Id`. Consumers of this trait are advised to assert /// [`Self::check_integrity`] prior to any use. - fn tracks() -> &'static [(Self::Id, TrackInfo)]; + fn tracks() -> impl Iterator>>; /// Determine the voting track for the given `origin`. fn track_for(origin: &Self::RuntimeOrigin) -> Result; - /// Return the track info for track `id`, by default this just looks it up in `Self::tracks()`. - fn info(id: Self::Id) -> Option<&'static TrackInfo> { - let tracks = Self::tracks(); - let maybe_index = tracks.binary_search_by_key(&id, |t| t.0).ok()?; + /// Return the list of identifiers of the known tracks. + fn tracks_ids() -> Vec { + Self::tracks().map(|x| x.id).collect() + } - tracks.get(maybe_index).map(|(_, info)| info) + /// Return the track info for track `id`, by default this just looks it up in `Self::tracks()`. + fn info(id: Self::Id) -> Option>> { + Self::tracks().into_iter().find(|x| x.id == id).map(|t| match t { + Cow::Borrowed(x) => Cow::Borrowed(&x.info), + Cow::Owned(x) => Cow::Owned(x.info), + }) } /// Check assumptions about the static data that this trait provides. @@ -167,11 +184,24 @@ pub trait TracksInfo { Balance: 'static, Moment: 'static, { - if Self::tracks().windows(2).all(|w| w[0].0 < w[1].0) { - Ok(()) - } else { - Err("The tracks that were returned by `tracks` were not sorted by `Id`") - } + use core::cmp::Ordering; + // Adapted from Iterator::is_sorted implementation available in nightly + // https://github.com/rust-lang/rust/issues/53485 + let mut iter = Self::tracks(); + let mut last = match iter.next() { + Some(ref e) => e.id, + None => return Ok(()), + }; + iter.all(|curr| { + let curr = curr.as_ref().id; + if let Some(Ordering::Greater) | None = last.partial_cmp(&curr) { + return false; + } + last = curr; + true + }) + .then_some(()) + .ok_or("The tracks that were returned by `tracks` were not sorted by `Id`") } } @@ -268,8 +298,9 @@ impl< Ongoing(x) if x.decision_deposit.is_none() => Ok(None), // Cannot refund deposit if Ongoing as this breaks assumptions. Ongoing(_) => Err(()), - Approved(_, _, d) | Rejected(_, _, d) | TimedOut(_, _, d) | Cancelled(_, _, d) => - Ok(d.take()), + Approved(_, _, d) | Rejected(_, _, d) | TimedOut(_, _, d) | Cancelled(_, _, d) => { + Ok(d.take()) + }, Killed(_) => Ok(None), } } @@ -441,10 +472,12 @@ impl Curve { /// Determine the `y` value for the given `x` value. pub fn threshold(&self, x: Perbill) -> Perbill { match self { - Self::LinearDecreasing { length, floor, ceil } => - *ceil - (x.min(*length).saturating_div(*length, Down) * (*ceil - *floor)), - Self::SteppedDecreasing { begin, end, step, period } => - (*begin - (step.int_mul(x.int_div(*period))).min(*begin)).max(*end), + Self::LinearDecreasing { length, floor, ceil } => { + *ceil - (x.min(*length).saturating_div(*length, Down) * (*ceil - *floor)) + }, + Self::SteppedDecreasing { begin, end, step, period } => { + (*begin - (step.int_mul(x.int_div(*period))).min(*begin)).max(*end) + }, Self::Reciprocal { factor, x_offset, y_offset } => factor .checked_rounding_div(FixedI64::from(x) + *x_offset, Low) .map(|yp| (yp + *y_offset).into_clamped_perthing()) @@ -483,20 +516,22 @@ impl Curve { /// ``` pub fn delay(&self, y: Perbill) -> Perbill { match self { - Self::LinearDecreasing { length, floor, ceil } => + Self::LinearDecreasing { length, floor, ceil } => { if y < *floor { Perbill::one() } else if y > *ceil { Perbill::zero() } else { (*ceil - y).saturating_div(*ceil - *floor, Up).saturating_mul(*length) - }, - Self::SteppedDecreasing { begin, end, step, period } => + } + }, + Self::SteppedDecreasing { begin, end, step, period } => { if y < *end { Perbill::one() } else { period.int_mul((*begin - y.min(*begin) + step.less_epsilon()).int_div(*step)) - }, + } + }, Self::Reciprocal { factor, x_offset, y_offset } => { let y = FixedI64::from(y); let maybe_term = factor.checked_rounding_div(y - *y_offset, High); @@ -546,7 +581,7 @@ impl Debug for Curve { mod tests { use super::*; use frame_support::traits::ConstU32; - use sp_runtime::PerThing; + use sp_runtime::{str_array as s, PerThing}; const fn percent(x: u128) -> FixedI64 { FixedI64::from_rational(x, 100) @@ -698,12 +733,12 @@ mod tests { impl TracksInfo for BadTracksInfo { type Id = u8; type RuntimeOrigin = ::PalletsOrigin; - fn tracks() -> &'static [(Self::Id, TrackInfo)] { - static DATA: [(u8, TrackInfo); 2] = [ - ( - 1u8, - TrackInfo { - name: "root", + fn tracks() -> impl Iterator>> { + static DATA: [Track; 2] = [ + Track { + id: 1u8, + info: TrackInfo { + name: s("root"), max_deciding: 1, decision_deposit: 10, prepare_period: 4, @@ -721,11 +756,11 @@ mod tests { ceil: Perbill::from_percent(100), }, }, - ), - ( - 0u8, - TrackInfo { - name: "none", + }, + Track { + id: 0u8, + info: TrackInfo { + name: s("none"), max_deciding: 3, decision_deposit: 1, prepare_period: 2, @@ -743,9 +778,9 @@ mod tests { ceil: Perbill::from_percent(100), }, }, - ), + }, ]; - &DATA[..] + DATA.iter().map(Cow::Borrowed) } fn track_for(_: &Self::RuntimeOrigin) -> Result { unimplemented!()