@@ -32,10 +32,29 @@ impl<F: Field> AllocatedBit<F> {
3232        self . variable 
3333    } 
3434
35+     /// Allocate a witness variable without a booleanity check. 
36+ fn  new_witness_without_booleanity_check < T :  Borrow < bool > > ( 
37+         cs :  ConstraintSystemRef < F > , 
38+         f :  impl  FnOnce ( )  -> Result < T ,  SynthesisError > , 
39+     )  -> Result < Self ,  SynthesisError >  { 
40+         let  mut  value = None ; 
41+         let  variable = cs. new_witness_variable ( || { 
42+             value = Some ( * f ( ) ?. borrow ( ) ) ; 
43+             value. get ( ) . map ( bool_to_field) 
44+         } ) ?; 
45+         Ok ( Self  { 
46+             value, 
47+             variable, 
48+             cs, 
49+         } ) 
50+     } 
51+ 
3552    /// Performs an XOR operation over the two operands, returning 
3653/// an `AllocatedBit`. 
3754pub  fn  xor ( & self ,  b :  & Self )  -> Result < Self ,  SynthesisError >  { 
38-         let  result = Self :: new_witness ( self . cs . clone ( ) ,  || Ok ( self . value ( ) ? ^ b. value ( ) ?) ) ?; 
55+         let  result = Self :: new_witness_without_booleanity_check ( self . cs . clone ( ) ,  || { 
56+             Ok ( self . value ( ) ? ^ b. value ( ) ?) 
57+         } ) ?; 
3958
4059        // Constrain (a + a) * (b) = (a + b - c) 
4160        // Given that a and b are boolean constrained, if they 
@@ -64,7 +83,9 @@ impl<F: Field> AllocatedBit<F> {
6483    /// Performs an AND operation over the two operands, returning 
6584/// an `AllocatedBit`. 
6685pub  fn  and ( & self ,  b :  & Self )  -> Result < Self ,  SynthesisError >  { 
67-         let  result = Self :: new_witness ( self . cs . clone ( ) ,  || Ok ( self . value ( ) ? &  b. value ( ) ?) ) ?; 
86+         let  result = Self :: new_witness_without_booleanity_check ( self . cs . clone ( ) ,  || { 
87+             Ok ( self . value ( ) ? &  b. value ( ) ?) 
88+         } ) ?; 
6889
6990        // Constrain (a) * (b) = (c), ensuring c is 1 iff 
7091        // a AND b are both 1. 
@@ -80,7 +101,9 @@ impl<F: Field> AllocatedBit<F> {
80101    /// Performs an OR operation over the two operands, returning 
81102/// an `AllocatedBit`. 
82103pub  fn  or ( & self ,  b :  & Self )  -> Result < Self ,  SynthesisError >  { 
83-         let  result = Self :: new_witness ( self . cs . clone ( ) ,  || Ok ( self . value ( ) ? | b. value ( ) ?) ) ?; 
104+         let  result = Self :: new_witness_without_booleanity_check ( self . cs . clone ( ) ,  || { 
105+             Ok ( self . value ( ) ? | b. value ( ) ?) 
106+         } ) ?; 
84107
85108        // Constrain (1 - a) * (1 - b) = (c), ensuring c is 1 iff 
86109        // a and b are both false, and otherwise c is 0. 
@@ -95,7 +118,9 @@ impl<F: Field> AllocatedBit<F> {
95118
96119    /// Calculates `a AND (NOT b)`. 
97120pub  fn  and_not ( & self ,  b :  & Self )  -> Result < Self ,  SynthesisError >  { 
98-         let  result = Self :: new_witness ( self . cs . clone ( ) ,  || Ok ( self . value ( ) ? &  !b. value ( ) ?) ) ?; 
121+         let  result = Self :: new_witness_without_booleanity_check ( self . cs . clone ( ) ,  || { 
122+             Ok ( self . value ( ) ? &  !b. value ( ) ?) 
123+         } ) ?; 
99124
100125        // Constrain (a) * (1 - b) = (c), ensuring c is 1 iff 
101126        // a is true and b is false, and otherwise c is 0. 
@@ -110,7 +135,9 @@ impl<F: Field> AllocatedBit<F> {
110135
111136    /// Calculates `(NOT a) AND (NOT b)`. 
112137pub  fn  nor ( & self ,  b :  & Self )  -> Result < Self ,  SynthesisError >  { 
113-         let  result = Self :: new_witness ( self . cs . clone ( ) ,  || Ok ( !( self . value ( ) ? | b. value ( ) ?) ) ) ?; 
138+         let  result = Self :: new_witness_without_booleanity_check ( self . cs . clone ( ) ,  || { 
139+             Ok ( !( self . value ( ) ? | b. value ( ) ?) ) 
140+         } ) ?; 
114141
115142        // Constrain (1 - a) * (1 - b) = (c), ensuring c is 1 iff 
116143        // a and b are both false, and otherwise c is 0. 
@@ -596,10 +623,12 @@ impl<F: Field> CondSelectGadget<F> for Boolean<F> {
596623                ( x,  & Constant ( true ) )  => cond. not ( ) . or ( x) , 
597624                ( a,  b)  => { 
598625                    let  cs = cond. cs ( ) . unwrap ( ) ; 
599-                     let  result = Boolean :: new_witness ( cs. clone ( ) ,  || { 
600-                         let  cond = cond. value ( ) ?; 
601-                         Ok ( if  cond {  a. value ( ) ? }  else  {  b. value ( ) ? } ) 
602-                     } ) ?; 
626+                     let  result:  Boolean < F >  =
627+                         AllocatedBit :: new_witness_without_booleanity_check ( cs. clone ( ) ,  || { 
628+                             let  cond = cond. value ( ) ?; 
629+                             Ok ( if  cond {  a. value ( ) ? }  else  {  b. value ( ) ? } ) 
630+                         } ) ?
631+                         . into ( ) ; 
603632                    // a = self; b = other; c = cond; 
604633                    // 
605634                    // r = c * a + (1  - c) * b 
@@ -1014,7 +1043,7 @@ mod test {
10141043    } 
10151044
10161045    #[ test]  
1017-     fn  test_boolean_cond_select ( )  -> Result < ( ) ,  r1cs_core :: SynthesisError >  { 
1046+     fn  test_boolean_cond_select ( )  -> Result < ( ) ,  SynthesisError >  { 
10181047        for  condition in  VARIANTS . iter ( ) . cloned ( )  { 
10191048            for  first_operand in  VARIANTS . iter ( ) . cloned ( )  { 
10201049                for  second_operand in  VARIANTS . iter ( ) . cloned ( )  { 
0 commit comments