subspace_proof_of_time/
lib.rs

1//! Proof of time implementation.
2
3#![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 core::num::NonZeroU32;
11use subspace_core_primitives::pot::{PotCheckpoints, PotSeed};
12
13/// Proof of time error
14#[derive(Debug, thiserror::Error)]
15pub enum PotError {
16    /// Iterations are not multiple of number of checkpoints times two
17    #[error(
18        "Iterations {iterations} are not multiple of number of checkpoints {num_checkpoints} \
19        times two"
20    )]
21    NotMultipleOfCheckpoints {
22        /// Slot iterations provided
23        iterations: NonZeroU32,
24        /// Number of checkpoints
25        num_checkpoints: u32,
26    },
27}
28
29/// Run PoT proving and produce checkpoints.
30///
31/// Returns error if `iterations` is not a multiple of checkpoints times two.
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(
41        seed,
42        seed.key(),
43        iterations.get() / u32::from(PotCheckpoints::NUM_CHECKPOINTS.get()),
44    ))
45}
46
47/// Verify checkpoint, number of iterations is set across uniformly distributed checkpoints.
48///
49/// Returns error if `iterations` is not a multiple of checkpoints times two.
50pub fn verify(
51    seed: PotSeed,
52    iterations: NonZeroU32,
53    checkpoints: &PotCheckpoints,
54) -> Result<bool, PotError> {
55    let num_checkpoints = checkpoints.len() as u32;
56    if iterations.get() % (num_checkpoints * 2) != 0 {
57        return Err(PotError::NotMultipleOfCheckpoints {
58            iterations,
59            num_checkpoints,
60        });
61    }
62
63    Ok(aes::verify_sequential(
64        seed,
65        seed.key(),
66        checkpoints,
67        iterations.get() / num_checkpoints,
68    ))
69}