frame_support/traits/
voting.rs1use crate::dispatch::Parameter;
22use alloc::{vec, vec::Vec};
23use codec::{HasCompact, MaxEncodedLen};
24use sp_arithmetic::Perbill;
25use sp_runtime::{traits::Member, DispatchError};
26
27pub trait VoteTally<Votes, Class> {
28 fn new(_: Class) -> Self;
30 fn ayes(&self, class: Class) -> Votes;
32 fn support(&self, class: Class) -> Perbill;
35 fn approval(&self, class: Class) -> Perbill;
37 #[cfg(feature = "runtime-benchmarks")]
40 fn unanimity(class: Class) -> Self;
41 #[cfg(feature = "runtime-benchmarks")]
43 fn rejection(class: Class) -> Self;
44 #[cfg(feature = "runtime-benchmarks")]
47 fn from_requirements(support: Perbill, approval: Perbill, class: Class) -> Self;
48 #[cfg(feature = "runtime-benchmarks")]
49 fn setup(class: Class, granularity: Perbill);
61}
62pub enum PollStatus<Tally, Moment, Class> {
63 None,
64 Ongoing(Tally, Class),
65 Completed(Moment, bool),
66}
67
68impl<Tally, Moment, Class> PollStatus<Tally, Moment, Class> {
69 pub fn ensure_ongoing(self) -> Option<(Tally, Class)> {
70 match self {
71 Self::Ongoing(t, c) => Some((t, c)),
72 _ => None,
73 }
74 }
75}
76
77pub struct ClassCountOf<P, T>(core::marker::PhantomData<(P, T)>);
78impl<T, P: Polling<T>> sp_runtime::traits::Get<u32> for ClassCountOf<P, T> {
79 fn get() -> u32 {
80 P::classes().len() as u32
81 }
82}
83
84pub trait Polling<Tally> {
85 type Index: Parameter + Member + Ord + PartialOrd + Copy + HasCompact + MaxEncodedLen;
86 type Votes: Parameter + Member + Ord + PartialOrd + Copy + HasCompact + MaxEncodedLen;
87 type Class: Parameter + Member + Ord + PartialOrd + MaxEncodedLen;
88 type Moment;
89
90 fn classes() -> Vec<Self::Class>;
92
93 fn as_ongoing(index: Self::Index) -> Option<(Tally, Self::Class)>;
98
99 fn access_poll<R>(
100 index: Self::Index,
101 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> R,
102 ) -> R;
103
104 fn try_access_poll<R>(
105 index: Self::Index,
106 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> Result<R, DispatchError>,
107 ) -> Result<R, DispatchError>;
108
109 #[cfg(feature = "runtime-benchmarks")]
114 fn create_ongoing(class: Self::Class) -> Result<Self::Index, ()>;
115
116 #[cfg(feature = "runtime-benchmarks")]
120 fn end_ongoing(index: Self::Index, approved: bool) -> Result<(), ()>;
121
122 #[cfg(feature = "runtime-benchmarks")]
125 fn max_ongoing() -> (Self::Class, u32) {
126 (Self::classes().into_iter().next().expect("Always one class"), u32::max_value())
127 }
128}
129
130pub struct NoOpPoll<Moment>(core::marker::PhantomData<Moment>);
132impl<Tally, Moment> Polling<Tally> for NoOpPoll<Moment> {
133 type Index = u8;
134 type Votes = u32;
135 type Class = u16;
136 type Moment = Moment;
137
138 fn classes() -> Vec<Self::Class> {
139 vec![]
140 }
141
142 fn as_ongoing(_index: Self::Index) -> Option<(Tally, Self::Class)> {
143 None
144 }
145
146 fn access_poll<R>(
147 _index: Self::Index,
148 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> R,
149 ) -> R {
150 f(PollStatus::None)
151 }
152
153 fn try_access_poll<R>(
154 _index: Self::Index,
155 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> Result<R, DispatchError>,
156 ) -> Result<R, DispatchError> {
157 f(PollStatus::None)
158 }
159
160 #[cfg(feature = "runtime-benchmarks")]
161 fn create_ongoing(_class: Self::Class) -> Result<Self::Index, ()> {
162 Err(())
163 }
164
165 #[cfg(feature = "runtime-benchmarks")]
166 fn end_ongoing(_index: Self::Index, _approved: bool) -> Result<(), ()> {
167 Err(())
168 }
169
170 #[cfg(feature = "runtime-benchmarks")]
171 fn max_ongoing() -> (Self::Class, u32) {
172 (0, 0)
173 }
174}