provekit-common 0.1.1

Common types and utilities for the ProveKit proving system
Documentation
mod binops;
mod digits;
mod ram;
mod scheduling;
mod witness_builder;
mod witness_generator;

use {
    crate::{
        utils::{serde_ark, serde_ark_vec},
        FieldElement,
    },
    ark_ff::{BigInt, BigInteger, One, PrimeField},
    serde::{Deserialize, Serialize},
};
pub use {
    binops::{BINOP_ATOMIC_BITS, BINOP_BITS, NUM_DIGITS},
    digits::{decompose_into_digits, DigitalDecompositionWitnesses},
    ram::{SpiceMemoryOperation, SpiceWitnesses},
    scheduling::{Layer, LayerType, LayeredWitnessBuilders, SplitError, SplitWitnessBuilders},
    witness_builder::{
        CombinedTableEntryInverseData, ConstantTerm, ProductLinearTerm, SumTerm, WitnessBuilder,
        WitnessCoefficient,
    },
    witness_generator::NoirWitnessGenerator,
};

/// The index of the constant 1 witness in the R1CS instance
pub const WITNESS_ONE_IDX: usize = 0;

/// Compute spread(val): interleave bits of val with zeros.
/// E.g., `0b1011` → `0b01_00_01_01`.
pub fn compute_spread(val: u64) -> u64 {
    let mut result = 0u64;
    for i in 0..32 {
        result |= ((val >> i) & 1) << (2 * i);
    }
    result
}

#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
pub enum ConstantOrR1CSWitness {
    Constant(#[serde(with = "serde_ark")] FieldElement),
    Witness(usize),
}

impl ConstantOrR1CSWitness {
    #[must_use]
    pub fn to_tuple(&self) -> (FieldElement, usize) {
        match self {
            ConstantOrR1CSWitness::Constant(c) => (*c, WITNESS_ONE_IDX),
            ConstantOrR1CSWitness::Witness(w) => (FieldElement::one(), *w),
        }
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PublicInputs(#[serde(with = "serde_ark_vec")] pub Vec<FieldElement>);

impl PublicInputs {
    #[must_use]
    pub fn new() -> Self {
        Self(Vec::new())
    }

    #[must_use]
    pub fn from_vec(vec: Vec<FieldElement>) -> Self {
        Self(vec)
    }

    #[must_use]
    pub fn len(&self) -> usize {
        self.0.len()
    }

    #[must_use]
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    #[must_use]
    pub fn hash(&self) -> FieldElement {
        fn compress(l: FieldElement, r: FieldElement) -> FieldElement {
            let out = skyscraper::simple::compress(l.into_bigint().0, r.into_bigint().0);
            FieldElement::new(BigInt(out))
        }

        match self.0.len() {
            0 => FieldElement::from(0u64),
            1 => compress(self.0[0], FieldElement::from(0u64)),
            _ => self.0.iter().copied().reduce(compress).unwrap(),
        }
    }

    #[must_use]
    pub fn hash_bytes(&self) -> [u8; 32] {
        let hash = self.hash();
        let bytes = hash.into_bigint().to_bytes_le();
        let mut result = [0u8; 32];
        let len = bytes.len().min(32);
        result[..len].copy_from_slice(&bytes[..len]);
        result
    }
}

impl Default for PublicInputs {
    fn default() -> Self {
        Self::new()
    }
}