referrerpolicy=no-referrer-when-downgrade

pallet_democracy/
types.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Miscellaneous additional datatypes.
19
20use crate::{AccountVote, Conviction, Vote, VoteThreshold};
21use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
22use scale_info::TypeInfo;
23use sp_runtime::{
24	traits::{Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Saturating, Zero},
25	RuntimeDebug,
26};
27
28/// A proposal index.
29pub type PropIndex = u32;
30
31/// A referendum index.
32pub type ReferendumIndex = u32;
33
34/// Info regarding an ongoing referendum.
35#[derive(Encode, MaxEncodedLen, Decode, Default, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
36pub struct Tally<Balance> {
37	/// The number of aye votes, expressed in terms of post-conviction lock-vote.
38	pub ayes: Balance,
39	/// The number of nay votes, expressed in terms of post-conviction lock-vote.
40	pub nays: Balance,
41	/// The amount of funds currently expressing its opinion. Pre-conviction.
42	pub turnout: Balance,
43}
44
45/// Amount of votes and capital placed in delegation for an account.
46#[derive(
47	Encode, MaxEncodedLen, Decode, Default, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo,
48)]
49pub struct Delegations<Balance> {
50	/// The number of votes (this is post-conviction).
51	pub votes: Balance,
52	/// The amount of raw capital, used for the turnout.
53	pub capital: Balance,
54}
55
56impl<Balance: Saturating> Saturating for Delegations<Balance> {
57	fn saturating_add(self, o: Self) -> Self {
58		Self {
59			votes: self.votes.saturating_add(o.votes),
60			capital: self.capital.saturating_add(o.capital),
61		}
62	}
63
64	fn saturating_sub(self, o: Self) -> Self {
65		Self {
66			votes: self.votes.saturating_sub(o.votes),
67			capital: self.capital.saturating_sub(o.capital),
68		}
69	}
70
71	fn saturating_mul(self, o: Self) -> Self {
72		Self {
73			votes: self.votes.saturating_mul(o.votes),
74			capital: self.capital.saturating_mul(o.capital),
75		}
76	}
77
78	fn saturating_pow(self, exp: usize) -> Self {
79		Self { votes: self.votes.saturating_pow(exp), capital: self.capital.saturating_pow(exp) }
80	}
81}
82
83impl<
84		Balance: From<u8>
85			+ Zero
86			+ Copy
87			+ CheckedAdd
88			+ CheckedSub
89			+ CheckedMul
90			+ CheckedDiv
91			+ Bounded
92			+ Saturating,
93	> Tally<Balance>
94{
95	/// Create a new tally.
96	pub fn new(vote: Vote, balance: Balance) -> Self {
97		let Delegations { votes, capital } = vote.conviction.votes(balance);
98		Self {
99			ayes: if vote.aye { votes } else { Zero::zero() },
100			nays: if vote.aye { Zero::zero() } else { votes },
101			turnout: capital,
102		}
103	}
104
105	/// Add an account's vote into the tally.
106	pub fn add(&mut self, vote: AccountVote<Balance>) -> Option<()> {
107		match vote {
108			AccountVote::Standard { vote, balance } => {
109				let Delegations { votes, capital } = vote.conviction.votes(balance);
110				self.turnout = self.turnout.checked_add(&capital)?;
111				match vote.aye {
112					true => self.ayes = self.ayes.checked_add(&votes)?,
113					false => self.nays = self.nays.checked_add(&votes)?,
114				}
115			},
116			AccountVote::Split { aye, nay } => {
117				let aye = Conviction::None.votes(aye);
118				let nay = Conviction::None.votes(nay);
119				self.turnout = self.turnout.checked_add(&aye.capital)?.checked_add(&nay.capital)?;
120				self.ayes = self.ayes.checked_add(&aye.votes)?;
121				self.nays = self.nays.checked_add(&nay.votes)?;
122			},
123		}
124		Some(())
125	}
126
127	/// Remove an account's vote from the tally.
128	pub fn remove(&mut self, vote: AccountVote<Balance>) -> Option<()> {
129		match vote {
130			AccountVote::Standard { vote, balance } => {
131				let Delegations { votes, capital } = vote.conviction.votes(balance);
132				self.turnout = self.turnout.checked_sub(&capital)?;
133				match vote.aye {
134					true => self.ayes = self.ayes.checked_sub(&votes)?,
135					false => self.nays = self.nays.checked_sub(&votes)?,
136				}
137			},
138			AccountVote::Split { aye, nay } => {
139				let aye = Conviction::None.votes(aye);
140				let nay = Conviction::None.votes(nay);
141				self.turnout = self.turnout.checked_sub(&aye.capital)?.checked_sub(&nay.capital)?;
142				self.ayes = self.ayes.checked_sub(&aye.votes)?;
143				self.nays = self.nays.checked_sub(&nay.votes)?;
144			},
145		}
146		Some(())
147	}
148
149	/// Increment some amount of votes.
150	pub fn increase(&mut self, approve: bool, delegations: Delegations<Balance>) -> Option<()> {
151		self.turnout = self.turnout.saturating_add(delegations.capital);
152		match approve {
153			true => self.ayes = self.ayes.saturating_add(delegations.votes),
154			false => self.nays = self.nays.saturating_add(delegations.votes),
155		}
156		Some(())
157	}
158
159	/// Decrement some amount of votes.
160	pub fn reduce(&mut self, approve: bool, delegations: Delegations<Balance>) -> Option<()> {
161		self.turnout = self.turnout.saturating_sub(delegations.capital);
162		match approve {
163			true => self.ayes = self.ayes.saturating_sub(delegations.votes),
164			false => self.nays = self.nays.saturating_sub(delegations.votes),
165		}
166		Some(())
167	}
168}
169
170/// Info regarding an ongoing referendum.
171#[derive(
172	Encode,
173	MaxEncodedLen,
174	Decode,
175	DecodeWithMemTracking,
176	Clone,
177	PartialEq,
178	Eq,
179	RuntimeDebug,
180	TypeInfo,
181)]
182pub struct ReferendumStatus<BlockNumber, Proposal, Balance> {
183	/// When voting on this referendum will end.
184	pub end: BlockNumber,
185	/// The proposal being voted on.
186	pub proposal: Proposal,
187	/// The thresholding mechanism to determine whether it passed.
188	pub threshold: VoteThreshold,
189	/// The delay (in blocks) to wait after a successful referendum before deploying.
190	pub delay: BlockNumber,
191	/// The current tally of votes in this referendum.
192	pub tally: Tally<Balance>,
193}
194
195/// Info regarding a referendum, present or past.
196#[derive(
197	Encode,
198	MaxEncodedLen,
199	Decode,
200	DecodeWithMemTracking,
201	Clone,
202	PartialEq,
203	Eq,
204	RuntimeDebug,
205	TypeInfo,
206)]
207pub enum ReferendumInfo<BlockNumber, Proposal, Balance> {
208	/// Referendum is happening, the arg is the block number at which it will end.
209	Ongoing(ReferendumStatus<BlockNumber, Proposal, Balance>),
210	/// Referendum finished at `end`, and has been `approved` or rejected.
211	Finished { approved: bool, end: BlockNumber },
212}
213
214impl<BlockNumber, Proposal, Balance: Default> ReferendumInfo<BlockNumber, Proposal, Balance> {
215	/// Create a new instance.
216	pub fn new(
217		end: BlockNumber,
218		proposal: Proposal,
219		threshold: VoteThreshold,
220		delay: BlockNumber,
221	) -> Self {
222		let s = ReferendumStatus { end, proposal, threshold, delay, tally: Tally::default() };
223		ReferendumInfo::Ongoing(s)
224	}
225}
226
227/// Whether an `unvote` operation is able to make actions that are not strictly always in the
228/// interest of an account.
229pub enum UnvoteScope {
230	/// Permitted to do everything.
231	Any,
232	/// Permitted to do only the changes that do not need the owner's permission.
233	OnlyExpired,
234}
235
236/// Identifies an owner of a metadata.
237#[derive(
238	Encode,
239	Decode,
240	DecodeWithMemTracking,
241	Clone,
242	PartialEq,
243	Eq,
244	RuntimeDebug,
245	TypeInfo,
246	MaxEncodedLen,
247)]
248pub enum MetadataOwner {
249	/// External proposal.
250	External,
251	/// Public proposal of the index.
252	Proposal(PropIndex),
253	/// Referendum of the index.
254	Referendum(ReferendumIndex),
255}