clean up, and refactor to use the circuit helper.

This commit is contained in:
M Alghazwi 2025-04-08 12:02:59 +02:00
parent 76374f084b
commit 1daf2dc0ea
No known key found for this signature in database
GPG Key ID: 646E567CAD7DB607
6 changed files with 80 additions and 125 deletions

View File

@ -11,7 +11,6 @@ use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData};
use plonky2::plonk::proof::ProofWithPublicInputs;
use codex_plonky2_circuits::circuits::params::CircuitParams;
use crate::data_structs::DatasetTree;
use crate::sponge::hash_bytes_no_padding;
use crate::params::{C, D, F, HF};
@ -220,12 +219,8 @@ pub fn get_m_circ_input<const M: usize>(params: InputParams) -> [SampleCircuitIn
mod tests {
use std::time::Instant;
use super::*;
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use codex_plonky2_circuits::circuits::params::CircuitParams;
use codex_plonky2_circuits::circuit_helper::Plonky2Circuit;
use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit;
// use crate::params::{C, D, F};
// Test sample cells (non-circuit)
#[test]
@ -241,37 +236,26 @@ mod tests {
// get input
let mut params = Params::default();
let mut input_params = params.input_params;
input_params.n_samples = 10;
let circ_input = gen_testing_circuit_input::<F,D>(&input_params);
// Create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let mut circuit_params = params.circuit_params;
input_params.n_samples = 10;
circuit_params.n_samples = 10;
let circ_input = gen_testing_circuit_input::<F,D>(&input_params);
// build the circuit
let circ = SampleCircuit::<F,D,HF>::new(circuit_params.clone());
let mut targets = circ.sample_slot_circuit_with_public_input(&mut builder)?;
// Create a PartialWitness and assign
let mut pw = PartialWitness::new();
// assign a witness
circ.sample_slot_assign_witness(&mut pw, &targets, &circ_input)?;
// Build the circuit
let data = builder.build::<C>();
let (targets, data) = circ.build_with_standard_config()?;
println!("circuit size = {:?}", data.common.degree_bits());
// Prove the circuit with the assigned witness
// separate the prover and verifier
let verifier_data = data.verifier_data();
let prover_data = data.prover_data();
// Prove the circuit using the circuit input
let start_time = Instant::now();
let proof_with_pis = data.prove(pw)?;
let proof_with_pis: ProofWithPublicInputs<F, C, D> = circ.prove(&targets, &circ_input, &prover_data)?;
println!("prove_time = {:?}", start_time.elapsed());
// Verify the proof
let verifier_data = data.verifier_data();
assert!(
verifier_data.verify(proof_with_pis).is_ok(),
"Merkle proof verification failed"

View File

@ -203,7 +203,7 @@ mod tests {
// create a PartialWitness and assign
let mut pw = PartialWitness::new();
assign_witness(&mut pw, &mut targets, circuit_input)?;
pw.set_hash_target(expected_root, tree.root().unwrap());
pw.set_hash_target(expected_root, tree.root().unwrap())?;
// build the circuit
let data = builder.build::<C>();
@ -290,7 +290,7 @@ mod tests {
};
assign_witness(&mut pw, &mut targets, circuit_input)?;
pw.set_hash_target(expected_root_target, expected_root);
pw.set_hash_target(expected_root_target, expected_root)?;
let proof_with_pis = data.prove(pw)?;

View File

@ -193,7 +193,7 @@ impl<
let mut i = 0;
for p in &path {
let bottom = if(i==0){
let bottom = if i==0 {
KEY_BOTTOM_LAYER
}else{
KEY_NONE

View File

@ -2,24 +2,22 @@
#[cfg(test)]
mod tests {
use plonky2::iop::witness::{PartialWitness};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::{CircuitConfig};
use plonky2::plonk::config::{ GenericConfig};
use plonky2::plonk::proof::{ProofWithPublicInputs};
use codex_plonky2_circuits::circuit_helper::Plonky2Circuit;
use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit;
use crate::params::{F, D, C, HF};
use crate::gen_input::gen_testing_circuit_input;
use crate::params::Params;
use codex_plonky2_circuits::recursion::uniform::{tree::TreeRecursion};
use codex_plonky2_circuits::recursion::uniform::pi_verifier::PublicInputVerificationCircuit;
use codex_plonky2_circuits::recursion::uniform::pi_verifier::{PublicInputVerificationCircuit, PublicInputVerificationInput};
use codex_plonky2_circuits::recursion::uniform::tree::get_hash_of_verifier_data;
#[test]
fn test_uniform_recursion() -> anyhow::Result<()> {
let config = CircuitConfig::standard_recursion_config();
let mut sampling_builder = CircuitBuilder::<F, D>::new(config);
// total number of proofs to aggregate
const T:usize = 4;
//------------ sampling inner circuit ----------------------
// Circuit that does the sampling - 100 samples
@ -28,27 +26,29 @@ mod tests {
params.circuit_params.n_samples = 100;
let one_circ_input = gen_testing_circuit_input::<F,D>(&params.input_params);
let samp_circ = SampleCircuit::<F,D,HF>::new(params.circuit_params);
let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut sampling_builder)?;
// get generate a sampling proof
let mut pw = PartialWitness::<F>::new();
samp_circ.sample_slot_assign_witness(&mut pw,&inner_tar,&one_circ_input)?;
let inner_data = sampling_builder.build::<C>();
println!("sampling circuit degree bits = {:?}", inner_data.common.degree_bits());
let inner_proof = inner_data.prove(pw)?;
let (inner_tar, inner_data) = samp_circ.build_with_standard_config()?;
let num_of_proofs = 4;
let proofs: Vec<ProofWithPublicInputs<F, C, D>> = (0..num_of_proofs).map(|i| inner_proof.clone()).collect();
let inner_verifier_data = inner_data.verifier_data();
let inner_prover_data = inner_data.prover_data();
println!("sampling circuit degree bits = {:?}", inner_verifier_data.common.degree_bits());
let inner_proof = samp_circ.prove(&inner_tar, &one_circ_input, &inner_prover_data)?;
let proofs: Vec<ProofWithPublicInputs<F, C, D>> = (0..T).map(|i| inner_proof.clone()).collect();
// ------------------- tree --------------------
// 2-to-1 tree aggregation
const N: usize = 1;
const M: usize = 2;
let mut tree = TreeRecursion::<F,D,C,HF, N, M>::build(inner_data.common.clone(), inner_data.verifier_only.clone())?;
let mut tree = TreeRecursion::<F,D,C,HF, N, M>::build_with_standard_config(inner_verifier_data.common.clone(), inner_verifier_data.verifier_only.clone())?;
// aggregate - no compression
let root = tree.prove_tree(&proofs)?;
println!("pub input size = {}", root.public_inputs.len());
println!("proof size = {:?} bytes", root.to_bytes().len());
// aggregate with compression
let root_compressed = tree.prove_tree_and_compress(&proofs)?;
println!("pub input size (compressed) = {}", root_compressed.public_inputs.len());
println!("proof size compressed = {:?} bytes", root_compressed.to_bytes().len());
@ -72,8 +72,10 @@ mod tests {
#[test]
fn test_pi_verifier() -> anyhow::Result<()> {
let config = CircuitConfig::standard_recursion_config();
let mut sampling_builder = CircuitBuilder::<F, D>::new(config);
// total number of proofs to aggregate
const T:usize = 4;
// 9 field elems as public inputs in the sampling circuit
const K:usize = 9;
//------------ sampling inner circuit ----------------------
// Circuit that does the sampling - 100 samples
@ -82,25 +84,22 @@ mod tests {
params.circuit_params.n_samples = 100;
let one_circ_input = gen_testing_circuit_input::<F,D>(&params.input_params);
let samp_circ = SampleCircuit::<F,D,HF>::new(params.circuit_params);
let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut sampling_builder)?;
// get generate a sampling proof
let mut pw = PartialWitness::<F>::new();
samp_circ.sample_slot_assign_witness(&mut pw,&inner_tar,&one_circ_input)?;
let inner_data = sampling_builder.build::<C>();
println!("sampling circuit degree bits = {:?}", inner_data.common.degree_bits());
let inner_proof = inner_data.prove(pw)?;
let (inner_tar, inner_data) = samp_circ.build_with_standard_config()?;
let inner_verifier_data = inner_data.verifier_data();
let inner_prover_data = inner_data.prover_data();
// get generate a sampling proof
println!("sampling circuit degree bits = {:?}", inner_verifier_data.common.degree_bits());
let inner_proof = samp_circ.prove(&inner_tar, &one_circ_input, &inner_prover_data)?;
// 9 field elems as public inputs in the sampling circuit
const K:usize = 9;
// change the following as needed.
const T: usize = 4;
let proofs: Vec<ProofWithPublicInputs<F, C, D>> = (0..T).map(|i| inner_proof.clone()).collect();
// ------------------- tree --------------------
const N: usize = 1;
const M: usize = 2;
let mut tree = TreeRecursion::<F,D,C,HF, N, M>::build(inner_data.common.clone(), inner_data.verifier_only.clone())?;
let mut tree = TreeRecursion::<F,D,C,HF, N, M>::build_with_standard_config(inner_verifier_data.common.clone(), inner_verifier_data.verifier_only.clone())?;
let root = tree.prove_tree(&proofs)?;
println!("pub input size = {}", root.public_inputs.len());
@ -117,18 +116,19 @@ mod tests {
let pi_verifier_circ = PublicInputVerificationCircuit::<F, D, C, HF, N, M, T, K>::new(tree.get_node_common_data(), tree.get_node_verifier_data().verifier_only);
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let pi_tarq = pi_verifier_circ.build(&mut builder)?;
let pi_circ_data = builder.build::<C>();
let (pi_tarq, pi_circ_data) = pi_verifier_circ.build_with_standard_config()?;
println!("PI verifier circuit degree bits = {:?}", pi_circ_data.common.degree_bits());
let mut pw = PartialWitness::<F>::new();
let pi_circ_input = PublicInputVerificationInput{
inner_proof:root,
inner_pub_inputs_vals: inner_pi.clone()
};
pi_verifier_circ.assign_targets(&mut pw, &pi_tarq, root, inner_pi.clone())?;
let pi_circ_verifier_data = pi_circ_data.verifier_data();
let pi_circ_prover_data = pi_circ_data.prover_data();
let proof =pi_verifier_circ.prove(&pi_tarq, &pi_circ_input, &pi_circ_prover_data)?;
let proof = pi_circ_data.prove(pw)?;
println!("pub input size = {}", proof.public_inputs.len());
println!("proof size = {:?} bytes", proof.to_bytes().len());
@ -150,7 +150,7 @@ mod tests {
assert!(
pi_circ_data.verify(proof).is_ok(),
pi_circ_verifier_data.verify(proof).is_ok(),
"pi-verifier proof verification failed"
);

View File

@ -10,12 +10,12 @@ use plonky2_field::extension::Extendable;
use plonky2_field::types::Field;
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
use codex_plonky2_circuits::circuits::sample_cells::SampleCircuitInput;
use plonky2::plonk::proof::CompressedProofWithPublicInputs;
use plonky2::plonk::proof::ProofWithPublicInputs;
use serde_json::to_writer_pretty;
// Function to export proof with public input to json file
fn export_proof_with_pi_to_json<F, C, const D: usize>(
instance: &CompressedProofWithPublicInputs<F, C, D>,
instance: &ProofWithPublicInputs<F, C, D>,
path: &str,
) -> io::Result<()>
where
@ -50,7 +50,8 @@ mod tests {
use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit;
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData};
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, ProverCircuitData, VerifierCircuitData};
use codex_plonky2_circuits::circuit_helper::Plonky2Circuit;
use plonky2_poseidon2::serialization::{DefaultGateSerializer, DefaultGeneratorSerializer};
use crate::gen_input::verify_circuit_input;
use crate::serialization::circuit_input::{export_circ_input_to_json, generate_and_export_circ_input_to_json, import_circ_input_from_json};
@ -72,7 +73,7 @@ mod tests {
fn test_import_circ_input_from_json() -> anyhow::Result<()> {
// Import the circuit input from the JSON file
// NOTE: MAKE SURE THE FILE EXISTS
let circ_input: SampleCircuitInput<F, D> = import_circ_input_from_json("input.json")?;
let _circ_input: SampleCircuitInput<F, D> = import_circ_input_from_json("input.json")?;
println!("circuit input imported successfully");
Ok(())
@ -108,36 +109,24 @@ mod tests {
#[test]
fn test_read_json_and_run_circuit() -> anyhow::Result<()> {
// Create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let circuit_params = Params::default().circuit_params;
let circ = SampleCircuit::<F,D,HF>::new(circuit_params.clone());
let mut targets = circ.sample_slot_circuit_with_public_input(&mut builder)?;
let (targets, data) = circ.build_with_standard_config()?;
// Create a PartialWitness and assign
let mut pw = PartialWitness::new();
let verifier_data: VerifierCircuitData<F, C, D> = data.verifier_data();
let prover_data: ProverCircuitData<F, C, D> = data.prover_data();
println!("circuit size = {:?}", verifier_data.common.degree_bits());
// Import the circuit input from JSON
let imported_circ_input: SampleCircuitInput<F, D> = import_circ_input_from_json("input.json")?;
println!("circuit input imported from input.json");
circ.sample_slot_assign_witness(&mut pw, &targets, &imported_circ_input)?;
// Build the circuit
let data = builder.build::<C>();
println!("circuit size = {:?}", data.common.degree_bits());
// Prove the circuit with the assigned witness
let start_time = Instant::now();
let proof_with_pis = data.prove(pw)?;
println!("prove_time = {:?}", start_time.elapsed());
let proof = circ.prove(&targets, &imported_circ_input, &prover_data)?;
// Verify the proof
let verifier_data = data.verifier_data();
assert!(
verifier_data.verify(proof_with_pis).is_ok(),
verifier_data.verify(proof).is_ok(),
"Merkle proof verification failed"
);
@ -171,27 +160,20 @@ mod tests {
let input_params = params.input_params;
// Create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let circuit_params = params.circuit_params;
let circ = SampleCircuit::<F,D,HF>::new(circuit_params.clone());
let mut targets = circ.sample_slot_circuit_with_public_input(&mut builder)?;
let (targets, data) = circ.build_with_standard_config()?;
println!("circuit size = {:?}", data.common.degree_bits());
// Create a PartialWitness and assign
let mut pw = PartialWitness::new();
let verifier_data: VerifierCircuitData<F, C, D> = data.verifier_data();
let prover_data: ProverCircuitData<F, C, D> = data.prover_data();
// gen circ input
let imported_circ_input: SampleCircuitInput<F, D> = gen_testing_circuit_input::<F,D>(&input_params);
circ.sample_slot_assign_witness(&mut pw, &targets, &imported_circ_input)?;
// Build the circuit
let data = builder.build::<C>();
println!("circuit size = {:?}", data.common.degree_bits());
let gate_serializer = DefaultGateSerializer;
let generator_serializer =DefaultGeneratorSerializer::<C, D>::default();
let data_bytes = data.to_bytes(&gate_serializer, &generator_serializer).unwrap();
let data_bytes = prover_data.to_bytes(&gate_serializer, &generator_serializer).unwrap();
let file_path = "circ_data.bin";
// Write data to the file
@ -200,15 +182,14 @@ mod tests {
// Read data back from the file
let read_data = read_bytes_from_file(file_path).unwrap();
let data = CircuitData::<F,C,D>::from_bytes(&read_data, &gate_serializer, &generator_serializer).unwrap();
let prover_data = ProverCircuitData::<F,C,D>::from_bytes(&read_data, &gate_serializer, &generator_serializer).unwrap();
// Prove the circuit with the assigned witness
let start_time = Instant::now();
let proof_with_pis = data.prove(pw)?;
let proof_with_pis = circ.prove(&targets, &imported_circ_input, &prover_data)?;
println!("prove_time = {:?}", start_time.elapsed());
// Verify the proof
let verifier_data = data.verifier_data();
assert!(
verifier_data.verify(proof_with_pis).is_ok(),
"Merkle proof verification failed"
@ -224,37 +205,28 @@ mod tests {
let input_params = params.input_params;
// Create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let circuit_params = params.circuit_params;
let circ = SampleCircuit::<F,D,HF>::new(circuit_params.clone());
let mut targets = circ.sample_slot_circuit_with_public_input(&mut builder)?;
let (targets, data) = circ.build_with_standard_config()?;
println!("circuit size = {:?}", data.common.degree_bits());
// Create a PartialWitness and assign
let mut pw = PartialWitness::new();
let verifier_data: VerifierCircuitData<F, C, D> = data.verifier_data();
let prover_data: ProverCircuitData<F, C, D> = data.prover_data();
// gen circ input
let imported_circ_input: SampleCircuitInput<F, D> = gen_testing_circuit_input::<F,D>(&input_params);
circ.sample_slot_assign_witness(&mut pw, &targets, &imported_circ_input)?;
// Build the circuit
let data = builder.build::<C>();
println!("circuit size = {:?}", data.common.degree_bits());
// Prove the circuit with the assigned witness
let start_time = Instant::now();
let proof_with_pis = data.prove(pw)?;
let proof_with_pis = circ.prove(&targets, &imported_circ_input, &prover_data)?;
println!("prove_time = {:?}", start_time.elapsed());
println!("Proof size: {} bytes", proof_with_pis.to_bytes().len());
let compressed_proof_with_pi = data.compress(proof_with_pis.clone())?;
let filename = "proof_with_pi.json";
export_proof_with_pi_to_json(&compressed_proof_with_pi,filename)?;
println!("Proof size: {} bytes", compressed_proof_with_pi.to_bytes().len());
export_proof_with_pi_to_json(&proof_with_pis,filename)?;
println!("Proof size: {} bytes", proof_with_pis.to_bytes().len());
// Verify the proof
let verifier_data = data.verifier_data();
assert!(
verifier_data.verify(proof_with_pis).is_ok(),
"Merkle proof verification failed"

View File

@ -35,8 +35,8 @@ pub fn hash_n_to_m_with_padding<
let domsep_value = F::from_canonical_u64(rate as u64 + 256 * 12 + 65536 * 63);
perm.set_elt(domsep_value, 8);
let N = inputs.len();
let num_chunks = (N + rate) / rate; // Calculate number of chunks with 10* padding
let input_n = inputs.len();
let num_chunks = (input_n + rate) / rate; // Calculate number of chunks with 10* padding
let mut input_iter = inputs.iter();
// Process all chunks except the last one
@ -59,7 +59,7 @@ pub fn hash_n_to_m_with_padding<
}
// Process the last chunk with 10* padding
let rem = num_chunks * rate - N; // Number of padding elements (0 < rem <= rate)
let rem = num_chunks * rate - input_n; // Number of padding elements (0 < rem <= rate)
let ofs = rate - rem; // Offset where padding starts
let mut last_chunk = Vec::with_capacity(rate);
@ -123,7 +123,6 @@ pub fn hash_bytes_to_m_no_padding<
let rate = P::RATE;
let width = P::WIDTH; // rate + capacity
let zero = F::ZERO;
let one = F::ONE;
let mut perm = P::new(core::iter::repeat(zero).take(width));
// Set the domain separator at index 8