From 0c15d965e1e9f8305e00213411dff009ef5f101c 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. NOTE: This feature will benefit from the soon to be released return_position_impl_trait_in_trait(https://github.com/rust-lang/rust/pull/115822) to not require the `TracksIter` associated type and from a bugfix in the compiler(https://github.com/rust-lang/rust/issues/116662) to declare the DEFAULT_MAX_TRACK_NAME_LEN generic constant in the `TracksInfo` trait. --- .../src/ambassador/tracks.rs | 104 ++++---- .../src/fellowship/tracks.rs | 222 +++++++++--------- .../rococo/src/governance/fellowship.rs | 118 +++++----- .../runtime/rococo/src/governance/tracks.rs | 163 ++++++------- .../runtime/westend/src/governance/tracks.rs | 163 ++++++------- substrate/bin/node/runtime/src/lib.rs | 53 +++-- substrate/frame/referenda/src/benchmarking.rs | 3 +- substrate/frame/referenda/src/lib.rs | 75 +++--- substrate/frame/referenda/src/mock.rs | 35 +-- substrate/frame/referenda/src/tests.rs | 5 +- substrate/frame/referenda/src/types.rs | 47 +++- 11 files changed, 529 insertions(+), 459 deletions(-) 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 d4a2d3bbf1c7..7bf79027d2e3 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::{StaticTracksIter, Track}; +use sp_runtime::{str_array as s, Perbill}; +use sp_std::borrow::Cow::Borrowed; /// Referendum `TrackId` type. pub type TrackId = u16; @@ -46,13 +48,15 @@ impl pallet_referenda::TracksInfo for TracksInfo { type RuntimeOrigin = ::PalletsOrigin; + type TracksIter = StaticTracksIter; + /// 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", + 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, @@ -70,11 +74,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), - ( - constants::AMBASSADOR_TIER_2, - pallet_referenda::TrackInfo { - name: "ambassador tier 2", + }, + 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, @@ -92,11 +96,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { 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: pallet_referenda::TrackInfo { + name: s("senior ambassador tier 3"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, @@ -114,11 +118,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { 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: pallet_referenda::TrackInfo { + name: s("senior ambassador tier 4"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, @@ -136,11 +140,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { 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: pallet_referenda::TrackInfo { + name: s("head ambassador tier 5"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, @@ -158,11 +162,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { 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: pallet_referenda::TrackInfo { + name: s("head ambassador tier 6"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, @@ -180,11 +184,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { 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: pallet_referenda::TrackInfo { + name: s("head ambassador tier 7"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, @@ -202,11 +206,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { 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: pallet_referenda::TrackInfo { + name: s("master ambassador tier 8"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, @@ -224,11 +228,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { 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: pallet_referenda::TrackInfo { + name: s("master ambassador tier 9"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 24 * HOURS, @@ -246,9 +250,9 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), + }, ]; - &DATA[..] + DATA.iter().map(Borrowed) } /// Determine the voting track for the given `origin`. @@ -259,7 +263,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(constants::MASTER_AMBASSADOR_TIER_9) + return Ok(constants::MASTER_AMBASSADOR_TIER_9); } } 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 099bdf4cf753..dca83bbd41c6 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::{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; @@ -114,13 +116,15 @@ 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: pallet_referenda::TrackInfo { + name: s("members"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, @@ -138,11 +142,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::PROFICIENTS, - pallet_referenda::TrackInfo { - name: "proficient members", + }, + Track { + id: tracks::PROFICIENTS, + info: pallet_referenda::TrackInfo { + name: s("proficient members"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, @@ -160,11 +164,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::FELLOWS, - pallet_referenda::TrackInfo { - name: "fellows", + }, + Track { + id: tracks::FELLOWS, + info: pallet_referenda::TrackInfo { + name: s("fellows"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, @@ -182,11 +186,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::ARCHITECTS, - pallet_referenda::TrackInfo { - name: "architects", + }, + Track { + id: tracks::ARCHITECTS, + info: pallet_referenda::TrackInfo { + name: s("architects"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, @@ -204,11 +208,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::ARCHITECTS_ADEPT, - pallet_referenda::TrackInfo { - name: "architects adept", + }, + Track { + id: tracks::ARCHITECTS_ADEPT, + info: pallet_referenda::TrackInfo { + name: s("architects adept"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, @@ -226,11 +230,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::GRAND_ARCHITECTS, - pallet_referenda::TrackInfo { - name: "grand architects", + }, + Track { + id: tracks::GRAND_ARCHITECTS, + info: pallet_referenda::TrackInfo { + name: s("grand architects"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, @@ -248,11 +252,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::MASTERS, - pallet_referenda::TrackInfo { - name: "masters", + }, + Track { + id: tracks::MASTERS, + info: pallet_referenda::TrackInfo { + name: s("masters"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, @@ -270,11 +274,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::MASTERS_CONSTANT, - pallet_referenda::TrackInfo { - name: "masters constant", + }, + Track { + id: tracks::MASTERS_CONSTANT, + info: pallet_referenda::TrackInfo { + name: s("masters constant"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, @@ -292,11 +296,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::GRAND_MASTERS, - pallet_referenda::TrackInfo { - name: "grand masters", + }, + Track { + id: tracks::GRAND_MASTERS, + info: pallet_referenda::TrackInfo { + name: s("grand masters"), max_deciding: 10, decision_deposit: 5 * DOLLARS, prepare_period: 30 * MINUTES, @@ -314,11 +318,11 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(100), }, }, - ), - ( - tracks::RETAIN_AT_1DAN, - pallet_referenda::TrackInfo { - name: "retain at I Dan", + }, + 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, @@ -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: pallet_referenda::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: pallet_referenda::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: pallet_referenda::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: pallet_referenda::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: pallet_referenda::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: pallet_referenda::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: pallet_referenda::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: pallet_referenda::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: pallet_referenda::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: pallet_referenda::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: pallet_referenda::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 b5df6cf2df34..d5781bce3d6a 100644 --- a/polkadot/runtime/rococo/src/governance/fellowship.rs +++ b/polkadot/runtime/rococo/src/governance/fellowship.rs @@ -17,7 +17,13 @@ //! Elements of governance concerning the Rococo Fellowship. use frame_support::traits::{MapSuccess, TryMapSuccess}; -use sp_runtime::traits::{CheckedReduceBy, ConstU16, Replace}; +use pallet_referenda::{StaticTracksIter, Track, TrackInfo}; +use sp_arithmetic::traits::CheckedSub; +use sp_runtime::{ + morph_types, str_array as s, + traits::{CheckedReduceBy, ConstU16, Replace, TypedGet}, +}; +use sp_std::borrow::Cow::Borrowed; use super::*; use crate::{CENTS, DAYS}; @@ -32,12 +38,14 @@ 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", + type TracksIter = StaticTracksIter; + + fn tracks() -> Self::TracksIter { + 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 +63,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 +85,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 +107,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 +129,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 +151,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 +173,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 +195,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 +217,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 +239,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 +261,9 @@ impl pallet_referenda::TracksInfo for TracksInfo { ceil: Perbill::from_percent(50), }, }, - ), + }, ]; - &DATA[..] + DATA.iter().map(Borrowed) } fn track_for(id: &Self::RuntimeOrigin) -> Result { use super::origins::Origin; @@ -266,7 +274,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 3765569f183e..993bb5454a3e 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, StaticTracksIter, Track, TrackInfo}; +use sp_runtime::str_array as s; +use sp_std::borrow::Cow::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,17 @@ 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[..] + type TracksIter = StaticTracksIter; + + fn tracks() -> Self::TracksIter { + 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/polkadot/runtime/westend/src/governance/tracks.rs b/polkadot/runtime/westend/src/governance/tracks.rs index 3765569f183e..993bb5454a3e 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, StaticTracksIter, Track, TrackInfo}; +use sp_runtime::str_array as s; +use sp_std::borrow::Cow::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,17 @@ 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[..] + type TracksIter = StaticTracksIter; + + fn tracks() -> Self::TracksIter { + 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 af41b39c520f..80d7e7c8bb6c 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -76,7 +76,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, @@ -85,7 +85,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; @@ -916,30 +916,33 @@ 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), + type TracksIter = pallet_referenda::StaticTracksIter; + + fn tracks() -> Self::TracksIter { + 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), + }, }, - 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()) { diff --git a/substrate/frame/referenda/src/benchmarking.rs b/substrate/frame/referenda/src/benchmarking.rs index 47d43cc0600c..bb746b4754e8 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 8912f9ad2173..8794bdbd7e7b 100644 --- a/substrate/frame/referenda/src/lib.rs +++ b/substrate/frame/referenda/src/lib.rs @@ -97,8 +97,8 @@ pub use self::{ types::{ BalanceOf, BoundedCallOf, CallOf, Curve, DecidingStatus, DecidingStatusOf, Deposit, InsertSorted, NegativeImbalanceOf, PalletsOriginOf, ReferendumIndex, ReferendumInfo, - ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf, - TrackIdOf, TrackInfo, TrackInfoOf, TracksInfo, VotesOf, + ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, + StaticTracksIter, 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(sp_std::borrow::Cow::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, @@ -504,7 +515,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(); @@ -640,7 +651,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); } @@ -728,7 +739,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( @@ -821,10 +832,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) } } @@ -846,7 +856,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 { @@ -1075,7 +1085,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), }; @@ -1111,7 +1121,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); } @@ -1158,7 +1168,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, @@ -1208,7 +1218,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); }, } @@ -1274,13 +1284,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`. @@ -1349,7 +1352,7 @@ 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." ); @@ -1373,8 +1376,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 b75558723e9b..2c2640bdcc66 100644 --- a/substrate/frame/referenda/src/mock.rs +++ b/substrate/frame/referenda/src/mock.rs @@ -18,7 +18,10 @@ //! The crate's tests. use super::*; -use crate as pallet_referenda; +use crate::{ + self as pallet_referenda, + types::{StaticTracksIter, Track}, +}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ assert_ok, derive_impl, ord_parameter_types, parameter_types, @@ -31,9 +34,11 @@ use frame_support::{ use frame_system::{EnsureRoot, EnsureSignedBy}; use sp_core::H256; use sp_runtime::{ + str_array as s, traits::{BlakeTwo256, Hash, IdentityLookup}, BuildStorage, DispatchResult, Perbill, }; +use sp_std::borrow::Cow; type Block = frame_system::mocking::MockBlock; @@ -144,12 +149,14 @@ 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", + type TracksIter = StaticTracksIter; + + fn tracks() -> Self::TracksIter { + static DATA: [Track; 2] = [ + Track { + id: 0u8, + info: TrackInfo { + name: s("root"), max_deciding: 1, decision_deposit: 10, prepare_period: 4, @@ -167,11 +174,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, @@ -189,9 +196,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 8f51136de0bf..d8166fd27023 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 8d6a13ef27c9..9b561947e6ca 100644 --- a/substrate/frame/referenda/src/types.rs +++ b/substrate/frame/referenda/src/types.rs @@ -26,7 +26,7 @@ use frame_support::{ use scale_info::TypeInfo; use sp_arithmetic::{Rounding::*, SignedRounding::*}; use sp_runtime::{FixedI64, PerThing, RuntimeDebug}; -use sp_std::fmt::Debug; +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,23 +138,50 @@ pub struct TrackInfo { pub min_support: Curve, } +#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo)] +pub struct Track { + pub id: Id, + pub info: TrackInfo, +} + +/// Iterator for the common use-case of tracks defined as static arrays +pub type StaticTracksIter = core::iter::Map< + core::slice::Iter<'static, Track>, + fn(&'static Track) -> Cow<'static, Track>, +>; + /// 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; - /// Return the array of known tracks and their information. - fn tracks() -> &'static [(Self::Id, TrackInfo)]; + /// The iterator returned by [`Self::tracks()`] to lazily traverse the available tracks + type TracksIter: Iterator>>; + + /// Return the iterable list of known tracks and their information. + fn tracks() -> Self::TracksIter; /// Determine the voting track for the given `origin`. fn track_for(origin: &Self::RuntimeOrigin) -> Result; + /// Return the list of identifiers of the known tracks. + fn tracks_ids() -> Vec { + Self::tracks().map(|x| x.id).collect() + } + /// 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> { - Self::tracks().iter().find(|x| x.0 == id).map(|x| &x.1) + 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), + }) } }