Skip to main content

ab_proof_of_time/
lib.rs

1//! Proof of time implementation.
2
3#![cfg_attr(
4    any(target_arch = "aarch64", target_arch = "x86_64"),
5    feature(portable_simd)
6)]
7#![no_std]
8
9mod aes;
10
11use ab_core_primitives::pot::{PotCheckpoints, PotSeed};
12use core::num::NonZeroU32;
13
14/// Proof of time error
15#[derive(Debug, thiserror::Error)]
16pub enum PotError {
17    /// Iterations are not multiple of number of checkpoints times two
18    #[error(
19        "Iterations {iterations} are not multiple of number of checkpoints {num_checkpoints} \
20        times two"
21    )]
22    NotMultipleOfCheckpoints {
23        /// Slot iterations provided
24        iterations: NonZeroU32,
25        /// Number of checkpoints
26        num_checkpoints: u32,
27    },
28}
29
30/// Run PoT proving and produce checkpoints.
31///
32/// Returns error if `iterations` is not a multiple of checkpoints times two.
33#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
34pub fn prove(seed: PotSeed, iterations: NonZeroU32) -> Result<PotCheckpoints, PotError> {
35    if !iterations
36        .get()
37        .is_multiple_of(u32::from(PotCheckpoints::NUM_CHECKPOINTS.get() * 2))
38    {
39        return Err(PotError::NotMultipleOfCheckpoints {
40            iterations,
41            num_checkpoints: u32::from(PotCheckpoints::NUM_CHECKPOINTS.get()),
42        });
43    }
44
45    // TODO: Is there a point in having both values derived from the same source?
46    Ok(aes::create(
47        seed,
48        seed.key(),
49        iterations.get() / u32::from(PotCheckpoints::NUM_CHECKPOINTS.get()),
50    ))
51}
52
53/// Verify checkpoint, number of iterations is set across uniformly distributed checkpoints.
54///
55/// Returns error if `iterations` is not a multiple of checkpoints times two.
56// TODO: Figure out what is wrong with macOS here
57#[cfg_attr(
58    all(feature = "no-panic", not(target_os = "macos")),
59    no_panic::no_panic
60)]
61pub fn verify(
62    seed: PotSeed,
63    iterations: NonZeroU32,
64    checkpoints: &PotCheckpoints,
65) -> Result<bool, PotError> {
66    let num_checkpoints = checkpoints.len() as u32;
67    if !iterations.get().is_multiple_of(num_checkpoints * 2) {
68        return Err(PotError::NotMultipleOfCheckpoints {
69            iterations,
70            num_checkpoints,
71        });
72    }
73
74    Ok(aes::verify_sequential(
75        seed,
76        seed.key(),
77        checkpoints,
78        iterations.get() / num_checkpoints,
79    ))
80}