use alloc::string::ToString;
use alloc::vec::Vec;
use crate::crypto::dsa::ecdsa_k256_keccak::PublicKey;
use crate::utils::serde::{
ByteReader,
ByteWriter,
Deserializable,
DeserializationError,
Serializable,
};
use crate::{Felt, Hasher, WORD_SIZE, Word};
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ValidatorKeysError {
#[error("validator set must contain at least one key")]
EmptySet,
#[error(
"validator set contains {count} keys but must contain at most {max}",
max = ValidatorKeys::MAX,
)]
TooManyKeys { count: usize },
#[error("validator set contains duplicate public keys")]
DuplicateKey,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ValidatorKeys {
keys: Vec<PublicKey>,
}
impl ValidatorKeys {
pub const MAX: usize = 5;
pub fn new(mut keys: Vec<PublicKey>) -> Result<Self, ValidatorKeysError> {
if keys.is_empty() {
return Err(ValidatorKeysError::EmptySet);
}
if keys.len() > Self::MAX {
return Err(ValidatorKeysError::TooManyKeys { count: keys.len() });
}
keys.sort_by_key(|key| key.to_bytes());
if keys.windows(2).any(|pair| pair[0] == pair[1]) {
return Err(ValidatorKeysError::DuplicateKey);
}
Ok(Self { keys })
}
pub fn as_keys(&self) -> &[PublicKey] {
&self.keys
}
pub fn len(&self) -> usize {
self.keys.len()
}
pub fn is_empty(&self) -> bool {
false
}
pub fn commitment(&self) -> Word {
let mut elements: Vec<Felt> = Vec::with_capacity(self.keys.len() * WORD_SIZE);
for key in &self.keys {
elements.extend_from_slice(key.to_commitment().as_elements());
}
Hasher::hash_elements(&elements)
}
}
impl Serializable for ValidatorKeys {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
self.keys.write_into(target);
}
}
impl Deserializable for ValidatorKeys {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let keys = Vec::<PublicKey>::read_from(source)?;
Self::new(keys).map_err(|err| DeserializationError::InvalidValue(err.to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::testing::random_secret_key::random_secret_key;
fn random_keys(count: usize) -> Vec<PublicKey> {
(0..count).map(|_| random_secret_key().public_key()).collect()
}
#[test]
fn new_rejects_empty_set() {
let result = ValidatorKeys::new(Vec::new());
assert!(matches!(result, Err(ValidatorKeysError::EmptySet)));
}
#[test]
fn new_accepts_single_validator() {
let keys = ValidatorKeys::new(random_keys(1)).unwrap();
assert_eq!(keys.len(), 1);
}
#[test]
fn new_accepts_max_validators() {
let keys = ValidatorKeys::new(random_keys(ValidatorKeys::MAX)).unwrap();
assert_eq!(keys.len(), ValidatorKeys::MAX);
}
#[test]
fn new_rejects_too_many_keys() {
let result = ValidatorKeys::new(random_keys(ValidatorKeys::MAX + 1));
assert!(matches!(
result,
Err(ValidatorKeysError::TooManyKeys { count }) if count == ValidatorKeys::MAX + 1
));
}
#[test]
fn new_rejects_duplicate_keys() {
let mut keys = random_keys(3);
keys[1] = keys[0].clone();
let result = ValidatorKeys::new(keys);
assert!(matches!(result, Err(ValidatorKeysError::DuplicateKey)));
}
#[test]
fn new_sorts_into_canonical_order() {
let keys = random_keys(5);
let forward = ValidatorKeys::new(keys.clone()).unwrap();
let mut reversed = keys;
reversed.reverse();
let backward = ValidatorKeys::new(reversed).unwrap();
assert_eq!(forward.as_keys(), backward.as_keys());
assert_eq!(forward.commitment(), backward.commitment());
}
#[test]
fn serde_round_trip() {
let validator_keys = ValidatorKeys::new(random_keys(4)).unwrap();
let bytes = validator_keys.to_bytes();
let deserialized = ValidatorKeys::read_from_bytes(&bytes).unwrap();
assert_eq!(validator_keys, deserialized);
}
}