@@ -59,11 +59,11 @@ pub struct ConstraintSystem<F: Field> {
59
59
60
60
/// Assignments to the public input variables. This is empty if `self.mode
61
61
/// == SynthesisMode::Setup`.
62
- instance_assignment : Vec < F > ,
62
+ pub instance_assignment : Vec < F > ,
63
63
64
64
/// Assignments to the private input variables. This is empty if `self.mode
65
65
/// == SynthesisMode::Setup`.
66
- witness_assignment : Vec < F > ,
66
+ pub witness_assignment : Vec < F > ,
67
67
68
68
/// Map for gadgets to cache computation results.
69
69
pub cache_map : Rc < RefCell < BTreeMap < TypeId , Box < dyn Any > > > > ,
@@ -227,10 +227,6 @@ impl<F: Field> ConstraintSystem<F> {
227
227
return Err ( SynthesisError :: PredicateNotFound ) ;
228
228
}
229
229
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
-
234
230
let lc_indices = lc_vec. into_iter ( ) . map ( |lc| {
235
231
let var = {
236
232
let index = LcIndex ( self . num_linear_combinations ) ;
@@ -754,31 +750,37 @@ impl<F: Field> ConstraintSystem<F> {
754
750
/// and uses these witness variables in the constraints instead of instance
755
751
/// variables. This technique is useful for verifier succinctness in some
756
752
/// SNARKs like Garuda, Pari and PolyMath
753
+ /// After the function call, The instances are only used in the `c` matrix
754
+ /// of r1cs
757
755
pub ( crate ) fn do_outline_instances ( & mut self ) -> crate :: gr1cs:: Result < ( ) > {
756
+ // First build a map from instance variables to witness variables
758
757
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 ) ) ;
761
763
self . num_witness_variables += 1 ;
762
764
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 ( ) {
765
769
if var. is_instance ( ) {
766
770
let _witness = instance_to_witness_map
767
771
. entry ( * var)
768
772
. or_insert ( Variable :: Witness ( self . num_witness_variables ) ) ;
769
773
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 ( ) {
777
774
* 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;
778
778
}
779
779
}
780
780
}
781
781
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
782
784
if !self . is_in_setup_mode ( ) {
783
785
self . witness_assignment . resize (
784
786
self . witness_assignment . len ( ) + instance_to_witness_map. len ( ) ,
@@ -796,13 +798,26 @@ impl<F: Field> ConstraintSystem<F> {
796
798
}
797
799
}
798
800
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
800
806
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
+
806
821
self . enforce_constraint ( R1CS_PREDICATE_LABEL , r1cs_constraint) ?;
807
822
}
808
823
0 commit comments