Skip to content

Commit

Permalink
add negative tests of endoscaling
Browse files Browse the repository at this point in the history
also improves a little bit of documentation
  • Loading branch information
marsella authored and b13decker committed Feb 27, 2024
1 parent d4e6859 commit 56706bb
Showing 1 changed file with 68 additions and 1 deletion.
69 changes: 68 additions & 1 deletion halo2_gadgets/src/endoscale/chip/alg_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ impl<F: PrimeFieldBits> Bitstring<F> {
.collect()
}

/// Produces an even-length bool array, the out-of-circuit equivalent to the `Bitstring`.
#[cfg(test)]
fn bitstring(&self) -> Value<Vec<bool>> {
let num_bits = self.num_bits();
Expand All @@ -589,7 +590,7 @@ impl<F: PrimeFieldBits> Bitstring<F> {
.iter()
.by_vals()
.take(num_bits)
// Padding for odd bits
// If there are an odd number of meaningful bits, add padding
.chain((num_bits % 2 == 1).then_some(false))
.collect()
})
Expand Down Expand Up @@ -871,4 +872,70 @@ mod tests {
let proof = MockProver::run(9, &circuit, vec![]).unwrap();
proof.assert_satisfied();
}

#[test]
#[should_panic(expected = "assertion failed: f(value)")]
fn endoscaling_depends_on_base_point() {
let mut rng = thread_rng();

// Use the same challenge
let challenge = pallas::Base::random(&mut rng);

// Use different base points for in- and out-of-circuit
let in_circuit_base_point = pallas::Point::random(&mut rng);
let out_of_circuit_base_point = pallas::Point::random(&mut rng);
assert_ne!(in_circuit_base_point, out_of_circuit_base_point);

// Convert challenge to bits / an endoscalar (out-of-circuit "alg 2")...
let out_of_circuit_endoscalar: pallas::Scalar =
EndoscalarChallenge::<pallas::Affine>::new(&challenge).get_scalar();
// ...then compute the relevant endoscaled value using scalar multiplication
let out_of_circuit_result = out_of_circuit_base_point * out_of_circuit_endoscalar;

// In-circuit, compute the endoscaled result ("alg 1")
let circuit = CompareDecompAndEndoscalingCircuit {
challenge: Value::known(challenge),
base_point: Value::known(in_circuit_base_point.to_affine()),
out_of_circuit_result: Value::known(out_of_circuit_result.to_affine()),
};

let proof = MockProver::run(9, &circuit, vec![]).unwrap();

// Actually, this will panic instead of being handled nicely because we use an assert in the
// circuit to check equality.
assert!(proof.verify().is_err());
}

#[test]
#[should_panic(expected = "assertion failed: f(value)")]
fn endoscaling_depends_on_scalar() {
let mut rng = thread_rng();

// Use different challenges
let in_circuit_challenge = pallas::Base::random(&mut rng);
let out_of_circuit_challenge = pallas::Base::random(&mut rng);
assert_ne!(in_circuit_challenge, out_of_circuit_challenge);

// Use the same base point
let base_point = pallas::Point::random(&mut rng);

// Convert challenge to bits / an endoscalar (out-of-circuit "alg 2")...
let out_of_circuit_endoscalar: pallas::Scalar =
EndoscalarChallenge::<pallas::Affine>::new(&out_of_circuit_challenge).get_scalar();
// ...then compute the relevant endoscaled value using scalar multiplication
let out_of_circuit_result = base_point * out_of_circuit_endoscalar;

// In-circuit, compute the endoscaled result ("alg 1")
let circuit = CompareDecompAndEndoscalingCircuit {
challenge: Value::known(in_circuit_challenge),
base_point: Value::known(base_point.to_affine()),
out_of_circuit_result: Value::known(out_of_circuit_result.to_affine()),
};

let proof = MockProver::run(9, &circuit, vec![]).unwrap();

// Actually, this will panic instead of being handled nicely because we use an assert in the
// circuit to check equality.
assert!(proof.verify().is_err());
}
}

0 comments on commit 56706bb

Please sign in to comment.