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;
39 #[cfg(feature = "runtime-benchmarks")]
42 fn unanimity(class: Class) -> Self;
43 #[cfg(feature = "runtime-benchmarks")]
45 fn rejection(class: Class) -> Self;
46 #[cfg(feature = "runtime-benchmarks")]
49 fn from_requirements(support: Perbill, approval: Perbill, class: Class) -> Self;
50 #[cfg(feature = "runtime-benchmarks")]
51 fn setup(class: Class, granularity: Perbill);
63}
64pub enum PollStatus<Tally, Moment, Class> {
65 None,
66 Ongoing(Tally, Class),
67 Completed(Moment, bool),
68}
69
70impl<Tally, Moment, Class> PollStatus<Tally, Moment, Class> {
71 pub fn ensure_ongoing(self) -> Option<(Tally, Class)> {
72 match self {
73 Self::Ongoing(t, c) => Some((t, c)),
74 _ => None,
75 }
76 }
77}
78
79pub struct ClassCountOf<P, T>(core::marker::PhantomData<(P, T)>);
80impl<T, P: Polling<T>> sp_runtime::traits::Get<u32> for ClassCountOf<P, T> {
81 fn get() -> u32 {
82 P::classes().len() as u32
83 }
84}
85
86pub trait Polling<Tally> {
87 type Index: Parameter + Member + Ord + PartialOrd + Copy + HasCompact + MaxEncodedLen;
88 type Votes: Parameter + Member + Ord + PartialOrd + Copy + HasCompact + MaxEncodedLen;
89 type Class: Parameter + Member + Ord + PartialOrd + MaxEncodedLen;
90 type Moment;
91
92 fn classes() -> Vec<Self::Class>;
94
95 fn as_ongoing(index: Self::Index) -> Option<(Tally, Self::Class)>;
100
101 fn access_poll<R>(
102 index: Self::Index,
103 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> R,
104 ) -> R;
105
106 fn try_access_poll<R>(
107 index: Self::Index,
108 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> Result<R, DispatchError>,
109 ) -> Result<R, DispatchError>;
110
111 #[cfg(feature = "runtime-benchmarks")]
116 fn create_ongoing(class: Self::Class) -> Result<Self::Index, ()>;
117
118 #[cfg(feature = "runtime-benchmarks")]
122 fn end_ongoing(index: Self::Index, approved: bool) -> Result<(), ()>;
123
124 #[cfg(feature = "runtime-benchmarks")]
127 fn max_ongoing() -> (Self::Class, u32) {
128 (Self::classes().into_iter().next().expect("Always one class"), u32::max_value())
129 }
130}
131
132pub struct NoOpPoll;
134impl<Tally> Polling<Tally> for NoOpPoll {
135 type Index = u8;
136 type Votes = u32;
137 type Class = u16;
138 type Moment = u64;
139
140 fn classes() -> Vec<Self::Class> {
141 vec![]
142 }
143
144 fn as_ongoing(_index: Self::Index) -> Option<(Tally, Self::Class)> {
145 None
146 }
147
148 fn access_poll<R>(
149 _index: Self::Index,
150 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> R,
151 ) -> R {
152 f(PollStatus::None)
153 }
154
155 fn try_access_poll<R>(
156 _index: Self::Index,
157 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> Result<R, DispatchError>,
158 ) -> Result<R, DispatchError> {
159 f(PollStatus::None)
160 }
161
162 #[cfg(feature = "runtime-benchmarks")]
163 fn create_ongoing(_class: Self::Class) -> Result<Self::Index, ()> {
164 Err(())
165 }
166
167 #[cfg(feature = "runtime-benchmarks")]
168 fn end_ongoing(_index: Self::Index, _approved: bool) -> Result<(), ()> {
169 Err(())
170 }
171
172 #[cfg(feature = "runtime-benchmarks")]
173 fn max_ongoing() -> (Self::Class, u32) {
174 (0, 0)
175 }
176}