diff --git a/src/circuit/boolean.rs b/src/circuit/boolean.rs index 48d243d..c8308ab 100644 --- a/src/circuit/boolean.rs +++ b/src/circuit/boolean.rs @@ -531,78 +531,6 @@ impl Boolean { }, } } - - /// Asserts that this bit representation is "in - /// the field" when interpreted in big endian. - pub fn enforce_in_field( - mut cs: CS, - bits: &[Self] - ) -> Result<(), SynthesisError> - where E: Engine, - CS: ConstraintSystem - { - assert_eq!(bits.len(), F::NUM_BITS as usize); - - let mut a = bits.iter(); - - // b = char() - 1 - let mut b = F::char(); - b.sub_noborrow(&1.into()); - - // Runs of ones in r - let mut last_run = Boolean::constant(true); - let mut current_run = vec![]; - - let mut found_one = false; - let mut run_i = 0; - let mut nand_i = 0; - for b in BitIterator::new(b) { - // Skip over unset bits at the beginning - found_one |= b; - if !found_one { - continue; - } - - let a = a.next().unwrap(); - - if b { - // This is part of a run of ones. - current_run.push(a.clone()); - } else { - if current_run.len() > 0 { - // This is the start of a run of zeros, but we need - // to k-ary AND against `last_run` first. - - current_run.push(last_run.clone()); - last_run = Self::kary_and( - cs.namespace(|| format!("run {}", run_i)), - ¤t_run - )?; - run_i += 1; - current_run.truncate(0); - } - - // If `last_run` is true, `a` must be false, or it would - // not be in the field. - // - // If `last_run` is false, `a` can be true or false. - // - // Ergo, at least one of `last_run` and `a` must be false. - Self::enforce_nand( - cs.namespace(|| format!("nand {}", nand_i)), - &[last_run.clone(), a.clone()] - )?; - nand_i += 1; - } - } - - // We should always end in a "run" of zeros, because - // the characteristic is an odd prime. So, this should - // be empty. - assert_eq!(current_run.len(), 0); - - Ok(()) - } } impl From for Boolean { @@ -1090,73 +1018,6 @@ mod test { } } - #[test] - fn test_enforce_in_field() { - { - let mut cs = TestConstraintSystem::::new(); - - let mut bits = vec![]; - for (i, b) in BitIterator::new(Fr::char()).skip(1).enumerate() { - bits.push(Boolean::from(AllocatedBit::alloc( - cs.namespace(|| format!("bit {}", i)), - Some(b) - ).unwrap())); - } - - Boolean::enforce_in_field::<_, _, Fr>(&mut cs, &bits).unwrap(); - - assert!(!cs.is_satisfied()); - } - - let mut rng = XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - - for _ in 0..1000 { - let r = Fr::rand(&mut rng); - let mut cs = TestConstraintSystem::::new(); - - let mut bits = vec![]; - for (i, b) in BitIterator::new(r.into_repr()).skip(1).enumerate() { - bits.push(Boolean::from(AllocatedBit::alloc( - cs.namespace(|| format!("bit {}", i)), - Some(b) - ).unwrap())); - } - - Boolean::enforce_in_field::<_, _, Fr>(&mut cs, &bits).unwrap(); - - assert!(cs.is_satisfied()); - } - - for _ in 0..1000 { - // Sample a random element not in the field - let r = loop { - let mut a = Fr::rand(&mut rng).into_repr(); - let b = Fr::rand(&mut rng).into_repr(); - - a.add_nocarry(&b); - // we're shaving off the high bit later - a.as_mut()[3] &= 0x7fffffffffffffff; - if Fr::from_repr(a).is_err() { - break a; - } - }; - - let mut cs = TestConstraintSystem::::new(); - - let mut bits = vec![]; - for (i, b) in BitIterator::new(r).skip(1).enumerate() { - bits.push(Boolean::from(AllocatedBit::alloc( - cs.namespace(|| format!("bit {}", i)), - Some(b) - ).unwrap())); - } - - Boolean::enforce_in_field::<_, _, Fr>(&mut cs, &bits).unwrap(); - - assert!(!cs.is_satisfied()); - } - } - #[test] fn test_enforce_nand() { {