1#![feature(portable_simd)]
4#![no_std]
5
6mod aes;
7
8use ab_core_primitives::pot::{PotCheckpoints, PotSeed};
9use core::num::NonZeroU32;
10
11#[derive(Debug, thiserror::Error)]
13pub enum PotError {
14 #[error(
16 "Iterations {iterations} are not multiple of number of checkpoints {num_checkpoints} \
17 times two"
18 )]
19 NotMultipleOfCheckpoints {
20 iterations: NonZeroU32,
22 num_checkpoints: u32,
24 },
25}
26
27#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
31pub fn prove(seed: PotSeed, iterations: NonZeroU32) -> Result<PotCheckpoints, PotError> {
32 if !iterations
33 .get()
34 .is_multiple_of(u32::from(PotCheckpoints::NUM_CHECKPOINTS.get() * 2))
35 {
36 return Err(PotError::NotMultipleOfCheckpoints {
37 iterations,
38 num_checkpoints: u32::from(PotCheckpoints::NUM_CHECKPOINTS.get()),
39 });
40 }
41
42 Ok(aes::create(
44 seed,
45 seed.key(),
46 iterations.get() / u32::from(PotCheckpoints::NUM_CHECKPOINTS.get()),
47 ))
48}
49
50#[cfg_attr(
55 all(feature = "no-panic", not(target_os = "macos")),
56 no_panic::no_panic
57)]
58pub fn verify(
59 seed: PotSeed,
60 iterations: NonZeroU32,
61 checkpoints: &PotCheckpoints,
62) -> Result<bool, PotError> {
63 let num_checkpoints = checkpoints.len() as u32;
64 if !iterations.get().is_multiple_of(num_checkpoints * 2) {
65 return Err(PotError::NotMultipleOfCheckpoints {
66 iterations,
67 num_checkpoints,
68 });
69 }
70
71 Ok(aes::verify_sequential(
72 seed,
73 seed.key(),
74 checkpoints,
75 iterations.get() / num_checkpoints,
76 ))
77}