use ark_relations::gr1cs::SynthesisError;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::{fmt::Debug, log2};
use thiserror::Error;
use crate::relations::{Relation, RelationGadget};
pub mod ccs;
pub mod r1cs;
#[derive(Error, Debug)]
pub enum Error {
#[error("The provided assignments have incorrect shape: {0}")]
MalformedAssignments(String),
#[error("The provided assignments do not satisfy the constraint system: {0}")]
UnsatisfiedAssignments(String),
#[error(
"The number of constraints in the constraint system configuration is invalid. Provided: {0}, expected: {1}"
)]
InvalidNumberOfConstraints(usize, usize),
#[error(
"The number of variables in the constraint system configuration is invalid. Provided: {0}, expected: {1}"
)]
InvalidNumberOfVariables(usize, usize),
#[error(transparent)]
SynthesisError(#[from] SynthesisError),
}
#[derive(Clone, Debug, Default, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
pub struct ArithConfig {
pub degree: usize,
pub n_constraints: usize,
pub n_variables: usize,
pub n_public_inputs: usize,
pub n_witnesses: usize,
}
impl ArithConfig {
pub fn log_constraints(&self) -> usize {
log2(self.n_constraints) as usize
}
}
pub trait Arith: Clone + Default + Send + Sync + CanonicalSerialize + CanonicalDeserialize {
fn config(&self) -> ArithConfig;
}
pub trait ArithRelation<W: ?Sized, U: ?Sized>: Arith {
type Evaluation;
fn eval_relation(&self, w: &W, u: &U) -> Result<Self::Evaluation, Error>;
fn check_evaluation(w: &W, u: &U, v: Self::Evaluation) -> Result<(), Error>;
}
impl<W, U, A: ArithRelation<W, U>> Relation<W, U> for A {
type Error = Error;
fn check_relation(&self, w: &W, u: &U) -> Result<(), Self::Error> {
let e = self.eval_relation(w, u)?;
Self::check_evaluation(w, u, e)
}
}
pub trait ArithRelationGadget<WVar, UVar> {
type Evaluation;
fn eval_relation(&self, w: &WVar, u: &UVar) -> Result<Self::Evaluation, SynthesisError>;
fn check_evaluation(w: &WVar, u: &UVar, e: Self::Evaluation) -> Result<(), SynthesisError>;
}
impl<WVar, UVar, A: ArithRelationGadget<WVar, UVar>> RelationGadget<WVar, UVar> for A {
fn check_relation(&self, w: &WVar, u: &UVar) -> Result<(), SynthesisError> {
let e = self.eval_relation(w, u)?;
Self::check_evaluation(w, u, e)
}
}