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