Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

helper function: Circuit::test_proof_and_verify() #772

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions halo2_proofs/examples/simple-example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use halo2_proofs::{
plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance, Selector},
poly::Rotation,
};
use pasta_curves::EqAffine;

// ANCHOR: instructions
trait NumericInstructions<F: Field>: Chip<F> {
Expand Down Expand Up @@ -237,7 +238,7 @@ impl<F: Field> NumericInstructions<F> for FieldChip<F> {
/// In this struct we store the private input variables. We use `Option<F>` because
/// they won't have any value during key generation. During proving, if any of these
/// were `None` we would get an error.
#[derive(Default)]
#[derive(Copy, Clone)]
struct MyCircuit<F: Field> {
constant: F,
a: Value<F>,
Expand All @@ -250,7 +251,11 @@ impl<F: Field> Circuit<F> for MyCircuit<F> {
type FloorPlanner = SimpleFloorPlanner;

fn without_witnesses(&self) -> Self {
Self::default()
Self {
constant: self.constant,
a: Value::default(),
b: Value::default(),
}
}

fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
Expand Down Expand Up @@ -308,7 +313,7 @@ fn main() {
// ANCHOR: test-circuit
// The number of rows in our circuit cannot exceed 2^k. Since our example
// circuit is very small, we can pick a very small value here.
let k = 4;
const K: u32 = 4;

// Prepare the private and public inputs to the circuit!
let constant = Fp::from(7);
Expand All @@ -328,12 +333,14 @@ fn main() {
let mut public_inputs = vec![c];

// Given the correct public input, our circuit will verify.
let prover = MockProver::run(k, &circuit, vec![public_inputs.clone()]).unwrap();
let prover = MockProver::run(K, &circuit, vec![public_inputs.clone()]).unwrap();
assert_eq!(prover.verify(), Ok(()));

assert!(circuit.test_prove_and_verify::<K, EqAffine>(&[&public_inputs]));

// If we try some other public input, the proof will fail!
public_inputs[0] += Fp::one();
let prover = MockProver::run(k, &circuit, vec![public_inputs]).unwrap();
let prover = MockProver::run(K, &circuit, vec![public_inputs]).unwrap();
assert!(prover.verify().is_err());
// ANCHOR_END: test-circuit
}
37 changes: 37 additions & 0 deletions halo2_proofs/src/plonk/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
circuit::{Layouter, Region, Value},
poly::Rotation,
};
use pasta_curves::arithmetic::CurveAffine;

mod compress_selectors;

Expand Down Expand Up @@ -482,6 +483,42 @@ pub trait Circuit<F: Field> {
/// the caller will be different depending on the context, and they may or
/// may not expect to have a witness present.
fn synthesize(&self, config: Self::Config, layouter: impl Layouter<F>) -> Result<(), Error>;

/// Test proof creation and verification for this circuit.
fn test_prove_and_verify<const K: u32, C>(self, instance: &[&[C::Scalar]]) -> bool
where
C: CurveAffine<ScalarExt = F>,
C::Scalar: ff::FromUniformBytes<64>,
Self: Sized,
{
use crate::{
plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, SingleVerifier},
poly::commitment::Params,
transcript::{Blake2bRead, Blake2bWrite, Challenge255},
};

let params = Params::<C>::new(K);

let vk = keygen_vk(&params, &self.without_witnesses()).expect("keygen_vk should not fail");
let pk =
keygen_pk(&params, vk, &self.without_witnesses()).expect("keygen_pk should not fail");

let mut transcript = Blake2bWrite::<_, _, Challenge255<C>>::init(vec![]);
create_proof(
&params,
&pk,
&[self],
&[instance],
rand_core::OsRng,
&mut transcript,
)
.expect("proof generation should not fail");
let proof: Vec<u8> = transcript.finalize();

let strategy = SingleVerifier::new(&params);
let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]);
verify_proof(&params, pk.get_vk(), strategy, &[instance], &mut transcript).is_ok()
}
}

/// Low-degree expression representing an identity that must hold over the committed columns.
Expand Down