miden_protocol/block/
validator_keys.rs1use alloc::string::ToString;
2use alloc::vec::Vec;
3
4use crate::crypto::dsa::ecdsa_k256_keccak::PublicKey;
5use crate::utils::serde::{
6 ByteReader,
7 ByteWriter,
8 Deserializable,
9 DeserializationError,
10 Serializable,
11};
12use crate::{Felt, Hasher, WORD_SIZE, Word};
13
14#[derive(Debug, thiserror::Error)]
19#[non_exhaustive]
20pub enum ValidatorKeysError {
21 #[error("validator set must contain at least one key")]
22 EmptySet,
23 #[error(
24 "validator set contains {count} keys but must contain at most {max}",
25 max = ValidatorKeys::MAX,
26 )]
27 TooManyKeys { count: usize },
28 #[error("validator set contains duplicate public keys")]
29 DuplicateKey,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct ValidatorKeys {
49 keys: Vec<PublicKey>,
51}
52
53impl ValidatorKeys {
54 pub const MAX: usize = 5;
59
60 pub fn new(mut keys: Vec<PublicKey>) -> Result<Self, ValidatorKeysError> {
74 if keys.is_empty() {
75 return Err(ValidatorKeysError::EmptySet);
76 }
77 if keys.len() > Self::MAX {
78 return Err(ValidatorKeysError::TooManyKeys { count: keys.len() });
79 }
80
81 keys.sort_by_key(|key| key.to_bytes());
83
84 if keys.windows(2).any(|pair| pair[0] == pair[1]) {
86 return Err(ValidatorKeysError::DuplicateKey);
87 }
88
89 Ok(Self { keys })
90 }
91
92 pub fn as_keys(&self) -> &[PublicKey] {
97 &self.keys
98 }
99
100 pub fn len(&self) -> usize {
102 self.keys.len()
103 }
104
105 pub fn is_empty(&self) -> bool {
107 false
108 }
109
110 pub fn commitment(&self) -> Word {
116 let mut elements: Vec<Felt> = Vec::with_capacity(self.keys.len() * WORD_SIZE);
117 for key in &self.keys {
118 elements.extend_from_slice(key.to_commitment().as_elements());
119 }
120 Hasher::hash_elements(&elements)
121 }
122}
123
124impl Serializable for ValidatorKeys {
128 fn write_into<W: ByteWriter>(&self, target: &mut W) {
129 self.keys.write_into(target);
130 }
131}
132
133impl Deserializable for ValidatorKeys {
134 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
135 let keys = Vec::<PublicKey>::read_from(source)?;
136 Self::new(keys).map_err(|err| DeserializationError::InvalidValue(err.to_string()))
137 }
138}
139
140#[cfg(test)]
144mod tests {
145 use super::*;
146 use crate::testing::random_secret_key::random_secret_key;
147
148 fn random_keys(count: usize) -> Vec<PublicKey> {
149 (0..count).map(|_| random_secret_key().public_key()).collect()
150 }
151
152 #[test]
153 fn new_rejects_empty_set() {
154 let result = ValidatorKeys::new(Vec::new());
155 assert!(matches!(result, Err(ValidatorKeysError::EmptySet)));
156 }
157
158 #[test]
159 fn new_accepts_single_validator() {
160 let keys = ValidatorKeys::new(random_keys(1)).unwrap();
161 assert_eq!(keys.len(), 1);
162 }
163
164 #[test]
165 fn new_accepts_max_validators() {
166 let keys = ValidatorKeys::new(random_keys(ValidatorKeys::MAX)).unwrap();
167 assert_eq!(keys.len(), ValidatorKeys::MAX);
168 }
169
170 #[test]
171 fn new_rejects_too_many_keys() {
172 let result = ValidatorKeys::new(random_keys(ValidatorKeys::MAX + 1));
173 assert!(matches!(
174 result,
175 Err(ValidatorKeysError::TooManyKeys { count }) if count == ValidatorKeys::MAX + 1
176 ));
177 }
178
179 #[test]
180 fn new_rejects_duplicate_keys() {
181 let mut keys = random_keys(3);
182 keys[1] = keys[0].clone();
183 let result = ValidatorKeys::new(keys);
184 assert!(matches!(result, Err(ValidatorKeysError::DuplicateKey)));
185 }
186
187 #[test]
188 fn new_sorts_into_canonical_order() {
189 let keys = random_keys(5);
190 let forward = ValidatorKeys::new(keys.clone()).unwrap();
191
192 let mut reversed = keys;
193 reversed.reverse();
194 let backward = ValidatorKeys::new(reversed).unwrap();
195
196 assert_eq!(forward.as_keys(), backward.as_keys());
198 assert_eq!(forward.commitment(), backward.commitment());
199 }
200
201 #[test]
202 fn serde_round_trip() {
203 let validator_keys = ValidatorKeys::new(random_keys(4)).unwrap();
204 let bytes = validator_keys.to_bytes();
205 let deserialized = ValidatorKeys::read_from_bytes(&bytes).unwrap();
206 assert_eq!(validator_keys, deserialized);
207 }
208}