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