arcium-core-utils 0.4.4

Arcium core utils
Documentation
pub mod batcher;
#[allow(clippy::module_inception)]
pub mod circuit;
pub(super) mod compressed_circuit;
pub mod errors;
pub mod gate;
#[cfg(any(test, feature = "dev"))]
pub mod mock_eval;
pub mod ops;
pub mod preprocessing;
pub mod slice;

pub use circuit::*;
pub use gate::*;
pub use ops::*;
pub use preprocessing::*;
use serde::{Deserialize, Serialize};
pub use slice::*;
use wincode::{SchemaRead, SchemaWrite};

use crate::circuit::errors::ConversionError;

pub type GateIndex = u32;
pub type BatchSize = GateIndex;

#[derive(
    Debug,
    Clone,
    Copy,
    PartialEq,
    Eq,
    Hash,
    Serialize,
    Deserialize,
    SchemaRead,
    SchemaWrite,
    PartialOrd,
    Ord,
)]
#[repr(C)]
pub enum FieldType {
    BaseField,
    ScalarField,
    Mersenne107,
}

#[derive(
    Debug,
    Clone,
    Copy,
    PartialEq,
    Eq,
    Hash,
    Serialize,
    Deserialize,
    SchemaRead,
    SchemaWrite,
    PartialOrd,
    Ord,
)]
#[repr(C)]
pub enum AlgebraicType {
    BaseField,
    ScalarField,
    Point,
    Bit,
    Mersenne107,
}

#[derive(
    Debug,
    Clone,
    Copy,
    PartialEq,
    Eq,
    Hash,
    Serialize,
    Deserialize,
    SchemaRead,
    SchemaWrite,
    PartialOrd,
    Ord,
)]
#[repr(C)]
pub enum ShareOrPlaintext {
    Share,
    Plaintext,
}

impl From<FieldType> for AlgebraicType {
    fn from(field_type: FieldType) -> Self {
        match field_type {
            FieldType::BaseField => AlgebraicType::BaseField,
            FieldType::ScalarField => AlgebraicType::ScalarField,
            FieldType::Mersenne107 => AlgebraicType::Mersenne107,
        }
    }
}

impl TryFrom<AlgebraicType> for FieldType {
    type Error = ConversionError;

    fn try_from(value: AlgebraicType) -> Result<Self, Self::Error> {
        match value {
            AlgebraicType::BaseField => Ok(FieldType::BaseField),
            AlgebraicType::ScalarField => Ok(FieldType::ScalarField),
            AlgebraicType::Point => Err(ConversionError::IntoFieldTypeError(value)),
            AlgebraicType::Bit => Err(ConversionError::IntoFieldTypeError(value)),
            AlgebraicType::Mersenne107 => Ok(FieldType::Mersenne107),
        }
    }
}

#[cfg(test)]
mod tests {
    use itertools::Itertools;
    use primitives::algebra::elliptic_curve::Curve;

    use crate::circuit::{AlgebraicType, Circuit, FieldShareBinaryOp, Gate, Input};

    pub fn create_add_tree_circuit<C: Curve>(depth: usize) -> Circuit<C> {
        let mut circuit = Circuit::<C>::new();
        let inputs = (0..(1 << depth))
            .map(|_| {
                circuit
                    .add_gate(Gate::Input(Input::SecretPlaintext {
                        inputer: 0,
                        algebraic_type: AlgebraicType::Mersenne107,
                        batch_size: 3,
                    }))
                    .unwrap()
            })
            .collect_vec();

        let mut level_gates = inputs;
        while level_gates.len() > 1 {
            let mut next_level = vec![];
            for chunk in level_gates.chunks(2) {
                let index = if chunk.len() == 2 {
                    circuit
                        .add_gate(Gate::FieldShareBinaryOp {
                            x: chunk[0],
                            y: chunk[1],
                            op: FieldShareBinaryOp::Add,
                        })
                        .unwrap()
                } else {
                    assert_eq!(chunk.len(), 1);
                    chunk[0]
                };
                next_level.push(index);
            }
            level_gates = next_level;
        }
        assert_eq!(level_gates.len(), 1);

        circuit.add_output(level_gates[0]).unwrap();

        circuit
    }

    pub fn create_mul_tree_circuit<C: Curve>(depth: usize) -> Circuit<C> {
        let mut circuit = Circuit::<C>::new();
        let inputs = (0..(1 << depth))
            .map(|_| {
                circuit
                    .add_gate(Gate::Input(Input::SecretPlaintext {
                        inputer: 0,
                        algebraic_type: AlgebraicType::Mersenne107,
                        batch_size: 3,
                    }))
                    .unwrap()
            })
            .collect_vec();

        let mut level_gates = inputs;
        while level_gates.len() > 1 {
            let mut next_level = vec![];
            for chunk in level_gates.chunks(2) {
                let index = if chunk.len() == 2 {
                    circuit
                        .add_gate(Gate::FieldShareBinaryOp {
                            x: chunk[0],
                            y: chunk[1],
                            op: FieldShareBinaryOp::Mul,
                        })
                        .unwrap()
                } else {
                    assert_eq!(chunk.len(), 1);
                    chunk[0]
                };
                next_level.push(index);
            }
            level_gates = next_level;
        }
        assert_eq!(level_gates.len(), 1);

        circuit.add_output(level_gates[0]).unwrap();

        circuit
    }
}