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
//! The conviction datatype.
19

            
20
use codec::{Decode, Encode, MaxEncodedLen};
21
use scale_info::TypeInfo;
22
use sp_runtime::{
23
	traits::{Bounded, CheckedDiv, CheckedMul, Zero},
24
	RuntimeDebug,
25
};
26

            
27
use crate::types::Delegations;
28

            
29
/// A value denoting the strength of conviction of a vote.
30
#[derive(
31
	Encode,
32
18
	Decode,
33
	Copy,
34
	Clone,
35
	Eq,
36
	PartialEq,
37
	Ord,
38
	PartialOrd,
39
	RuntimeDebug,
40
	TypeInfo,
41
	MaxEncodedLen,
42
)]
43
pub enum Conviction {
44
657
	/// 0.1x votes, unlocked.
45
657
	None,
46
147
	/// 1x votes, locked for an enactment period following a successful vote.
47
147
	Locked1x,
48
72
	/// 2x votes, locked for 2x enactment periods following a successful vote.
49
72
	Locked2x,
50
63
	/// 3x votes, locked for 4x...
51
63
	Locked3x,
52
12
	/// 4x votes, locked for 8x...
53
12
	Locked4x,
54
45
	/// 5x votes, locked for 16x...
55
45
	Locked5x,
56
30
	/// 6x votes, locked for 32x...
57
30
	Locked6x,
58
}
59

            
60
impl Default for Conviction {
61
	fn default() -> Self {
62
		Conviction::None
63
	}
64
}
65

            
66
impl From<Conviction> for u8 {
67
1660
	fn from(c: Conviction) -> u8 {
68
1660
		match c {
69
1592
			Conviction::None => 0,
70
56
			Conviction::Locked1x => 1,
71
4
			Conviction::Locked2x => 2,
72
4
			Conviction::Locked3x => 3,
73
			Conviction::Locked4x => 4,
74
4
			Conviction::Locked5x => 5,
75
			Conviction::Locked6x => 6,
76
		}
77
1660
	}
78
}
79

            
80
impl TryFrom<u8> for Conviction {
81
	type Error = ();
82
984
	fn try_from(i: u8) -> Result<Conviction, ()> {
83
984
		Ok(match i {
84
928
			0 => Conviction::None,
85
28
			1 => Conviction::Locked1x,
86
			2 => Conviction::Locked2x,
87
			3 => Conviction::Locked3x,
88
			4 => Conviction::Locked4x,
89
			5 => Conviction::Locked5x,
90
			6 => Conviction::Locked6x,
91
28
			_ => return Err(()),
92
		})
93
984
	}
94
}
95

            
96
impl Conviction {
97
	/// The amount of time (in number of periods) that our conviction implies a successful voter's
98
	/// balance should be locked for.
99
	pub fn lock_periods(self) -> u32 {
100
		match self {
101
			Conviction::None => 0,
102
			Conviction::Locked1x => 1,
103
			Conviction::Locked2x => 2,
104
			Conviction::Locked3x => 4,
105
			Conviction::Locked4x => 8,
106
			Conviction::Locked5x => 16,
107
			Conviction::Locked6x => 32,
108
		}
109
	}
110

            
111
	/// The votes of a voter of the given `balance` with our conviction.
112
174
	pub fn votes<B: From<u8> + Zero + Copy + CheckedMul + CheckedDiv + Bounded>(
113
174
		self,
114
174
		capital: B,
115
174
	) -> Delegations<B> {
116
174
		let votes = match self {
117
162
			Conviction::None => capital.checked_div(&10u8.into()).unwrap_or_else(Zero::zero),
118
12
			x => capital.checked_mul(&u8::from(x).into()).unwrap_or_else(B::max_value),
119
		};
120
174
		Delegations { votes, capital }
121
174
	}
122
}
123

            
124
impl Bounded for Conviction {
125
	fn min_value() -> Self {
126
		Conviction::None
127
	}
128
	fn max_value() -> Self {
129
		Conviction::Locked6x
130
	}
131
}