An End-to-End example
This example builds off the previous example of the simple-example
, where the mock-prover
is replaced with an example of generating real proofs.
Constructing the circuit using private inputs from the User
// 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;
// Args from the command line
let args: Vec<String> = env::args().collect();
// Prepare the private and public inputs to the circuit!
let constant = Fp::from(7);
let a = Fp::from(args[1].parse::<u64>().unwrap());
let b = Fp::from(args[2].parse::<u64>().unwrap());
let c = constant * a.square() * b.square();
// Instantiate the circuit with the private inputs.
let circuit = MyCircuit {
constant,
a: Value::known(a),
b: Value::known(b),
};
Creating a proof
To generate a proof, we need to generate a verification key
(vk
) and a proving key
(ok
) as inputs for generating the proof using create_proof
.
let params: Params<EqAffine> = halo2_proofs::poly::commitment::Params::new(k);
// Generate verification key.
println!("Generating Verification Key");
let vk = keygen_vk(¶ms, &circuit).unwrap();
// Generate proving key.
println!("Generating Proving Key from Verification Key");
let pk = keygen_pk(¶ms, vk, &circuit).unwrap();
let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]);
println!("Generating Proof!");
create_proof(
¶ms,
&pk,
&[circuit],
&[&[&[c]]],
&mut OsRng,
&mut transcript,
)
.expect("Failed to create proof!");
Write proof to a file
This is an example of how to write the proof to a file.
let proof_path = "./proof";
let proof = transcript.finalize();
File::create(Path::new(proof_path))
.expect("Failed to create proof file")
.write_all(&proof[..])
.expect("Failed to write proof");
println!("Proof written to: {}", proof_path);
Verifying the proof
let mut transcript_proof = Blake2bRead::init(&proof[..]);
// Verify the proof
println!("Verifying Proof");
let verified_proof_result = verify_proof(
¶ms,
pk.get_vk(),
SingleVerifier::new(¶ms),
&[&[&[c]]],
&mut transcript_proof,
);
// Print "OK(())" if the proof is valid or an error message otherwise.
if verified_proof_result.is_ok() {
println!("Proof verified!");
} else {
println!(
"Proof verification failed! {}",
verified_proof_result.err().unwrap()
);
}
Running the example
To generate the proof and verify the proof in this example run: cargo run --example e2e-example 2 3
where 2
and 3
are the values of the a
and b
variables in the proof.
Full Main
Function
fn main() {
use halo2_proofs::pasta::Fp;
// 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;
// Args from the command line
let args: Vec<String> = env::args().collect();
// Prepare the private and public inputs to the circuit!
let constant = Fp::from(7);
let a = Fp::from(args[1].parse::<u64>().unwrap());
let b = Fp::from(args[2].parse::<u64>().unwrap());
let c = constant * a.square() * b.square();
// Instantiate the circuit with the private inputs.
let circuit = MyCircuit {
constant,
a: Value::known(a),
b: Value::known(b),
};
let params: Params<EqAffine> = halo2_proofs::poly::commitment::Params::new(k);
// Generate verification key.
println!("Generating Verification Key");
let vk = keygen_vk(¶ms, &circuit).unwrap();
// Generate proving key.
println!("Generating Proving Key from Verification Key");
let pk = keygen_pk(¶ms, vk, &circuit).unwrap();
let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]);
println!("Generating Proof!");
create_proof(
¶ms,
&pk,
&[circuit],
&[&[&[c]]],
&mut OsRng,
&mut transcript,
)
.expect("Failed to create proof!");
let proof_path = "./proof";
let proof = transcript.finalize();
File::create(Path::new(proof_path))
.expect("Failed to create proof file")
.write_all(&proof[..])
.expect("Failed to write proof");
println!("Proof written to: {}", proof_path);
let mut transcript_proof = Blake2bRead::init(&proof[..]);
// Verify the proof
println!("Verifying Proof");
let verified_proof_result = verify_proof(
¶ms,
pk.get_vk(),
SingleVerifier::new(¶ms),
&[&[&[c]]],
&mut transcript_proof,
);
// Print "OK(())" if the proof is valid or an error message otherwise.
if verified_proof_result.is_ok() {
println!("Proof verified!");
} else {
println!(
"Proof verification failed! {}",
verified_proof_result.err().unwrap()
);
}
}