1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3use std::cmp::Ordering;
4use std::convert::TryFrom;
5use std::convert::TryInto;
6
7use sha2::{Digest, Sha256};
8
9use cosmwasm_std::Binary;
10
11#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
14pub struct Validator {
15 pub address: Binary,
17 pub power: u64,
18}
19
20#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
23pub struct ValidatorUpdate {
24 pub pubkey: Pubkey,
26 pub power: u64,
28}
29
30#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
33pub struct ValidatorVote {
34 pub address: Binary,
36 pub power: u64,
37 pub voted: bool,
38}
39
40#[non_exhaustive]
49#[derive(Serialize, Deserialize, Clone, JsonSchema, Debug, PartialEq, Eq)]
50#[serde(rename_all = "snake_case")]
51pub enum Pubkey {
52 Ed25519(Binary),
54 Secp256k1(Binary),
56 Sr25519(Binary),
58}
59
60impl PartialOrd for Pubkey {
62 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
63 Some(self.cmp(other))
64 }
65}
66
67impl Ord for Pubkey {
69 fn cmp(&self, other: &Self) -> Ordering {
70 match (self, other) {
71 (Pubkey::Ed25519(a), Pubkey::Ed25519(b)) => a.0.cmp(&b.0),
73 (Pubkey::Ed25519(_), Pubkey::Secp256k1(_)) => Ordering::Less,
74 (Pubkey::Ed25519(_), Pubkey::Sr25519(_)) => Ordering::Less,
75 (Pubkey::Secp256k1(_), Pubkey::Ed25519(_)) => Ordering::Greater,
76 (Pubkey::Secp256k1(a), Pubkey::Secp256k1(b)) => a.0.cmp(&b.0),
77 (Pubkey::Secp256k1(_), Pubkey::Sr25519(_)) => Ordering::Less,
78 (Pubkey::Sr25519(_), Pubkey::Ed25519(_)) => Ordering::Greater,
79 (Pubkey::Sr25519(_), Pubkey::Secp256k1(_)) => Ordering::Greater,
80 (Pubkey::Sr25519(a), Pubkey::Sr25519(b)) => a.0.cmp(&b.0),
81 }
82 }
83}
84
85#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq, Eq)]
124pub struct Ed25519Pubkey([u8; 32]);
125
126impl Ed25519Pubkey {
127 pub fn to_vec(&self) -> Vec<u8> {
128 self.0.to_vec()
129 }
130
131 pub fn to_base64(&self) -> String {
133 base64::encode(self.0)
134 }
135}
136
137impl ToAddress for Ed25519Pubkey {
138 fn to_address(&self) -> [u8; 20] {
139 let hash = Sha256::digest(&self.0);
140 hash[0..20].try_into().unwrap()
141 }
142}
143
144pub trait ToAddress {
145 fn to_address(&self) -> [u8; 20];
146}
147
148impl From<Ed25519Pubkey> for Pubkey {
149 fn from(ed: Ed25519Pubkey) -> Self {
150 Pubkey::Ed25519(ed.0.into())
151 }
152}
153
154#[derive(Debug)]
155pub enum Ed25519PubkeyConversionError {
156 WrongType,
157 InvalidDataLength,
158}
159
160impl<'a> TryFrom<&'a Pubkey> for Ed25519Pubkey {
161 type Error = Ed25519PubkeyConversionError;
162
163 fn try_from(pubkey: &'a Pubkey) -> Result<Self, Self::Error> {
164 match pubkey {
165 Pubkey::Ed25519(data) => {
166 let data: [u8; 32] = data
167 .as_slice()
168 .try_into()
169 .map_err(|_| Ed25519PubkeyConversionError::InvalidDataLength)?;
170 Ok(Ed25519Pubkey(data))
171 }
172 _ => Err(Ed25519PubkeyConversionError::WrongType),
173 }
174 }
175}
176
177impl TryFrom<Pubkey> for Ed25519Pubkey {
178 type Error = Ed25519PubkeyConversionError;
179
180 fn try_from(pubkey: Pubkey) -> Result<Self, Self::Error> {
181 Ed25519Pubkey::try_from(&pubkey)
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188 use hex_literal::hex;
189
190 #[test]
191 fn pubkey_implements_ord() {
192 let ed_a = Pubkey::Ed25519(b"abc".into());
193 let ed_b = Pubkey::Ed25519(b"bcd".into());
194 let se_a = Pubkey::Secp256k1(b"abc".into());
195 let se_b = Pubkey::Secp256k1(b"bcd".into());
196 let sr_a = Pubkey::Sr25519(b"abc".into());
197 let sr_b = Pubkey::Sr25519(b"bcd".into());
198 assert!(ed_a < ed_b);
199 assert!(se_a < se_b);
200 assert!(sr_a < sr_b);
201
202 assert!(ed_a < se_a);
203 assert!(se_a < sr_a);
204 assert!(ed_a < sr_a);
205 }
206
207 #[test]
208 fn ed25519pubkey_address() {
209 let pubkey = Ed25519Pubkey(hex!(
213 "14253D61EF42D166D02E68D540D07FDF8D65A9AF0ACAA46302688E788A8521E2"
214 ));
215 let address = pubkey.to_address();
216 assert_eq!(address, hex!("0CDA3F47EF3C4906693B170EF650EB968C5F4B2C"))
217 }
218}