remainder/prover/
helpers.rs1#![allow(clippy::type_complexity)]
2
3use ark_std::{end_timer, start_timer};
4
5use itertools::Itertools;
6
7use serde_json;
8use sha3::Digest;
9use sha3::Sha3_256;
10use shared_types::circuit_hash::CircuitHashType;
11use shared_types::config::global_config::{
12 global_prover_circuit_description_hash_type, global_verifier_circuit_description_hash_type,
13};
14use shared_types::config::{GKRCircuitProverConfig, GKRCircuitVerifierConfig, ProofConfig};
15use shared_types::transcript::poseidon_sponge::PoseidonSponge;
16use shared_types::transcript::{TranscriptReader, TranscriptSponge, TranscriptWriter};
17use shared_types::{
18 perform_function_under_expected_configs, perform_function_under_prover_config,
19 perform_function_under_verifier_config, Field, Halo2FFTFriendlyField,
20};
21use std::fs::File;
22use std::hash::{DefaultHasher, Hash, Hasher};
23use std::io::BufWriter;
24use std::path::Path;
25
26use crate::provable_circuit::ProvableCircuit;
27use crate::verifiable_circuit::VerifiableCircuit;
28
29use super::GKRCircuitDescription;
30
31pub fn write_circuit_description_to_file<F: Field>(
39 circuit_description: &GKRCircuitDescription<F>,
40 circuit_description_path: &Path,
41) {
42 let f = File::create(circuit_description_path).unwrap();
43 let writer = BufWriter::new(f);
44 serde_json::to_writer(writer, circuit_description).unwrap();
45}
46
47pub fn get_circuit_description_hash_as_field_elems<F: Field>(
57 circuit_description: &GKRCircuitDescription<F>,
58 circuit_description_hash_type: CircuitHashType,
59) -> Vec<F> {
60 match circuit_description_hash_type {
61 CircuitHashType::DefaultRustHash => {
62 let mut hasher = DefaultHasher::new();
63 circuit_description.hash(&mut hasher);
64 let hash_value = hasher.finish();
65 vec![F::from(hash_value)]
66 }
67 CircuitHashType::Sha3_256 => {
68 let serialized = serde_json::to_vec(&circuit_description).expect("Failed to serialize");
70 let mut hasher = Sha3_256::new();
71 hasher.update(&serialized);
72 let circuit_description_hash_bytes = hasher.finalize();
73
74 let mut circuit_description_hash_bytes_first_half = [0; 32];
79 let mut circuit_description_hash_bytes_second_half = [0; 32];
80
81 circuit_description_hash_bytes_first_half[..16]
82 .copy_from_slice(&circuit_description_hash_bytes.to_vec()[..16]);
83 circuit_description_hash_bytes_second_half[..16]
84 .copy_from_slice(&circuit_description_hash_bytes.to_vec()[16..]);
85
86 vec![
87 F::from_bytes_le(circuit_description_hash_bytes_first_half.as_ref()),
88 F::from_bytes_le(circuit_description_hash_bytes_second_half.as_ref()),
89 ]
90 }
91 CircuitHashType::Poseidon => {
92 let serialized = serde_json::to_vec(&circuit_description).expect("Failed to serialize");
94 let circuit_field_elem_desc = serialized
97 .chunks(16)
98 .map(|byte_chunk| F::from_bytes_le(byte_chunk))
99 .collect_vec();
100 let mut poseidon_sponge: PoseidonSponge<F> = PoseidonSponge::default();
101 poseidon_sponge.absorb_elements(&circuit_field_elem_desc);
102 vec![poseidon_sponge.squeeze()]
103 }
104 }
105}
106
107pub fn test_circuit_with_config<F: Halo2FFTFriendlyField>(
110 provable_circuit: &ProvableCircuit<F>,
111 expected_prover_config: &GKRCircuitProverConfig,
112 expected_verifier_config: &GKRCircuitVerifierConfig,
113) {
114 perform_function_under_expected_configs!(
115 test_circuit_internal,
116 expected_prover_config,
117 expected_verifier_config,
118 provable_circuit
119 )
120}
121
122pub fn test_circuit_with_runtime_optimized_config<F: Halo2FFTFriendlyField>(
125 provable_circuit: &ProvableCircuit<F>,
126) {
127 let expected_prover_config = GKRCircuitProverConfig::runtime_optimized_default();
128 let expected_verifier_config =
129 GKRCircuitVerifierConfig::new_from_prover_config(&expected_prover_config, false);
130 perform_function_under_expected_configs!(
131 test_circuit_internal,
132 &expected_prover_config,
133 &expected_verifier_config,
134 provable_circuit
135 )
136}
137
138pub fn test_circuit_with_memory_optimized_config<F: Halo2FFTFriendlyField>(
140 provable_circuit: &ProvableCircuit<F>,
141) {
142 let expected_prover_config = GKRCircuitProverConfig::memory_optimized_default();
143 let expected_verifier_config =
144 GKRCircuitVerifierConfig::new_from_prover_config(&expected_prover_config, true);
145 perform_function_under_expected_configs!(
146 test_circuit_internal,
147 &expected_prover_config,
148 &expected_verifier_config,
149 provable_circuit
150 )
151}
152
153fn test_circuit_internal<F: Halo2FFTFriendlyField>(provable_circuit: &ProvableCircuit<F>) {
162 let verifiable_circuit = provable_circuit._gen_verifiable_circuit();
163 let (proof_config, proof_as_transcript_reader) =
164 prove_circuit_internal::<F, PoseidonSponge<F>>(provable_circuit);
165 verify_circuit_internal::<F, PoseidonSponge<F>>(
166 &verifiable_circuit,
167 &proof_config,
168 proof_as_transcript_reader,
169 );
170}
171
172fn prove_circuit_internal<F: Halo2FFTFriendlyField, Tr: TranscriptSponge<F>>(
176 provable_circuit: &ProvableCircuit<F>,
177) -> (ProofConfig, TranscriptReader<F, Tr>) {
178 let mut transcript_writer = TranscriptWriter::<F, Tr>::new("GKR Prover Transcript");
179 let prover_timer = start_timer!(|| "Proof generation");
180
181 match provable_circuit.prove(
182 global_prover_circuit_description_hash_type(),
183 &mut transcript_writer,
184 ) {
185 Ok(proof_config) => {
186 end_timer!(prover_timer);
187 let proof_transcript = transcript_writer.get_transcript();
188 (
189 proof_config,
190 TranscriptReader::<F, Tr>::new(proof_transcript),
191 )
192 }
193 Err(err) => {
194 println!("Proof failed! Error: {err}");
195 panic!();
196 }
197 }
198}
199
200fn verify_circuit_internal<F: Halo2FFTFriendlyField, Tr: TranscriptSponge<F>>(
208 verifiable_circuit: &VerifiableCircuit<F>,
209 proof_config: &ProofConfig,
210 mut proof_as_transcript: TranscriptReader<F, Tr>,
211) {
212 let verifier_timer = start_timer!(|| "Proof verification");
213
214 match verifiable_circuit.verify(
215 global_verifier_circuit_description_hash_type(),
216 &mut proof_as_transcript,
217 proof_config,
218 ) {
219 Ok(_) => {
220 end_timer!(verifier_timer);
221 }
222 Err(err) => {
223 println!("Verify failed! Error: {err}");
224 panic!();
225 }
226 }
227}
228
229pub fn prove_circuit_with_runtime_optimized_config<
232 F: Halo2FFTFriendlyField,
233 Tr: TranscriptSponge<F>,
234>(
235 provable_circuit: &ProvableCircuit<F>,
236) -> (ProofConfig, TranscriptReader<F, Tr>) {
237 let runtime_optimized_config = GKRCircuitProverConfig::runtime_optimized_default();
238 perform_function_under_prover_config!(
239 prove_circuit_internal,
240 &runtime_optimized_config,
241 provable_circuit
242 )
243}
244
245pub fn verify_circuit_with_proof_config<F: Halo2FFTFriendlyField, Tr: TranscriptSponge<F>>(
248 verifiable_circuit: &VerifiableCircuit<F>,
249 proof_config: &ProofConfig,
250 proof_as_transcript: TranscriptReader<F, Tr>,
251) {
252 let verifier_runtime_optimized_config =
253 GKRCircuitVerifierConfig::new_from_proof_config(proof_config, false);
254 perform_function_under_verifier_config!(
255 verify_circuit_internal,
256 &verifier_runtime_optimized_config,
257 verifiable_circuit,
258 proof_config,
259 proof_as_transcript
260 )
261}