topsoil_core/traits/
voting.rs1use crate::dispatch::Parameter;
11use alloc::{vec, vec::Vec};
12use codec::{HasCompact, MaxEncodedLen};
13use subsoil::arithmetic::Perbill;
14use subsoil::runtime::{traits::Member, DispatchError};
15
16pub trait VoteTally<Votes, Class> {
17 fn new(_: Class) -> Self;
19 fn ayes(&self, class: Class) -> Votes;
21 fn support(&self, class: Class) -> Perbill;
24 fn approval(&self, class: Class) -> Perbill;
26 #[cfg(feature = "runtime-benchmarks")]
29 fn unanimity(class: Class) -> Self;
30 #[cfg(feature = "runtime-benchmarks")]
32 fn rejection(class: Class) -> Self;
33 #[cfg(feature = "runtime-benchmarks")]
36 fn from_requirements(support: Perbill, approval: Perbill, class: Class) -> Self;
37 #[cfg(feature = "runtime-benchmarks")]
38 fn setup(class: Class, granularity: Perbill);
50}
51pub enum PollStatus<Tally, Moment, Class> {
52 None,
53 Ongoing(Tally, Class),
54 Completed(Moment, bool),
55}
56
57impl<Tally, Moment, Class> PollStatus<Tally, Moment, Class> {
58 pub fn ensure_ongoing(self) -> Option<(Tally, Class)> {
59 match self {
60 Self::Ongoing(t, c) => Some((t, c)),
61 _ => None,
62 }
63 }
64}
65
66pub struct ClassCountOf<P, T>(core::marker::PhantomData<(P, T)>);
67impl<T, P: Polling<T>> subsoil::runtime::traits::Get<u32> for ClassCountOf<P, T> {
68 fn get() -> u32 {
69 P::classes().len() as u32
70 }
71}
72
73pub trait Polling<Tally> {
74 type Index: Parameter + Member + Ord + PartialOrd + Copy + HasCompact + MaxEncodedLen;
75 type Votes: Parameter + Member + Ord + PartialOrd + Copy + HasCompact + MaxEncodedLen;
76 type Class: Parameter + Member + Ord + PartialOrd + MaxEncodedLen;
77 type Moment;
78
79 fn classes() -> Vec<Self::Class>;
81
82 fn as_ongoing(index: Self::Index) -> Option<(Tally, Self::Class)>;
87
88 fn access_poll<R>(
89 index: Self::Index,
90 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> R,
91 ) -> R;
92
93 fn try_access_poll<R>(
94 index: Self::Index,
95 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> Result<R, DispatchError>,
96 ) -> Result<R, DispatchError>;
97
98 #[cfg(feature = "runtime-benchmarks")]
103 fn create_ongoing(class: Self::Class) -> Result<Self::Index, ()>;
104
105 #[cfg(feature = "runtime-benchmarks")]
109 fn end_ongoing(index: Self::Index, approved: bool) -> Result<(), ()>;
110
111 #[cfg(feature = "runtime-benchmarks")]
114 fn max_ongoing() -> (Self::Class, u32) {
115 (Self::classes().into_iter().next().expect("Always one class"), u32::max_value())
116 }
117}
118
119pub struct NoOpPoll<Moment>(core::marker::PhantomData<Moment>);
121impl<Tally, Moment> Polling<Tally> for NoOpPoll<Moment> {
122 type Index = u8;
123 type Votes = u32;
124 type Class = u16;
125 type Moment = Moment;
126
127 fn classes() -> Vec<Self::Class> {
128 vec![]
129 }
130
131 fn as_ongoing(_index: Self::Index) -> Option<(Tally, Self::Class)> {
132 None
133 }
134
135 fn access_poll<R>(
136 _index: Self::Index,
137 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> R,
138 ) -> R {
139 f(PollStatus::None)
140 }
141
142 fn try_access_poll<R>(
143 _index: Self::Index,
144 f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> Result<R, DispatchError>,
145 ) -> Result<R, DispatchError> {
146 f(PollStatus::None)
147 }
148
149 #[cfg(feature = "runtime-benchmarks")]
150 fn create_ongoing(_class: Self::Class) -> Result<Self::Index, ()> {
151 Err(())
152 }
153
154 #[cfg(feature = "runtime-benchmarks")]
155 fn end_ongoing(_index: Self::Index, _approved: bool) -> Result<(), ()> {
156 Err(())
157 }
158
159 #[cfg(feature = "runtime-benchmarks")]
160 fn max_ongoing() -> (Self::Class, u32) {
161 (0, 0)
162 }
163}