mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-12 00:41:28 +01:00
Add decider circuit RelaxedR1CS (#21)
- Add naive decider circuit `RelaxedR1CSGadget`, which in-circuit checks that the given z satisfies the given RelaxedR1CS instance - Add method to relax the R1CS instance - Add check_relation (for testing only) to R1CS & RelaxedR1CS - Migrate from own SparseMatrix to use ark_relations::r1cs::Matrix - Add frontend helper to use arkworks circuits
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use ark_ff::PrimeField;
|
||||
|
||||
use crate::utils::vec::*;
|
||||
use crate::Error;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct R1CS<F: PrimeField> {
|
||||
@@ -9,17 +10,67 @@ pub struct R1CS<F: PrimeField> {
|
||||
pub B: SparseMatrix<F>,
|
||||
pub C: SparseMatrix<F>,
|
||||
}
|
||||
|
||||
impl<F: PrimeField> R1CS<F> {
|
||||
/// returns a tuple containing (w, x) (witness and public inputs respectively)
|
||||
pub fn split_z(&self, z: &[F]) -> (Vec<F>, Vec<F>) {
|
||||
(z[self.l + 1..].to_vec(), z[1..self.l + 1].to_vec())
|
||||
}
|
||||
|
||||
/// check that a R1CS structure is satisfied by a z vector. Only for testing.
|
||||
pub fn check_relation(&self, z: &[F]) -> Result<(), Error> {
|
||||
let Az = mat_vec_mul_sparse(&self.A, z);
|
||||
let Bz = mat_vec_mul_sparse(&self.B, z);
|
||||
let Cz = mat_vec_mul_sparse(&self.C, z);
|
||||
let AzBz = hadamard(&Az, &Bz);
|
||||
assert_eq!(AzBz, Cz);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// converts the R1CS instance into a RelaxedR1CS as described in
|
||||
/// [Nova](https://eprint.iacr.org/2021/370.pdf) section 4.1.
|
||||
pub fn relax(self) -> RelaxedR1CS<F> {
|
||||
RelaxedR1CS::<F> {
|
||||
l: self.l,
|
||||
E: vec![F::zero(); self.A.n_rows],
|
||||
A: self.A,
|
||||
B: self.B,
|
||||
C: self.C,
|
||||
u: F::one(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct RelaxedR1CS<F: PrimeField> {
|
||||
pub l: usize, // io len
|
||||
pub A: SparseMatrix<F>,
|
||||
pub B: SparseMatrix<F>,
|
||||
pub C: SparseMatrix<F>,
|
||||
pub u: F,
|
||||
pub E: Vec<F>,
|
||||
}
|
||||
impl<F: PrimeField> RelaxedR1CS<F> {
|
||||
/// check that a RelaxedR1CS structure is satisfied by a z vector. Only for testing.
|
||||
pub fn check_relation(&self, z: &[F]) -> Result<(), Error> {
|
||||
let Az = mat_vec_mul_sparse(&self.A, z);
|
||||
let Bz = mat_vec_mul_sparse(&self.B, z);
|
||||
let Cz = mat_vec_mul_sparse(&self.C, z);
|
||||
let uCz = vec_scalar_mul(&Cz, &self.u);
|
||||
let uCzE = vec_add(&uCz, &self.E);
|
||||
let AzBz = hadamard(&Az, &Bz);
|
||||
assert_eq!(AzBz, uCzE);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use crate::utils::vec::tests::{to_F_matrix, to_F_vec};
|
||||
use ark_pallas::Fr;
|
||||
|
||||
pub fn get_test_r1cs<F: PrimeField>() -> R1CS<F> {
|
||||
// R1CS for: x^3 + x + 5 = y (example from article
|
||||
@@ -57,4 +108,12 @@ pub mod tests {
|
||||
input * input * input + input, // x^3 + x
|
||||
])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_relation() {
|
||||
let r1cs = get_test_r1cs::<Fr>();
|
||||
let z = get_test_z(5);
|
||||
r1cs.check_relation(&z).unwrap();
|
||||
r1cs.relax().check_relation(&z).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user