pub mod batcher;
pub mod circuit;
pub(super) mod compressed_circuit;
pub mod errors;
#[cfg(test)]
mod format_fingerprint;
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::*;
use serde::{Deserialize, Serialize};
pub use slice::*;
use crate::circuit::errors::ConversionError;
pub type GateIndex = u32;
pub type BatchSize = GateIndex;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
#[repr(C)]
pub enum FieldType {
BaseField,
ScalarField,
MpcField,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
#[repr(C)]
pub enum AlgebraicType {
BaseField,
ScalarField,
Point,
Bit,
MpcField,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, 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::MpcField => AlgebraicType::MpcField,
}
}
}
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::MpcField => Ok(FieldType::MpcField),
}
}
}
#[cfg(test)]
mod tests {
use itertools::Itertools;
use primitives::utils::bincode_io;
use crate::{
circuit::{AlgebraicType, Circuit, FieldShareBinaryOp, Gate, Input},
config::MpcConfig,
};
pub fn create_add_tree_circuit<C: MpcConfig>(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::MpcField,
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: MpcConfig>(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::MpcField,
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
}
#[test]
fn field_type_discriminants_are_stable() {
use primitives::algebra::field::{mersenne::Mersenne107, SubfieldElement};
use crate::{
circuit::latest::{Constant, FieldType},
config::DefaultConfig,
};
assert_eq!(
bincode_io::serialize(&FieldType::MpcField).unwrap(),
[2, 0, 0, 0]
);
assert_eq!(
bincode_io::serialize(&AlgebraicType::MpcField).unwrap(),
[4, 0, 0, 0]
);
let constant: Constant<DefaultConfig> =
Constant::MpcField(SubfieldElement::<Mersenne107>::from(42u64));
assert_eq!(
bincode_io::serialize(&constant).unwrap(),
[4, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
);
}
}