referrerpolicy=no-referrer-when-downgrade

collectives_westend_runtime/fellowship/
origins.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3// SPDX-License-Identifier: Apache-2.0
4
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// 	http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17//! Fellowship custom origins.
18
19use super::ranks;
20pub use pallet_origins::*;
21
22#[frame_support::pallet]
23pub mod pallet_origins {
24	use super::ranks;
25	use frame_support::pallet_prelude::*;
26	use pallet_ranked_collective::Rank;
27
28	#[pallet::config]
29	pub trait Config: frame_system::Config {}
30
31	#[pallet::pallet]
32	pub struct Pallet<T>(_);
33
34	#[derive(
35		PartialEq,
36		Eq,
37		Clone,
38		MaxEncodedLen,
39		Encode,
40		Decode,
41		DecodeWithMemTracking,
42		TypeInfo,
43		RuntimeDebug,
44	)]
45	#[pallet::origin]
46	pub enum Origin {
47		/// Origin aggregated through weighted votes of those with rank 1 or above; `Success` is 1.
48		/// Aka the "voice" of all Members.
49		Members,
50		/// Origin aggregated through weighted votes of those with rank 2 or above; `Success` is 2.
51		/// Aka the "voice" of members at least II Dan.
52		Fellowship2Dan,
53		/// Origin aggregated through weighted votes of those with rank 3 or above; `Success` is 3.
54		/// Aka the "voice" of all Fellows.
55		Fellows,
56		/// Origin aggregated through weighted votes of those with rank 4 or above; `Success` is 4.
57		/// Aka the "voice" of members at least IV Dan.
58		Architects,
59		/// Origin aggregated through weighted votes of those with rank 5 or above; `Success` is 5.
60		/// Aka the "voice" of members at least V Dan.
61		Fellowship5Dan,
62		/// Origin aggregated through weighted votes of those with rank 6 or above; `Success` is 6.
63		/// Aka the "voice" of members at least VI Dan.
64		Fellowship6Dan,
65		/// Origin aggregated through weighted votes of those with rank 7 or above; `Success` is 7.
66		/// Aka the "voice" of all Masters.
67		Masters,
68		/// Origin aggregated through weighted votes of those with rank 8 or above; `Success` is 8.
69		/// Aka the "voice" of members at least VIII Dan.
70		Fellowship8Dan,
71		/// Origin aggregated through weighted votes of those with rank 9 or above; `Success` is 9.
72		/// Aka the "voice" of members at least IX Dan.
73		Fellowship9Dan,
74
75		/// Origin aggregated through weighted votes of those with rank 3 or above when voting on
76		/// a fortnight-long track; `Success` is 1.
77		RetainAt1Dan,
78		/// Origin aggregated through weighted votes of those with rank 4 or above when voting on
79		/// a fortnight-long track; `Success` is 2.
80		RetainAt2Dan,
81		/// Origin aggregated through weighted votes of those with rank 5 or above when voting on
82		/// a fortnight-long track; `Success` is 3.
83		RetainAt3Dan,
84		/// Origin aggregated through weighted votes of those with rank 6 or above when voting on
85		/// a fortnight-long track; `Success` is 4.
86		RetainAt4Dan,
87		/// Origin aggregated through weighted votes of those with rank 7 or above when voting on
88		/// a fortnight-long track; `Success` is 5.
89		RetainAt5Dan,
90		/// Origin aggregated through weighted votes of those with rank 8 or above when voting on
91		/// a fortnight-long track; `Success` is 6.
92		RetainAt6Dan,
93
94		/// Origin aggregated through weighted votes of those with rank 3 or above when voting on
95		/// a month-long track; `Success` is 1.
96		PromoteTo1Dan,
97		/// Origin aggregated through weighted votes of those with rank 4 or above when voting on
98		/// a month-long track; `Success` is 2.
99		PromoteTo2Dan,
100		/// Origin aggregated through weighted votes of those with rank 5 or above when voting on
101		/// a month-long track; `Success` is 3.
102		PromoteTo3Dan,
103		/// Origin aggregated through weighted votes of those with rank 6 or above when voting on
104		/// a month-long track; `Success` is 4.
105		PromoteTo4Dan,
106		/// Origin aggregated through weighted votes of those with rank 7 or above when voting on
107		/// a month-long track; `Success` is 5.
108		PromoteTo5Dan,
109		/// Origin aggregated through weighted votes of those with rank 8 or above when voting on
110		/// a month-long track; `Success` is 6.
111		PromoteTo6Dan,
112	}
113
114	impl Origin {
115		/// Returns the rank that the origin `self` speaks for, or `None` if it doesn't speak for
116		/// any.
117		///
118		/// `Some` will be returned only for the first 9 elements of [Origin].
119		pub fn as_voice(&self) -> Option<pallet_ranked_collective::Rank> {
120			Some(match &self {
121				Origin::Members => ranks::DAN_1,
122				Origin::Fellowship2Dan => ranks::DAN_2,
123				Origin::Fellows => ranks::DAN_3,
124				Origin::Architects => ranks::DAN_4,
125				Origin::Fellowship5Dan => ranks::DAN_5,
126				Origin::Fellowship6Dan => ranks::DAN_6,
127				Origin::Masters => ranks::DAN_7,
128				Origin::Fellowship8Dan => ranks::DAN_8,
129				Origin::Fellowship9Dan => ranks::DAN_9,
130				_ => return None,
131			})
132		}
133	}
134
135	/// A `TryMorph` implementation which is designed to convert an aggregate `RuntimeOrigin`
136	/// value into the Fellowship voice it represents if it is a Fellowship pallet origin an
137	/// appropriate variant. See also [Origin::as_voice].
138	pub struct ToVoice;
139	impl<'a, O: 'a + TryInto<&'a Origin>> sp_runtime::traits::TryMorph<O> for ToVoice {
140		type Outcome = pallet_ranked_collective::Rank;
141		fn try_morph(o: O) -> Result<pallet_ranked_collective::Rank, ()> {
142			o.try_into().ok().and_then(Origin::as_voice).ok_or(())
143		}
144	}
145
146	macro_rules! decl_unit_ensures {
147		( $name:ident: $success_type:ty = $success:expr ) => {
148			pub struct $name;
149			impl<O: OriginTrait + From<Origin>> EnsureOrigin<O> for $name
150			where
151				for <'a> &'a O::PalletsOrigin: TryInto<&'a Origin>,
152			{
153				type Success = $success_type;
154				fn try_origin(o: O) -> Result<Self::Success, O> {
155					match o.caller().try_into() {
156						Ok(Origin::$name) => return Ok($success),
157						_ => (),
158					}
159
160					Err(o)
161				}
162				#[cfg(feature = "runtime-benchmarks")]
163				fn try_successful_origin() -> Result<O, ()> {
164					Ok(O::from(Origin::$name))
165				}
166			}
167		};
168		( $name:ident ) => { decl_unit_ensures! { $name : () = () } };
169		( $name:ident: $success_type:ty = $success:expr, $( $rest:tt )* ) => {
170			decl_unit_ensures! { $name: $success_type = $success }
171			decl_unit_ensures! { $( $rest )* }
172		};
173		( $name:ident, $( $rest:tt )* ) => {
174			decl_unit_ensures! { $name }
175			decl_unit_ensures! { $( $rest )* }
176		};
177		() => {}
178	}
179	decl_unit_ensures!(
180		Members: Rank = ranks::DAN_1,
181		Fellows: Rank = ranks::DAN_3,
182		Architects: Rank = ranks::DAN_4,
183		Masters: Rank = ranks::DAN_7,
184	);
185
186	macro_rules! decl_ensure {
187		(
188			$vis:vis type $name:ident: EnsureOrigin<Success = $success_type:ty> {
189				$( $item:ident = $success:expr, )*
190			}
191		) => {
192			$vis struct $name;
193			impl<O: OriginTrait + From<Origin>> EnsureOrigin<O> for $name
194			where
195				for <'a> &'a O::PalletsOrigin: TryInto<&'a Origin>,
196			{
197				type Success = $success_type;
198				fn try_origin(o: O) -> Result<Self::Success, O> {
199					match o.caller().try_into() {
200						$(
201							Ok(Origin::$item) => return Ok($success),
202						)*
203						_ => (),
204					}
205
206					Err(o)
207				}
208				#[cfg(feature = "runtime-benchmarks")]
209				fn try_successful_origin() -> Result<O, ()> {
210					// By convention the more privileged origins go later, so for greatest chance
211					// of success, we want the last one.
212					let _result: Result<O, ()> = Err(());
213					$(
214						let _result: Result<O, ()> = Ok(O::from(Origin::$item));
215					)*
216					_result
217				}
218			}
219		}
220	}
221
222	// Fellowship origin indicating weighted voting from at least the rank of `Success` on a
223	// week-long track.
224	decl_ensure! {
225		pub type EnsureFellowship: EnsureOrigin<Success = Rank> {
226			Members = ranks::DAN_1,
227			Fellowship2Dan = ranks::DAN_2,
228			Fellows = ranks::DAN_3,
229			Architects = ranks::DAN_4,
230			Fellowship5Dan = ranks::DAN_5,
231			Fellowship6Dan = ranks::DAN_6,
232			Masters = ranks::DAN_7,
233			Fellowship8Dan = ranks::DAN_8,
234			Fellowship9Dan = ranks::DAN_9,
235		}
236	}
237
238	// Fellowship origin indicating weighted voting from at least the rank of `Success + 2` on
239	// a fortnight-long track; needed for Fellowship retention voting.
240	decl_ensure! {
241		pub type EnsureCanRetainAt: EnsureOrigin<Success = Rank> {
242			RetainAt1Dan = ranks::DAN_1,
243			RetainAt2Dan = ranks::DAN_2,
244			RetainAt3Dan = ranks::DAN_3,
245			RetainAt4Dan = ranks::DAN_4,
246			RetainAt5Dan = ranks::DAN_5,
247			RetainAt6Dan = ranks::DAN_6,
248		}
249	}
250
251	// Fellowship origin indicating weighted voting from at least the rank of `Success + 2` on
252	// a month-long track; needed for Fellowship promotion voting.
253	decl_ensure! {
254		pub type EnsureCanPromoteTo: EnsureOrigin<Success = Rank> {
255			PromoteTo1Dan = ranks::DAN_1,
256			PromoteTo2Dan = ranks::DAN_2,
257			PromoteTo3Dan = ranks::DAN_3,
258			PromoteTo4Dan = ranks::DAN_4,
259			PromoteTo5Dan = ranks::DAN_5,
260			PromoteTo6Dan = ranks::DAN_6,
261		}
262	}
263}