1
1
//! This module contains the implementation of the `ConstraintSystem` struct.
2
2
//! a constraint system contains multiple predicate constraint systems,
3
- //! each of which enforce have seperate predicates and constraints. For more infomation about the terminology and the structure of the constraint system, refer to section 3.3 of https://eprint.iacr.org/2024/1245
3
+ //! each of which enforce have separate predicates and constraints. For more information about the terminology and the structure of the constraint system, refer to section 3.3 of https://eprint.iacr.org/2024/1245
4
4
5
5
use super :: {
6
+ instance_outliner:: InstanceOutliner ,
6
7
predicate:: {
7
8
polynomial_constraint:: R1CS_PREDICATE_LABEL , PredicateConstraintSystem , PredicateType ,
8
9
} ,
@@ -22,6 +23,7 @@ use ark_std::{
22
23
string:: { String , ToString } ,
23
24
vec:: Vec ,
24
25
} ;
26
+ // TODO: Prayush's PR, Hashbrown, HAshmap for nostd
25
27
///////////////////////////////////////////////////////////////////////////////////////
26
28
27
29
/// A GR1CS `ConstraintSystem`. Enforces constraints of the form
@@ -55,7 +57,7 @@ pub struct ConstraintSystem<F: Field> {
55
57
/// It assigns a witness variable to each instance variable and enforces the
56
58
/// equality of the instance and witness variables. Then only uses the
57
59
/// witness variables in the constraints.
58
- outline_instances : bool ,
60
+ instance_outliner : Option < InstanceOutliner < F > > ,
59
61
60
62
/// Assignments to the public input variables. This is empty if `self.mode
61
63
/// == SynthesisMode::Setup`.
@@ -99,7 +101,7 @@ impl<F: Field> ConstraintSystem<F> {
99
101
num_instance_variables : 1 ,
100
102
num_witness_variables : 0 ,
101
103
num_linear_combinations : 0 ,
102
- outline_instances : false ,
104
+ instance_outliner : None ,
103
105
predicate_constraint_systems : BTreeMap :: new ( ) ,
104
106
instance_assignment : vec ! [ F :: one( ) ] ,
105
107
witness_assignment : Vec :: new ( ) ,
@@ -109,7 +111,7 @@ impl<F: Field> ConstraintSystem<F> {
109
111
mode : SynthesisMode :: Prove {
110
112
construct_matrices : true ,
111
113
} ,
112
- optimization_goal : OptimizationGoal :: Constraints ,
114
+ optimization_goal : OptimizationGoal :: None ,
113
115
#[ cfg( feature = "std" ) ]
114
116
predicate_traces : BTreeMap :: new ( ) ,
115
117
} ;
@@ -361,6 +363,11 @@ impl<F: Field> ConstraintSystem<F> {
361
363
Ok ( ( ) )
362
364
}
363
365
366
+ /// Remove the predicate with the given label from the constraint system.
367
+ pub fn remove_predicate ( & mut self , predicate_label : & str ) {
368
+ self . predicate_constraint_systems . remove ( predicate_label) ;
369
+ }
370
+
364
371
/// check if there is a predicate with the given label
365
372
pub fn has_predicate ( & self , predicate_label : & str ) -> bool {
366
373
self . predicate_constraint_systems
@@ -402,15 +409,15 @@ impl<F: Field> ConstraintSystem<F> {
402
409
/// If `self` is unsatisfied, outputs `Ok(false)`.
403
410
/// If `self.is_in_setup_mode()` or if `self == None`, outputs `Err(())`.
404
411
pub fn is_satisfied ( & self ) -> crate :: utils:: Result < bool > {
405
- self . which_predicate_is_unsatisfied ( ) . map ( |s| s. is_none ( ) )
412
+ self . which_is_unsatisfied ( ) . map ( |s| s. is_none ( ) )
406
413
}
407
414
408
415
/// If `self` is satisfied, outputs `Ok(None)`.
409
416
/// If `self` is unsatisfied, outputs `Some(s,i)`, where `s` is the label of
410
417
/// the unsatisfied prediacate and `i` is the index of
411
418
/// the first unsatisfied constraint in that predicate.
412
419
/// If `self.is_in_setup_mode()` or `self == None`, outputs `Err(())`.
413
- pub fn which_predicate_is_unsatisfied ( & self ) -> crate :: utils:: Result < Option < String > > {
420
+ pub fn which_is_unsatisfied ( & self ) -> crate :: utils:: Result < Option < String > > {
414
421
if self . is_in_setup_mode ( ) {
415
422
Err ( SynthesisError :: AssignmentMissing )
416
423
} else {
@@ -448,24 +455,35 @@ impl<F: Field> ConstraintSystem<F> {
448
455
/// Finalize the constraint system (either by outlining or inlining,
449
456
/// if an optimization goal is set).
450
457
pub fn finalize ( & mut self ) {
458
+ let timer_finalize = start_timer ! ( || "Finalize GR1CS" ) ;
459
+ let timer_inline_ouline_lcs = start_timer ! ( || "Inline/Outline LCs" ) ;
451
460
match self . optimization_goal {
452
- OptimizationGoal :: None => self . inline_all_lcs ( ) ,
453
461
OptimizationGoal :: Constraints => self . inline_all_lcs ( ) ,
454
462
OptimizationGoal :: Weight => self . outline_lcs ( ) ,
463
+ _ => self . inline_all_lcs ( ) ,
455
464
} ;
456
- if self . outline_instances {
457
- let _ = self . do_outline_instances ( ) ;
465
+ end_timer ! ( timer_inline_ouline_lcs) ;
466
+ // check if should outline instance or not
467
+ let timer_instance_outlining = start_timer ! ( || "Instance Outlining" ) ;
468
+ if let Some ( instance_outliner) = self . instance_outliner . take ( ) {
469
+ // Check if the predicate to be outlined is in the constraint system
470
+ if self . has_predicate ( & instance_outliner. pred_label ) {
471
+ // Outline the instances
472
+ let _ = self . perform_instance_outlining ( instance_outliner) ;
473
+ }
458
474
}
475
+ end_timer ! ( timer_instance_outlining) ;
476
+ end_timer ! ( timer_finalize) ;
459
477
}
460
478
461
479
/// Naively inlines symbolic linear combinations into the linear
462
480
/// combinations that use them.
463
481
///
464
- /// Useful for standard pairing-based SNARKs where addition gates are cheap.
465
- /// For example, in the SNARKs such as [\[Groth16\]](https://eprint.iacr.org/2016/260) and
482
+ /// Useful for standard pairing-based SNARKs where addition gates are
483
+ /// cheap. For example, in the SNARKs such as [\[Groth16\]](https://eprint.iacr.org/2016/260) and
466
484
/// [\[Groth-Maller17\]](https://eprint.iacr.org/2017/540), addition gates
467
- /// do not contribute to the size of the multi-scalar multiplication, which
468
- /// is the dominating cost.
485
+ /// do not contribute to the size of the multi-scalar multiplication,
486
+ /// which is the dominating cost.
469
487
pub fn inline_all_lcs ( & mut self ) {
470
488
// Only inline when a matrix representing R1CS is needed.
471
489
if !self . should_construct_matrices ( ) {
@@ -478,11 +496,11 @@ impl<F: Field> ConstraintSystem<F> {
478
496
self . transform_lc_map ( & mut |_, _, _| ( 0 , None ) ) ;
479
497
}
480
498
481
- /// If a `SymbolicLc` is used in more than one location and has sufficient
482
- /// length, this method makes a new variable for that `SymbolicLc`, adds
483
- /// a constraint ensuring the equality of the variable and the linear
484
- /// combination, and then uses that variable in every location the
485
- /// `SymbolicLc` is used.
499
+ /// If a `SymbolicLc` is used in more than one location and has
500
+ /// sufficient length, this method makes a new variable for that
501
+ /// `SymbolicLc`, adds a constraint ensuring the equality of the
502
+ /// variable and the linear combination, and then uses that
503
+ /// variable in every location the `SymbolicLc` is used.
486
504
///
487
505
/// Useful for SNARKs like [\[Marlin\]](https://eprint.iacr.org/2019/1047) or
488
506
/// [\[Fractal\]](https://eprint.iacr.org/2019/1076), where addition gates
@@ -583,10 +601,10 @@ impl<F: Field> ConstraintSystem<F> {
583
601
/// This method is used as a subroutine of `inline_all_lcs` and
584
602
/// `outline_lcs`.
585
603
///
586
- /// The transformer function is given a references of this constraint system
587
- /// (&self), number of times used, and a mutable reference of the linear
588
- /// combination to be transformed. (&ConstraintSystem<F>, usize,
589
- /// &mut LinearCombination<F>)
604
+ /// The transformer function is given a references of this constraint
605
+ /// system (&self), number of times used, and a mutable
606
+ /// reference of the linear combination to be transformed.
607
+ /// (&ConstraintSystem<F>, usize, &mut LinearCombination<F>)
590
608
///
591
609
/// The transformer function returns the number of new witness variables
592
610
/// needed and a vector of new witness assignments (if not in the setup
@@ -600,7 +618,8 @@ impl<F: Field> ConstraintSystem<F> {
600
618
) -> ( usize , Option < Vec < F > > ) ,
601
619
) {
602
620
// `transformed_lc_map` stores the transformed linear combinations.
603
- let mut transformed_lc_map = BTreeMap :: < _ , LinearCombination < F > > :: new ( ) ;
621
+ let mut transformed_lc_map: BTreeMap < LcIndex , LinearCombination < F > > =
622
+ BTreeMap :: < _ , LinearCombination < F > > :: new ( ) ;
604
623
let mut num_times_used = self . lc_num_times_used ( false ) ;
605
624
606
625
// This loop goes through all the LCs in the map, starting from
@@ -707,8 +726,8 @@ impl<F: Field> ConstraintSystem<F> {
707
726
}
708
727
709
728
/// Get the linear combination corresponding to the given `lc_index`.
710
- /// TODO: This function should return a reference to the linear combination
711
- /// and not clone it.
729
+ /// TODO: This function should return a reference to the linear
730
+ /// combination and not clone it.
712
731
pub fn get_lc ( & self , lc_index : LcIndex ) -> crate :: gr1cs:: Result < LinearCombination < F > > {
713
732
self . lc_map
714
733
. get ( & lc_index)
@@ -735,24 +754,27 @@ impl<F: Field> ConstraintSystem<F> {
735
754
}
736
755
737
756
/// Sets the flag for outlining the instances
738
- pub ( crate ) fn outline_instances ( & mut self ) {
739
- self . outline_instances = true ;
757
+ pub ( crate ) fn set_instance_outliner ( & mut self , instance_outliner : InstanceOutliner < F > ) {
758
+ self . instance_outliner = Some ( instance_outliner ) ;
740
759
}
741
760
742
- /// Returns the flag for outlining the instances, This is by default set to
743
- /// false
761
+ /// Returns the flag for outlining the instances, This is by default set
762
+ /// to false
744
763
pub ( crate ) fn should_outline_instances ( & self ) -> bool {
745
- self . outline_instances
764
+ self . instance_outliner . is_some ( )
746
765
}
747
766
748
767
/// Outlines the instances in the constraint system
749
- /// This function creates a new witness variable for each instance variable
750
- /// and uses these witness variables in the constraints instead of instance
751
- /// variables. This technique is useful for verifier succinctness in some
752
- /// SNARKs like Garuda, Pari and PolyMath
753
- /// After the function call, The instances are only used in the `c` matrix
754
- /// of r1cs
755
- pub ( crate ) fn do_outline_instances ( & mut self ) -> crate :: gr1cs:: Result < ( ) > {
768
+ /// This function creates a new witness variable for each instance
769
+ /// variable and uses these witness variables in the constraints
770
+ /// instead of instance variables. This technique is useful for
771
+ /// verifier succinctness in some SNARKs like Garuda, Pari and
772
+ /// PolyMath After the function call, The instances are only
773
+ /// used in the `c` matrix of r1cs
774
+ pub fn perform_instance_outlining (
775
+ & mut self ,
776
+ outliner : InstanceOutliner < F > ,
777
+ ) -> crate :: gr1cs:: Result < ( ) > {
756
778
// First build a map from instance variables to witness variables
757
779
let mut instance_to_witness_map = BTreeMap :: < Variable , Variable > :: new ( ) ;
758
780
// Initialize the map with the one variable, this is done manually because we
@@ -797,30 +819,7 @@ impl<F: Field> ConstraintSystem<F> {
797
819
self . witness_assignment [ witness_index] = instance_value;
798
820
}
799
821
}
800
-
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
806
- for ( instance, witness) in instance_to_witness_map. iter ( ) {
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
-
821
- self . enforce_constraint ( R1CS_PREDICATE_LABEL , r1cs_constraint) ?;
822
- }
823
-
822
+ ( outliner. func ) ( self , instance_to_witness_map) ?;
824
823
Ok ( ( ) )
825
824
}
826
825
}
0 commit comments