extern crate alloc;
use alloc::format;
use alloc::string::String;
use lib_q_stark_field::Field;
pub fn constant_time_eq<F: Field>(a: &F, b: &F) -> bool {
(*a - *b).is_zero()
}
pub fn constant_time_eq_bytes(a: &[u8], b: &[u8]) -> bool {
if a.len() != b.len() {
return false;
}
let mut result = 0u8;
for (ai, bi) in a.iter().zip(b.iter()) {
result |= ai ^ bi;
}
result == 0
}
pub fn validate_proof_size(size: usize, max_size: usize) -> Result<(), String> {
if size > max_size {
return Err(format!("Proof size {} exceeds maximum {}", size, max_size));
}
Ok(())
}
pub fn validate_array_length(
length: usize,
max_length: usize,
parameter_name: &str,
) -> Result<(), String> {
if length > max_length {
return Err(format!(
"{} length {} exceeds maximum {}",
parameter_name, length, max_length
));
}
Ok(())
}
pub fn validate_range(
value: usize,
min: usize,
max: usize,
parameter_name: &str,
) -> Result<(), String> {
if value < min || value > max {
return Err(format!(
"{} value {} is outside valid range [{}, {}]",
parameter_name, value, min, max
));
}
Ok(())
}
pub fn is_power_of_two(n: usize) -> bool {
n > 0 && (n & (n - 1)) == 0
}
pub fn next_power_of_two_ceil(n: usize) -> usize {
if n == 0 {
return 1;
}
if is_power_of_two(n) {
return n;
}
let mut power = 1;
while power < n {
power <<= 1;
}
power
}
#[cfg(test)]
mod tests {
use lib_q_stark_field::PrimeCharacteristicRing;
use lib_q_stark_field::extension::Complex;
use lib_q_stark_mersenne31::Mersenne31;
use super::*;
type TestField = Complex<Mersenne31>;
#[test]
fn test_constant_time_eq() {
let a = TestField::from_u8(5);
let b = TestField::from_u8(5);
let c = TestField::from_u8(6);
assert!(constant_time_eq(&a, &b));
assert!(!constant_time_eq(&a, &c));
}
#[test]
fn test_constant_time_eq_bytes() {
let a = b"test";
let b = b"test";
let c = b"fail";
assert!(constant_time_eq_bytes(a, b));
assert!(!constant_time_eq_bytes(a, c));
assert!(!constant_time_eq_bytes(a, b"test1"));
}
#[test]
fn test_validate_proof_size() {
assert!(validate_proof_size(100, 1000).is_ok());
assert!(validate_proof_size(1000, 1000).is_ok());
assert!(validate_proof_size(1001, 1000).is_err());
}
#[test]
fn test_validate_array_length() {
assert!(validate_array_length(10, 100, "test").is_ok());
assert!(validate_array_length(100, 100, "test").is_ok());
assert!(validate_array_length(101, 100, "test").is_err());
}
#[test]
fn test_validate_range() {
assert!(validate_range(5, 1, 10, "test").is_ok());
assert!(validate_range(1, 1, 10, "test").is_ok());
assert!(validate_range(10, 1, 10, "test").is_ok());
assert!(validate_range(0, 1, 10, "test").is_err());
assert!(validate_range(11, 1, 10, "test").is_err());
}
#[test]
fn test_is_power_of_two() {
assert!(is_power_of_two(1));
assert!(is_power_of_two(2));
assert!(is_power_of_two(4));
assert!(is_power_of_two(8));
assert!(is_power_of_two(16));
assert!(!is_power_of_two(3));
assert!(!is_power_of_two(5));
assert!(!is_power_of_two(0));
}
#[test]
fn test_next_power_of_two_ceil() {
assert_eq!(next_power_of_two_ceil(0), 1);
assert_eq!(next_power_of_two_ceil(1), 1);
assert_eq!(next_power_of_two_ceil(2), 2);
assert_eq!(next_power_of_two_ceil(3), 4);
assert_eq!(next_power_of_two_ceil(5), 8);
assert_eq!(next_power_of_two_ceil(8), 8);
}
}