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.get() % u32::from(PotCheckpoints::NUM_CHECKPOINTS.get() * 2) != 0 {
34 return Err(PotError::NotMultipleOfCheckpoints {
35 iterations,
36 num_checkpoints: u32::from(PotCheckpoints::NUM_CHECKPOINTS.get()),
37 });
38 }
39
40 Ok(aes::create(
42 seed,
43 seed.key(),
44 iterations.get() / u32::from(PotCheckpoints::NUM_CHECKPOINTS.get()),
45 ))
46}
47
48#[cfg_attr(
53 all(feature = "no-panic", not(target_os = "macos")),
54 no_panic::no_panic
55)]
56pub fn verify(
57 seed: PotSeed,
58 iterations: NonZeroU32,
59 checkpoints: &PotCheckpoints,
60) -> Result<bool, PotError> {
61 let num_checkpoints = checkpoints.len() as u32;
62 if iterations.get() % (num_checkpoints * 2) != 0 {
63 return Err(PotError::NotMultipleOfCheckpoints {
64 iterations,
65 num_checkpoints,
66 });
67 }
68
69 Ok(aes::verify_sequential(
70 seed,
71 seed.key(),
72 checkpoints,
73 iterations.get() / num_checkpoints,
74 ))
75}