add wrap test

This commit is contained in:
M Alghazwi 2025-06-17 12:32:13 +02:00
parent c9224bf48f
commit 7948d6538d
No known key found for this signature in database
GPG Key ID: 646E567CAD7DB607
23 changed files with 286 additions and 425 deletions

0
proof-input/.gitignore vendored Normal file → Executable file
View File

0
proof-input/Cargo.toml Normal file → Executable file
View File

0
proof-input/README.md Normal file → Executable file
View File

0
proof-input/src/data_structs.rs Normal file → Executable file
View File

0
proof-input/src/gen_input.rs Normal file → Executable file
View File

0
proof-input/src/lib.rs Normal file → Executable file
View File

0
proof-input/src/merkle_tree/key_compress.rs Normal file → Executable file
View File

0
proof-input/src/merkle_tree/merkle_circuit.rs Normal file → Executable file
View File

0
proof-input/src/merkle_tree/merkle_safe.rs Normal file → Executable file
View File

0
proof-input/src/merkle_tree/mod.rs Normal file → Executable file
View File

0
proof-input/src/merkle_tree/test.rs Normal file → Executable file
View File

10
proof-input/src/params.rs Normal file → Executable file
View File

@ -1,7 +1,7 @@
// params for generating input for proof circuit
// use plonky2::hash::poseidon::PoseidonHash;
// use plonky2::plonk::config::PoseidonGoldilocksConfig;
use plonky2::hash::poseidon::PoseidonHash;
use plonky2::plonk::config::PoseidonGoldilocksConfig;
use plonky2::plonk::config::GenericConfig;
use std::env;
use anyhow::{Result, Context};
@ -11,9 +11,11 @@ use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2Hash;
// test types
pub const D: usize = 2;
pub type C = Poseidon2GoldilocksConfig;
pub type C = PoseidonGoldilocksConfig;
pub type C2 = Poseidon2GoldilocksConfig;
pub type F = <C as GenericConfig<D>>::F; // this is the goldilocks field
pub type HF = Poseidon2Hash;
pub type HF = PoseidonHash;
pub type HF2 = Poseidon2Hash;
// hardcoded default params for generating proof input
const DEFAULT_MAX_DEPTH: usize = 32; // depth of big tree (slot tree depth, includes block tree depth)

0
proof-input/src/recursion/leaf_test.rs Normal file → Executable file
View File

1
proof-input/src/recursion/mod.rs Normal file → Executable file
View File

@ -8,6 +8,7 @@ use crate::params::{C, D, F, HF, Params};
pub mod tree_test;
pub mod leaf_test;
pub mod node_test;
pub mod wrap_test;
pub fn run_sampling_circ() -> anyhow::Result<(ProofWithPublicInputs<F, C, D>, ProverCircuitData<F, C, D>, VerifierCircuitData<F, C, D>)> {

0
proof-input/src/recursion/node_test.rs Normal file → Executable file
View File

0
proof-input/src/recursion/tree_test.rs Normal file → Executable file
View File

View File

@ -0,0 +1,117 @@
#[cfg(test)]
mod tests {
use plonky2::field::types::Field;
use plonky2::gates::noop::NoopGate;
use plonky2::iop::witness::{PartialWitness, WitnessWrite};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::{CircuitConfig, VerifierCircuitData};
use plonky2::plonk::proof::ProofWithPublicInputs;
use codex_plonky2_circuits::bn254_wrapper::config::PoseidonBN254GoldilocksConfig;
use codex_plonky2_circuits::bn254_wrapper::wrap::{WrapCircuit, WrapInput};
use codex_plonky2_circuits::circuit_helper::Plonky2Circuit;
use codex_plonky2_circuits::recursion::tree::TreeRecursion;
use crate::params::{D, C, F, HF};
use crate::recursion::run_sampling_circ;
type OuterParameters = PoseidonBN254GoldilocksConfig;
fn bn254_wrap(proof: ProofWithPublicInputs<F, C, D>, vd: VerifierCircuitData<F, C, D>) -> anyhow::Result<()>{
// wrap this in the outer circuit.
let wrapper = WrapCircuit::<F,D,C,OuterParameters>::new(vd);
let (targ, data) = wrapper.build_with_standard_config().unwrap();
println!(
"wrapper circuit degree: {}",
data.common.degree_bits()
);
let verifier_data = data.verifier_data();
let prover_data = data.prover_data();
let wrap_input = WrapInput{
inner_proof: proof,
};
let proof = wrapper.prove(&targ, &wrap_input,&prover_data).unwrap();
assert!(verifier_data.verify(proof).is_ok());
Ok(())
}
#[test]
fn test_dummy_wrap() -> anyhow::Result<()>{
let conf = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(conf);
for _ in 0..(4096+10) {
builder.add_gate(NoopGate, vec![]);
}
// Add one virtual public input so that the circuit has minimal structure.
let t = builder.add_virtual_public_input();
// Set up the dummy circuit and wrapper.
let dummy_circuit = builder.build::<C>();
let mut pw = PartialWitness::new();
pw.set_target(t, F::ZERO).expect("faulty assign");
println!(
"dummy circuit degree: {}",
dummy_circuit.common.degree_bits()
);
let dummy_inner_proof = dummy_circuit.prove(pw).unwrap();
assert!(dummy_circuit.verify(dummy_inner_proof.clone()).is_ok());
println!("Verified dummy_circuit");
// wrap this in the outer circuit.
bn254_wrap(dummy_inner_proof, dummy_circuit.verifier_data())?;
Ok(())
}
fn run_tree_recursion<const N: usize, const T: usize>(compress: bool) -> anyhow::Result<()> {
//------------ sampling inner circuit ----------------------
// Circuit that does the sampling - 100 samples
let (inner_proof, inner_prover_data, inner_verifier_data) = run_sampling_circ()?;
let proofs: Vec<ProofWithPublicInputs<F, C, D>> = (0..T).map(|_i| inner_proof.clone()).collect();
// ------------------- tree --------------------
// N-to-1 tree aggregation
let mut tree = TreeRecursion::<F, D,C,HF, N, T>::build_with_standard_config(inner_verifier_data.clone())?;
// aggregate
let root = if !compress {
tree.prove_tree(&proofs)?
} else {
println!("Mode: tree with compression");
tree.prove_tree_and_compress(&proofs)?
};
println!("pub input size = {}", root.public_inputs.len());
println!("pub input = {:?}", root.public_inputs);
println!("proof size = {:?} bytes", root.to_bytes().len());
// sanity check
let vd = if !compress {
tree.get_node_verifier_data()}
else{
tree.get_compression_verifier_data()};
assert!(vd.verify(root.clone()).is_ok());
bn254_wrap(root, vd)?;
Ok(())
}
#[test]
fn test_wrap_tree_recursion() -> anyhow::Result<()> {
// total number of proofs to aggregate
const T:usize = 4;
run_tree_recursion::<2, T>(false)
}
#[test]
fn test_wrap_tree_recursion_with_compression() -> anyhow::Result<()> {
// total number of proofs to aggregate
const T:usize = 4;
run_tree_recursion::<2, T>(true)
}
}

198
proof-input/src/serialization/circuit_input.rs Normal file → Executable file
View File

@ -6,43 +6,12 @@ use anyhow::{anyhow, Error};
use codex_plonky2_circuits::circuits::sample_cells::{Cell, MerklePath, SampleCircuitInput};
use std::fs::File;
use std::io::{BufReader, Write};
use std::path::Path;
use crate::gen_input::gen_testing_circuit_input;
use crate::params::InputParams;
use crate::serialization::file_paths::CIRC_INPUT_JSON;
use crate::serialization::json::ensure_parent_directory_exists;
/// export circuit input to json file
pub fn export_circ_input_to_json<
F: RichField + Extendable<D> + Poseidon2 + Serialize,
const D: usize,
> (circ_input:SampleCircuitInput<F, D>) -> anyhow::Result<()>{
// Convert the circuit input to a serializable format
let serializable_circ_input = SerializableCircuitInput::from_circ_input(&circ_input);
// Serialize to JSON
let json_data = serde_json::to_string_pretty(&serializable_circ_input)?;
// Write to file
ensure_parent_directory_exists(CIRC_INPUT_JSON)?;
let mut file = File::create(CIRC_INPUT_JSON)?;
file.write_all(json_data.as_bytes())?;
Ok(())
}
/// Function to generate circuit input and export to JSON
pub fn generate_and_export_circ_input_to_json<
F: RichField + Extendable<D> + Poseidon2 + Serialize,
const D: usize,
>(params: &InputParams) -> anyhow::Result<()> {
let circ_input = gen_testing_circuit_input::<F,D>(params);
export_circ_input_to_json(circ_input)?;
Ok(())
}
use codex_plonky2_circuits::serialization::ensure_parent_directory_exists;
pub const CIRC_INPUT_JSON: &str = "prover_data/input.json";
// Serializable versions of the circuit input
// naming here is not Rust friendly but only so that its compatible with Nim code.
@ -268,12 +237,169 @@ impl<> SerializableCircuitInput {
}
}
/// export circuit input to json file
pub fn export_circ_input_to_json<
F: RichField + Extendable<D> + Poseidon2 + Serialize,
const D: usize,
P: AsRef<Path>,
>(
circ_input: SampleCircuitInput<F, D>,
base_path: P,
) -> anyhow::Result<()> {
// Convert the circuit input to a serializable format
let serializable_circ_input = SerializableCircuitInput::from_circ_input(&circ_input);
// Serialize to JSON
let json_data = serde_json::to_string_pretty(&serializable_circ_input)?;
let full_path = base_path.as_ref().join(CIRC_INPUT_JSON);
// Write to file
ensure_parent_directory_exists(&full_path)?;
let mut file = File::create(&full_path)?;
file.write_all(json_data.as_bytes())?;
Ok(())
}
/// Function to generate circuit input and export to JSON
pub fn generate_and_export_circ_input_to_json<
F: RichField + Extendable<D> + Poseidon2 + Serialize,
const D: usize,
P: AsRef<Path>,
>(
params: &InputParams,
base_path: P,
) -> anyhow::Result<()> {
let circ_input = gen_testing_circuit_input::<F,D>(params);
export_circ_input_to_json(circ_input, base_path)?;
Ok(())
}
/// reads the json file, converts it to circuit input (SampleCircuitInput) and returns it
pub fn import_circ_input_from_json<F: RichField + Extendable<D> + Poseidon2, const D: usize>() -> anyhow::Result<SampleCircuitInput<F, D>> {
let file = File::open(CIRC_INPUT_JSON)?;
pub fn import_circ_input_from_json<
F: RichField + Extendable<D> + Poseidon2,
const D: usize,
P: AsRef<Path>,
>(
base_path: P,
) -> anyhow::Result<SampleCircuitInput<F, D>> {
let full_path = base_path.as_ref().join(CIRC_INPUT_JSON);
let file = File::open(&full_path)?;
let reader = BufReader::new(file);
let serializable_circ_input: SerializableCircuitInput = serde_json::from_reader(reader)?;
let circ_input = serializable_circ_input.to_circ_input()?;
Ok(circ_input)
}
#[cfg(test)]
mod tests {
use crate::params::{C, D, F, HF, Params};
use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit, SampleCircuitInput};
use plonky2::plonk::circuit_data::{ProverCircuitData, VerifierCircuitData};
use codex_plonky2_circuits::circuit_helper::Plonky2Circuit;
use crate::gen_input::{gen_testing_circuit_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};
// Test to generate the JSON file
#[test]
fn test_export_circ_input_to_json() -> anyhow::Result<()> {
// Create Params
let params = Params::default().input_params;
// Export the circuit input to JSON
generate_and_export_circ_input_to_json::<F, D,_>(&params, "../output/test/")?;
println!("Circuit input exported to input.json");
Ok(())
}
#[test]
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("../output/test/")?;
println!("circuit input imported successfully");
Ok(())
}
// export the circuit input and then import it and checks equality
#[test]
fn test_export_import_circ_input() -> anyhow::Result<()> {
// Create Params instance
let params = Params::default().input_params;
// Export the circuit input to JSON
let original_circ_input = gen_testing_circuit_input(&params);
export_circ_input_to_json(original_circ_input.clone(), "../output/test/")?;
println!("circuit input exported to input.json");
// Import the circuit input from JSON
let imported_circ_input: SampleCircuitInput<F, D> = import_circ_input_from_json("../output/test/")?;
println!("circuit input imported from input.json");
// Compare the original and imported circuit input
assert_eq!(original_circ_input, imported_circ_input, "circuit input are not equal");
// cleanup: Remove the generated JSON file
// fs::remove_file("input.json")?;
println!("Test passed: Original and imported circuit input are equal.");
Ok(())
}
// reads the json input from file and runs the circuit
#[test]
fn test_read_json_and_run_circuit() -> anyhow::Result<()> {
// Create the circuit
let circuit_params = Params::default().circuit_params;
let circ = SampleCircuit::<F, D, HF>::new(circuit_params.clone());
let (targets, data) = circ.build_with_standard_config()?;
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("../output/test/")?;
println!("circuit input imported from input.json");
let proof = circ.prove(&targets, &imported_circ_input, &prover_data)?;
// Verify the proof
assert!(
verifier_data.verify(proof).is_ok(),
"Merkle proof verification failed"
);
Ok(())
}
// reads the json input and verify (non-circuit)
// NOTE: expects that the json input proof uses the default params
#[test]
fn test_read_json_and_verify() -> anyhow::Result<()> {
let params = Params::default().input_params;
// Import the circuit input from JSON
let imported_circ_input: SampleCircuitInput<F, D> = import_circ_input_from_json("../output/test/")?;
println!("circuit input imported from input.json");
// Verify the proof
let ver = verify_circuit_input(imported_circ_input, &params);
assert!(
ver,
"Merkle proof verification failed"
);
Ok(())
}
}

View File

@ -1,12 +0,0 @@
/// File constants with full paths - Prover
pub const CIRC_INPUT_JSON: &str = "prover_data/input.json";
pub const PROVER_CIRC_DATA_JSON: &str = "prover_data/prover_circ_data.bin";
pub const TARGETS_JSON: &str = "prover_data/targets.json";
/// File constants with full paths - Verifier
pub const VERIFIER_CIRC_DATA_JSON: &str = "verifier_data/verifier_circ_data.bin";
pub const PROOF_JSON: &str = "verifier_data/proof.json";
pub const TREE_PROOF_JSON: &str = "verifier_data/tree_proof.json";

View File

@ -1,371 +0,0 @@
use serde::Serialize;
use std::{fs, io};
use std::path::Path;
use anyhow::Context;
use plonky2::hash::hash_types::RichField;
use plonky2::plonk::circuit_data::{CircuitData, ProverCircuitData, VerifierCircuitData};
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
use plonky2_field::extension::Extendable;
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
use plonky2::plonk::proof::ProofWithPublicInputs;
use serde::de::DeserializeOwned;
use plonky2_poseidon2::serialization::{DefaultGateSerializer, DefaultGeneratorSerializer};
use crate::serialization::file_paths::{PROOF_JSON, PROVER_CIRC_DATA_JSON, TARGETS_JSON, TREE_PROOF_JSON, VERIFIER_CIRC_DATA_JSON};
/// Writes the provided bytes to the specified file path using `std::fs::write`.
pub fn write_bytes_to_file<P: AsRef<Path>>(data: Vec<u8>, path: P) -> io::Result<()> {
fs::write(path, data)
}
/// Reads the contents of the specified file and returns them as a vector of bytes using `std::fs::read`.
pub fn read_bytes_from_file<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
fs::read(path)
}
/// Ensures that the parent directory of the given file path exists.
/// If it does not exist, the function creates the entire directory path.
pub fn ensure_parent_directory_exists(path: &str) -> anyhow::Result<()> {
if let Some(parent) = Path::new(path).parent() {
fs::create_dir_all(parent)
.with_context(|| format!("Failed to create directory {:?}", parent))?;
}
Ok(())
}
/// Export the circuit data to disk. This function serializes the prover data,
/// verifier data, and circuit targets, and then writes them to their respective files.
/// The function uses the file paths defined in file_paths.rs
pub fn export_circuit_data<F, C, const D: usize>(
circ_data: CircuitData<F,C,D>,
targets: &impl Serialize,
) -> anyhow::Result<()>
where
F: RichField + Extendable<D> + Poseidon2 + Serialize,
C: GenericConfig<D, F = F> + 'static + Serialize, C:Default,
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
{
// separate the prover and verifier data
let verifier_data: VerifierCircuitData<F, C,D> = circ_data.verifier_data();
let prover_data = circ_data.prover_data();
let gate_serializer = DefaultGateSerializer;
let generator_serializer =DefaultGeneratorSerializer::<C, D>::default();
// Serialize the prover data.
let prover_data_bytes = prover_data
.to_bytes(&gate_serializer, &generator_serializer)
.map_err(|e| anyhow::anyhow!("Failed to serialize prover data: {:?}", e))?;
// Serialize the verifier data.
let verifier_data_bytes = verifier_data
.to_bytes(&gate_serializer)
.map_err(|e| anyhow::anyhow!("Failed to serialize verifier data: {:?}", e))?;
// Serialize the circuit targets using serde_json.
let targets_bytes = serde_json::to_vec(targets)
.context("Failed to serialize circuit targets")?;
// Ensure that the parent directories exist.
ensure_parent_directory_exists(PROVER_CIRC_DATA_JSON)?;
ensure_parent_directory_exists(VERIFIER_CIRC_DATA_JSON)?;
ensure_parent_directory_exists(TARGETS_JSON)?;
// Write all data to the corresponding files.
write_bytes_to_file(prover_data_bytes, PROVER_CIRC_DATA_JSON)
.with_context(|| format!("Failed to write prover data to {}", PROVER_CIRC_DATA_JSON))?;
write_bytes_to_file(verifier_data_bytes, VERIFIER_CIRC_DATA_JSON)
.with_context(|| format!("Failed to write verifier data to {}", VERIFIER_CIRC_DATA_JSON))?;
write_bytes_to_file(targets_bytes, TARGETS_JSON)
.with_context(|| format!("Failed to write circuit targets to {}", TARGETS_JSON))?;
Ok(())
}
/// Import the prover circuit data from disk and deserialize it.
pub fn import_prover_circuit_data<F, C, const D: usize>() -> anyhow::Result<ProverCircuitData<F, C, D>>
where
F: RichField + Extendable<D> + Poseidon2 + Serialize,
C: GenericConfig<D, F = F> + 'static + Serialize, C:Default,
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
{
let gate_serializer = DefaultGateSerializer;
let generator_serializer =DefaultGeneratorSerializer::<C, D>::default();
let bytes = read_bytes_from_file(PROVER_CIRC_DATA_JSON)
.with_context(|| format!("Failed to read prover circuit data from {}", PROVER_CIRC_DATA_JSON))?;
let prover_data = ProverCircuitData::<F,C,D>::from_bytes(&bytes, &gate_serializer, &generator_serializer)
.map_err(|e| anyhow::anyhow!("Failed to deserialize prover data: {:?}", e))?;
Ok(prover_data)
}
/// Import the verifier circuit data from disk and deserialize it.
pub fn import_verifier_circuit_data<F, C, const D: usize>(
) -> anyhow::Result<VerifierCircuitData<F, C, D>>
where
F: RichField + Extendable<D> + Poseidon2 + Serialize,
C: GenericConfig<D, F = F> + Serialize,
{
let gate_serializer = DefaultGateSerializer;
let bytes = read_bytes_from_file(VERIFIER_CIRC_DATA_JSON)
.with_context(|| format!("Failed to read verifier circuit data from {}", VERIFIER_CIRC_DATA_JSON))?;
let verifier_data = VerifierCircuitData::<F,C,D>::from_bytes(bytes, &gate_serializer)
.map_err(|e| anyhow::anyhow!("Failed to deserialize verifier data: {:?}", e))?;
Ok(verifier_data)
}
/// Import the proof with public input from the JSON file.
pub fn import_proof_with_pi<F, C, const D: usize>() -> anyhow::Result<ProofWithPublicInputs<F, C, D>>
where
F: RichField + Extendable<D> + Poseidon2,
C: GenericConfig<D, F = F>,
{
let proof_json = fs::read_to_string(PROOF_JSON)
.with_context(|| format!("Failed to read file {}", PROOF_JSON))?;
let proof = serde_json::from_str(&proof_json)
.context("Failed to deserialize proof with public input")?;
Ok(proof)
}
/// Import the circuit targets from the JSON file.
/// This function is generic over the type `T` that represents the targets and
/// must implement `DeserializeOwned` so that it can be deserialized.
pub fn import_targets<T>() -> anyhow::Result<T>
where
T: DeserializeOwned,
{
let targets_json = fs::read_to_string(TARGETS_JSON)
.with_context(|| format!("Failed to read file {}", TARGETS_JSON))?;
let targets = serde_json::from_str(&targets_json)
.context("Failed to deserialize targets")?;
Ok(targets)
}
/// Function to export tree proof with public input to json file
pub fn export_tree_proof_with_pi<F, C, const D: usize>(
proof_with_pis: &ProofWithPublicInputs<F, C, D>,
) -> anyhow::Result<()>
where
F: RichField + Extendable<D> + Poseidon2 + Serialize,
C: GenericConfig<D, F = F> + Serialize,
{
export_proof_with_pi_to_given_path(proof_with_pis, TREE_PROOF_JSON)
}
/// Function to export proof with public input to json file
pub fn export_proof_with_pi<F, C, const D: usize>(
proof_with_pis: &ProofWithPublicInputs<F, C, D>,
) -> anyhow::Result<()>
where
F: RichField + Extendable<D> + Poseidon2 + Serialize,
C: GenericConfig<D, F = F> + Serialize,
{
export_proof_with_pi_to_given_path(proof_with_pis, PROOF_JSON)
}
/// Function to export proof with public input to json file
/// takes the path
fn export_proof_with_pi_to_given_path<F, C, const D: usize>(
proof_with_pis: &ProofWithPublicInputs<F, C, D>,
path: &str,
) -> anyhow::Result<()>
where
F: RichField + Extendable<D> + Poseidon2 + Serialize,
C: GenericConfig<D, F = F> + Serialize,
{
let proof_serialized= serde_json::to_vec(&proof_with_pis)
.map_err(|e| anyhow::anyhow!("Failed to serialize proof with public input: {:?}", e))?;
fs::write(path , &proof_serialized).expect("Unable to write file");
Ok(())
}
#[cfg(test)]
mod tests {
use crate::params::{C, D, F, HF, Params};
use std::time::Instant;
use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit, SampleCircuitInput};
use plonky2::plonk::circuit_data::{ ProverCircuitData, VerifierCircuitData};
use codex_plonky2_circuits::circuit_helper::Plonky2Circuit;
use codex_plonky2_circuits::circuits::utils::read_bytes_from_file;
use plonky2_poseidon2::serialization::{DefaultGateSerializer, DefaultGeneratorSerializer};
use crate::gen_input::{gen_testing_circuit_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};
use crate::serialization::json::{export_proof_with_pi, write_bytes_to_file};
// Test to generate the JSON file
#[test]
fn test_export_circ_input_to_json() -> anyhow::Result<()> {
// Create Params
let params = Params::default().input_params;
// Export the circuit input to JSON
generate_and_export_circ_input_to_json::<F,D>(&params)?;
println!("Circuit input exported to input.json");
Ok(())
}
#[test]
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()?;
println!("circuit input imported successfully");
Ok(())
}
// export the circuit input and then import it and checks equality
#[test]
fn test_export_import_circ_input() -> anyhow::Result<()> {
// Create Params instance
let params = Params::default().input_params;
// Export the circuit input to JSON
let original_circ_input = gen_testing_circuit_input(&params);
export_circ_input_to_json(original_circ_input.clone())?;
println!("circuit input exported to input.json");
// Import the circuit input from JSON
let imported_circ_input: SampleCircuitInput<F, D> = import_circ_input_from_json()?;
println!("circuit input imported from input.json");
// Compare the original and imported circuit input
assert_eq!(original_circ_input, imported_circ_input, "circuit input are not equal");
// cleanup: Remove the generated JSON file
// fs::remove_file("input.json")?;
println!("Test passed: Original and imported circuit input are equal.");
Ok(())
}
// reads the json input from file and runs the circuit
#[test]
fn test_read_json_and_run_circuit() -> anyhow::Result<()> {
// Create the circuit
let circuit_params = Params::default().circuit_params;
let circ = SampleCircuit::<F,D,HF>::new(circuit_params.clone());
let (targets, data) = circ.build_with_standard_config()?;
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()?;
println!("circuit input imported from input.json");
let proof = circ.prove(&targets, &imported_circ_input, &prover_data)?;
// Verify the proof
assert!(
verifier_data.verify(proof).is_ok(),
"Merkle proof verification failed"
);
Ok(())
}
// reads the json input and verify (non-circuit)
// NOTE: expects that the json input proof uses the default params
#[test]
fn test_read_json_and_verify() -> anyhow::Result<()> {
let params = Params::default().input_params;
// Import the circuit input from JSON
let imported_circ_input: SampleCircuitInput<F, D> = import_circ_input_from_json()?;
println!("circuit input imported from input.json");
// Verify the proof
let ver = verify_circuit_input(imported_circ_input, &params);
assert!(
ver,
"Merkle proof verification failed"
);
Ok(())
}
// test out custom default gate and generator serializers to export/import circuit data
#[test]
fn test_circuit_data_serializer() -> anyhow::Result<()> {
let params = Params::default();
let input_params = params.input_params;
// Create the circuit
let circuit_params = params.circuit_params;
let circ = SampleCircuit::<F,D,HF>::new(circuit_params.clone());
let (targets, data) = circ.build_with_standard_config()?;
println!("circuit size = {:?}", data.common.degree_bits());
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);
let gate_serializer = DefaultGateSerializer;
let generator_serializer =DefaultGeneratorSerializer::<C, D>::default();
let data_bytes = prover_data.to_bytes(&gate_serializer, &generator_serializer).unwrap();
let file_path = "circ_data.bin";
// Write data to the file
write_bytes_to_file(data_bytes.clone(), file_path).unwrap();
println!("Data written to {}", file_path);
// Read data back from the file
let read_data = read_bytes_from_file(file_path).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 = circ.prove(&targets, &imported_circ_input, &prover_data)?;
println!("prove_time = {:?}", start_time.elapsed());
// Verify the proof
assert!(
verifier_data.verify(proof_with_pis).is_ok(),
"Merkle proof verification failed"
);
Ok(())
}
// test proof with public input serialization
#[test]
fn test_proof_with_pi_serializer() -> anyhow::Result<()> {
let params = Params::default();
let input_params = params.input_params;
// Create the circuit
let circuit_params = params.circuit_params;
let circ = SampleCircuit::<F,D,HF>::new(circuit_params.clone());
let (targets, data) = circ.build_with_standard_config()?;
println!("circuit size = {:?}", data.common.degree_bits());
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);
// Prove the circuit with the assigned witness
let start_time = Instant::now();
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());
export_proof_with_pi(&proof_with_pis)?;
println!("Proof size: {} bytes", proof_with_pis.to_bytes().len());
// Verify the proof
assert!(
verifier_data.verify(proof_with_pis).is_ok(),
"Merkle proof verification failed"
);
Ok(())
}
}

2
proof-input/src/serialization/mod.rs Normal file → Executable file
View File

@ -1,3 +1 @@
pub mod circuit_input;
pub mod json;
pub mod file_paths;

0
proof-input/src/sponge.rs Normal file → Executable file
View File

0
proof-input/src/utils.rs Normal file → Executable file
View File