Skip to content

Commit f632770

Browse files
Fix and comments for instance outlining (#386)
* r1cs replaced with gr1cs * addressed the PR comments * instance assignment getter created * instance assignment fixed outer * nax_arity added * predicate num constraints added * bump version to 0.5.0 and update dependencies * refactor: changed the constraint storage method in the predicates * Fix: predicate weakly references to a constraint system * polish * feat: expose R1CS_PREDICATE_LABEL from gr1cs module * refactor: move make_row method to ConstraintSystem and ConstraintSystemRef for matrix row creation * refactor: update make_row method to improve error handling and clarity * refactor: Replaced the weak reference with downstreaming constraint system reference * tracing checked * work * works * ready to review * finalized * Update * Fix * Fix * Remove patches * Bug Fix: Outline instances handling 'One' * bug fix: Handling one in instance outline * outline instance optimized * path instance_outline * Bug Fix: Outline instances handling 'One' * bug fix: Handling one in instance outline * outline instance optimized * path instance_outline * Fmt * Fix * Fix --------- Co-authored-by: Alireza Shirzad <alr.shirzad@gmail.com>
1 parent 9c52852 commit f632770

File tree

4 files changed

+63
-29
lines changed

4 files changed

+63
-29
lines changed

relations/src/gr1cs/constraint_system.rs

+38-23
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ pub struct ConstraintSystem<F: Field> {
5959

6060
/// Assignments to the public input variables. This is empty if `self.mode
6161
/// == SynthesisMode::Setup`.
62-
instance_assignment: Vec<F>,
62+
pub instance_assignment: Vec<F>,
6363

6464
/// Assignments to the private input variables. This is empty if `self.mode
6565
/// == SynthesisMode::Setup`.
66-
witness_assignment: Vec<F>,
66+
pub witness_assignment: Vec<F>,
6767

6868
/// Map for gadgets to cache computation results.
6969
pub cache_map: Rc<RefCell<BTreeMap<TypeId, Box<dyn Any>>>>,
@@ -227,10 +227,6 @@ impl<F: Field> ConstraintSystem<F> {
227227
return Err(SynthesisError::PredicateNotFound);
228228
}
229229
if self.should_construct_matrices() {
230-
// TODO: Find a way to get rid of the following collect, barrier1: we need the
231-
// size, possible to use ExactSizeIterator, barrier2: We will need lifetimes
232-
// which leads to having two &mut refs to self
233-
234230
let lc_indices = lc_vec.into_iter().map(|lc| {
235231
let var = {
236232
let index = LcIndex(self.num_linear_combinations);
@@ -754,31 +750,37 @@ impl<F: Field> ConstraintSystem<F> {
754750
/// and uses these witness variables in the constraints instead of instance
755751
/// variables. This technique is useful for verifier succinctness in some
756752
/// SNARKs like Garuda, Pari and PolyMath
753+
/// After the function call, The instances are only used in the `c` matrix
754+
/// of r1cs
757755
pub(crate) fn do_outline_instances(&mut self) -> crate::gr1cs::Result<()> {
756+
// First build a map from instance variables to witness variables
758757
let mut instance_to_witness_map = BTreeMap::<Variable, Variable>::new();
759-
instance_to_witness_map
760-
.insert(Variable::One, Variable::Witness(self.num_witness_variables));
758+
// Initialize the map with the one variable, this is done manually because we
759+
// certainely need this variable and it might not show up in the lc_map
760+
let one_witt = instance_to_witness_map
761+
.insert(Variable::One, Variable::Witness(self.num_witness_variables))
762+
.unwrap_or(Variable::Witness(self.num_witness_variables));
761763
self.num_witness_variables += 1;
762764

763-
for (_, lc) in self.lc_map.iter() {
764-
for (_, var) in lc.iter() {
765+
// Now, Go over all the linear combinations and create a new witness for each
766+
// instance variable you see
767+
for (_, lc) in self.lc_map.iter_mut() {
768+
for (_, var) in lc.iter_mut() {
765769
if var.is_instance() {
766770
let _witness = instance_to_witness_map
767771
.entry(*var)
768772
.or_insert(Variable::Witness(self.num_witness_variables));
769773
self.num_witness_variables += 1;
770-
}
771-
}
772-
}
773-
774-
for (_, lc) in self.lc_map.iter_mut() {
775-
for (_, var) in lc.iter_mut() {
776-
if var.is_instance() {
777774
*var = instance_to_witness_map[var];
775+
} else if var.is_one() {
776+
// if the variable is one, the witness is already created, just replace it
777+
*var = one_witt;
778778
}
779779
}
780780
}
781781

782+
// If we're not in the setup mode, we also have to update the assignments:
783+
// Append the newly created witness assignments to the witness assignment vector
782784
if !self.is_in_setup_mode() {
783785
self.witness_assignment.resize(
784786
self.witness_assignment.len() + instance_to_witness_map.len(),
@@ -796,13 +798,26 @@ impl<F: Field> ConstraintSystem<F> {
796798
}
797799
}
798800

799-
let one_witt = instance_to_witness_map.get(&Variable::One).unwrap();
801+
// Now, enforce the equality between the instance and the corresponding witness
802+
// variable This is done by iterating over the instance-witness map
803+
// which contains the unique instance-witness pairs The equality
804+
// constraints are enforced with r1cs constraints, it is assumed that a
805+
// constraint system has a default r1cs predicate registered
800806
for (instance, witness) in instance_to_witness_map.iter() {
801-
let r1cs_constraint = vec![
802-
LinearCombination::from(*instance),
803-
LinearCombination::from(*one_witt),
804-
LinearCombination::from(*witness),
805-
];
807+
let r1cs_constraint = if instance.is_one() {
808+
vec![
809+
LinearCombination::from(*witness),
810+
LinearCombination::from(*witness),
811+
LinearCombination::from(*instance),
812+
]
813+
} else {
814+
vec![
815+
LinearCombination::from(one_witt),
816+
LinearCombination::from(*witness),
817+
LinearCombination::from(*instance),
818+
]
819+
};
820+
806821
self.enforce_constraint(R1CS_PREDICATE_LABEL, r1cs_constraint)?;
807822
}
808823

relations/src/gr1cs/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ pub use crate::{
3737
pub use namespace::Namespace;
3838
///////////////////////////////////////////////////////////////////////////////////////
3939

40-
/// Computations are expressed in terms of generalized rank-1 constraint systems (GR1CS).
41-
/// The `generate_constraints` method is called to generate constraints for
42-
/// both CRS generation and for proving.
40+
/// Computations are expressed in terms of generalized rank-1 constraint systems
41+
/// (GR1CS). The `generate_constraints` method is called to generate constraints
42+
/// for both CRS generation and for proving.
4343
// TODO: Think: should we replace this with just a closure?
4444
pub trait ConstraintSynthesizer<F: Field> {
4545
/// Drives generation of new constraints inside `cs`.

relations/src/gr1cs/predicate/mod.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub mod polynomial_constraint;
88
use super::{Constraint, ConstraintSystem, LcIndex, Matrix};
99
use crate::utils::{error::SynthesisError::ArityMismatch, variable::Variable::SymbolicLc};
1010
use ark_ff::Field;
11-
use ark_serialize::{CanonicalSerialize, Compress, SerializationError};
11+
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError};
1212
use ark_std::{io::Write, vec::Vec};
1313
use polynomial_constraint::PolynomialPredicate;
1414

@@ -24,6 +24,25 @@ pub enum PredicateType<F: Field> {
2424
// Add other predicates in the future, e.g. lookup table
2525
}
2626

27+
impl<F: Field> ark_serialize::Valid for PredicateType<F> {
28+
fn check(&self) -> Result<(), SerializationError> {
29+
match self {
30+
PredicateType::Polynomial(p) => p.check(),
31+
}
32+
}
33+
}
34+
impl<F: Field> CanonicalDeserialize for PredicateType<F> {
35+
fn deserialize_with_mode<R: ark_serialize::Read>(
36+
reader: R,
37+
compress: Compress,
38+
should_validate: ark_serialize::Validate,
39+
) -> Result<Self, SerializationError> {
40+
let predicate_type =
41+
PolynomialPredicate::<F>::deserialize_with_mode(reader, compress, should_validate)?;
42+
Ok(PredicateType::Polynomial(predicate_type))
43+
}
44+
}
45+
2746
impl<F: Field> CanonicalSerialize for PredicateType<F> {
2847
fn serialize_with_mode<W: Write>(
2948
&self,

relations/src/gr1cs/predicate/polynomial_constraint.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ use ark_poly::{
88
multivariate::{SparsePolynomial, SparseTerm, Term},
99
DenseMVPolynomial, Polynomial,
1010
};
11-
use ark_serialize::CanonicalSerialize;
11+
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
1212
use ark_std::vec::Vec;
1313

1414
/// A polynomial predicat is just a polynomial
15-
#[derive(Debug, Clone, CanonicalSerialize)]
15+
#[derive(Debug, Clone, CanonicalSerialize, CanonicalDeserialize)]
1616
pub struct PolynomialPredicate<F: Field> {
1717
/// The sparse polynomial for the predicate
1818
pub polynomial: SparsePolynomial<F, SparseTerm>,

0 commit comments

Comments
 (0)