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	Debug,
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, Debug, 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(Encode, MaxEncodedLen, Decode, Default, Copy, Clone, PartialEq, Eq, Debug, TypeInfo)]
47pub struct Delegations<Balance> {
48	/// The number of votes (this is post-conviction).
49	pub votes: Balance,
50	/// The amount of raw capital, used for the turnout.
51	pub capital: Balance,
52}
53
54impl<Balance: Saturating> Saturating for Delegations<Balance> {
55	fn saturating_add(self, o: Self) -> Self {
56		Self {
57			votes: self.votes.saturating_add(o.votes),
58			capital: self.capital.saturating_add(o.capital),
59		}
60	}
61
62	fn saturating_sub(self, o: Self) -> Self {
63		Self {
64			votes: self.votes.saturating_sub(o.votes),
65			capital: self.capital.saturating_sub(o.capital),
66		}
67	}
68
69	fn saturating_mul(self, o: Self) -> Self {
70		Self {
71			votes: self.votes.saturating_mul(o.votes),
72			capital: self.capital.saturating_mul(o.capital),
73		}
74	}
75
76	fn saturating_pow(self, exp: usize) -> Self {
77		Self { votes: self.votes.saturating_pow(exp), capital: self.capital.saturating_pow(exp) }
78	}
79}
80
81impl<
82		Balance: From<u8>
83			+ Zero
84			+ Copy
85			+ CheckedAdd
86			+ CheckedSub
87			+ CheckedMul
88			+ CheckedDiv
89			+ Bounded
90			+ Saturating,
91	> Tally<Balance>
92{
93	/// Create a new tally.
94	pub fn new(vote: Vote, balance: Balance) -> Self {
95		let Delegations { votes, capital } = vote.conviction.votes(balance);
96		Self {
97			ayes: if vote.aye { votes } else { Zero::zero() },
98			nays: if vote.aye { Zero::zero() } else { votes },
99			turnout: capital,
100		}
101	}
102
103	/// Add an account's vote into the tally.
104	pub fn add(&mut self, vote: AccountVote<Balance>) -> Option<()> {
105		match vote {
106			AccountVote::Standard { vote, balance } => {
107				let Delegations { votes, capital } = vote.conviction.votes(balance);
108				self.turnout = self.turnout.checked_add(&capital)?;
109				match vote.aye {
110					true => self.ayes = self.ayes.checked_add(&votes)?,
111					false => self.nays = self.nays.checked_add(&votes)?,
112				}
113			},
114			AccountVote::Split { aye, nay } => {
115				let aye = Conviction::None.votes(aye);
116				let nay = Conviction::None.votes(nay);
117				self.turnout = self.turnout.checked_add(&aye.capital)?.checked_add(&nay.capital)?;
118				self.ayes = self.ayes.checked_add(&aye.votes)?;
119				self.nays = self.nays.checked_add(&nay.votes)?;
120			},
121		}
122		Some(())
123	}
124
125	/// Remove an account's vote from the tally.
126	pub fn remove(&mut self, vote: AccountVote<Balance>) -> Option<()> {
127		match vote {
128			AccountVote::Standard { vote, balance } => {
129				let Delegations { votes, capital } = vote.conviction.votes(balance);
130				self.turnout = self.turnout.checked_sub(&capital)?;
131				match vote.aye {
132					true => self.ayes = self.ayes.checked_sub(&votes)?,
133					false => self.nays = self.nays.checked_sub(&votes)?,
134				}
135			},
136			AccountVote::Split { aye, nay } => {
137				let aye = Conviction::None.votes(aye);
138				let nay = Conviction::None.votes(nay);
139				self.turnout = self.turnout.checked_sub(&aye.capital)?.checked_sub(&nay.capital)?;
140				self.ayes = self.ayes.checked_sub(&aye.votes)?;
141				self.nays = self.nays.checked_sub(&nay.votes)?;
142			},
143		}
144		Some(())
145	}
146
147	/// Increment some amount of votes.
148	pub fn increase(&mut self, approve: bool, delegations: Delegations<Balance>) -> Option<()> {
149		self.turnout = self.turnout.saturating_add(delegations.capital);
150		match approve {
151			true => self.ayes = self.ayes.saturating_add(delegations.votes),
152			false => self.nays = self.nays.saturating_add(delegations.votes),
153		}
154		Some(())
155	}
156
157	/// Decrement some amount of votes.
158	pub fn reduce(&mut self, approve: bool, delegations: Delegations<Balance>) -> Option<()> {
159		self.turnout = self.turnout.saturating_sub(delegations.capital);
160		match approve {
161			true => self.ayes = self.ayes.saturating_sub(delegations.votes),
162			false => self.nays = self.nays.saturating_sub(delegations.votes),
163		}
164		Some(())
165	}
166}
167
168/// Info regarding an ongoing referendum.
169#[derive(
170	Encode, MaxEncodedLen, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, Debug, TypeInfo,
171)]
172pub struct ReferendumStatus<BlockNumber, Proposal, Balance> {
173	/// When voting on this referendum will end.
174	pub end: BlockNumber,
175	/// The proposal being voted on.
176	pub proposal: Proposal,
177	/// The thresholding mechanism to determine whether it passed.
178	pub threshold: VoteThreshold,
179	/// The delay (in blocks) to wait after a successful referendum before deploying.
180	pub delay: BlockNumber,
181	/// The current tally of votes in this referendum.
182	pub tally: Tally<Balance>,
183}
184
185/// Info regarding a referendum, present or past.
186#[derive(
187	Encode, MaxEncodedLen, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, Debug, TypeInfo,
188)]
189pub enum ReferendumInfo<BlockNumber, Proposal, Balance> {
190	/// Referendum is happening, the arg is the block number at which it will end.
191	Ongoing(ReferendumStatus<BlockNumber, Proposal, Balance>),
192	/// Referendum finished at `end`, and has been `approved` or rejected.
193	Finished { approved: bool, end: BlockNumber },
194}
195
196impl<BlockNumber, Proposal, Balance: Default> ReferendumInfo<BlockNumber, Proposal, Balance> {
197	/// Create a new instance.
198	pub fn new(
199		end: BlockNumber,
200		proposal: Proposal,
201		threshold: VoteThreshold,
202		delay: BlockNumber,
203	) -> Self {
204		let s = ReferendumStatus { end, proposal, threshold, delay, tally: Tally::default() };
205		ReferendumInfo::Ongoing(s)
206	}
207}
208
209/// Whether an `unvote` operation is able to make actions that are not strictly always in the
210/// interest of an account.
211pub enum UnvoteScope {
212	/// Permitted to do everything.
213	Any,
214	/// Permitted to do only the changes that do not need the owner's permission.
215	OnlyExpired,
216}
217
218/// Identifies an owner of a metadata.
219#[derive(
220	Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen,
221)]
222pub enum MetadataOwner {
223	/// External proposal.
224	External,
225	/// Public proposal of the index.
226	Proposal(PropIndex),
227	/// Referendum of the index.
228	Referendum(ReferendumIndex),
229}