267 lines
9.9 KiB
Rust
Raw Normal View History

2024-11-08 12:23:55 +01:00
use serde::{Deserialize, Serialize};
use std::fs::File;
2024-11-26 09:53:47 +01:00
use std::{fs, io};
2025-01-10 11:30:04 +01:00
use std::io::{BufWriter, Write};
2024-11-26 09:53:47 +01:00
use std::path::Path;
2025-01-10 11:30:04 +01:00
use crate::gen_input::gen_testing_circuit_input;
use plonky2::hash::hash_types::RichField;
2024-11-08 12:23:55 +01:00
use plonky2::plonk::config::{GenericConfig, Hasher};
use plonky2_field::extension::Extendable;
use plonky2_field::types::Field;
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
2025-01-10 11:30:04 +01:00
use codex_plonky2_circuits::circuits::sample_cells::SampleCircuitInput;
2024-11-26 11:35:47 +01:00
use plonky2::plonk::proof::CompressedProofWithPublicInputs;
use serde_json::to_writer_pretty;
2024-11-12 12:03:56 +01:00
use crate::params::TestParams;
2024-11-08 12:23:55 +01:00
2024-11-26 11:35:47 +01:00
// 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>,
path: &str,
) -> io::Result<()>
where
F: RichField + Extendable<D> + Poseidon2 + Serialize,
C: GenericConfig<D, F = F> + Serialize,
{
// Create or overwrite the file at the given path
let file = File::create(path)?;
let writer = BufWriter::new(file);
// Serialize the struct to JSON and write it to the file
to_writer_pretty(writer, instance)?;
Ok(())
}
2024-11-26 09:53:47 +01:00
/// 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)
}
2024-11-08 12:23:55 +01:00
#[cfg(test)]
mod tests {
use super::*;
2024-11-12 12:03:56 +01:00
use crate::params::{C, D, F};
2024-11-08 12:23:55 +01:00
use std::time::Instant;
2024-11-12 12:03:56 +01:00
use codex_plonky2_circuits::circuits::params::CircuitParams;
2024-11-08 12:23:55 +01:00
use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit;
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
2024-11-26 09:53:47 +01:00
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData};
use plonky2_poseidon2::serialization::{DefaultGateSerializer, DefaultGeneratorSerializer};
2024-11-12 12:03:56 +01:00
use crate::gen_input::verify_circuit_input;
2025-01-10 11:30:04 +01:00
use crate::serialization::circuit_input::{export_circ_input_to_json, generate_and_export_circ_input_to_json, import_circ_input_from_json};
2024-11-08 12:23:55 +01:00
// Test to generate the JSON file
#[test]
2025-01-10 11:30:04 +01:00
fn test_export_circ_input_to_json() -> anyhow::Result<()> {
2024-11-08 12:23:55 +01:00
// Create Params
2024-11-12 12:03:56 +01:00
let params = TestParams::default();
// Export the circuit input to JSON
generate_and_export_circ_input_to_json::<F,D>(&params, "input.json")?;
2024-11-08 12:23:55 +01:00
2024-11-12 12:03:56 +01:00
println!("Circuit input exported to input.json");
2024-11-08 12:23:55 +01:00
Ok(())
}
#[test]
2024-11-12 12:03:56 +01:00
fn test_import_circ_input_from_json() -> anyhow::Result<()> {
// Import the circuit input from the JSON file
2024-11-08 12:23:55 +01:00
// NOTE: MAKE SURE THE FILE EXISTS
2024-11-12 12:03:56 +01:00
let circ_input: SampleCircuitInput<F, D> = import_circ_input_from_json("input.json")?;
println!("circuit input imported successfully");
2024-11-08 12:23:55 +01:00
Ok(())
}
2024-11-12 12:03:56 +01:00
// export the circuit input and then import it and checks equality
2024-11-08 12:23:55 +01:00
#[test]
2024-11-12 12:03:56 +01:00
fn test_export_import_circ_input() -> anyhow::Result<()> {
2024-11-08 12:23:55 +01:00
// Create Params instance
2024-11-12 12:03:56 +01:00
let params = TestParams::default();
2024-11-08 12:23:55 +01:00
2024-11-12 12:03:56 +01:00
// Export the circuit input to JSON
let original_circ_input = gen_testing_circuit_input(&params);
export_circ_input_to_json(original_circ_input.clone(), "input.json")?;
println!("circuit input exported to input.json");
2024-11-08 12:23:55 +01:00
2024-11-12 12:03:56 +01:00
// 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");
2024-11-08 12:23:55 +01:00
2024-11-12 12:03:56 +01:00
// Compare the original and imported circuit input
assert_eq!(original_circ_input, imported_circ_input, "circuit input are not equal");
2024-11-08 12:23:55 +01:00
// cleanup: Remove the generated JSON file
2024-11-14 12:26:37 +01:00
// fs::remove_file("input.json")?;
2024-11-08 12:23:55 +01:00
2024-11-12 12:03:56 +01:00
println!("Test passed: Original and imported circuit input are equal.");
2024-11-08 12:23:55 +01:00
Ok(())
}
2024-11-12 12:03:56 +01:00
// reads the json input from file and runs the circuit
2024-11-08 12:23:55 +01:00
#[test]
2024-11-12 12:03:56 +01:00
fn test_read_json_and_run_circuit() -> anyhow::Result<()> {
let params = TestParams::default();
2024-11-08 12:23:55 +01:00
// Create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
2024-11-26 09:53:47 +01:00
let circuit_params = CircuitParams::default();
2024-11-08 12:23:55 +01:00
let circ = SampleCircuit::new(circuit_params.clone());
2025-01-10 11:30:04 +01:00
let mut targets = circ.sample_slot_circuit_with_public_input(&mut builder)?;
2024-11-08 12:23:55 +01:00
// Create a PartialWitness and assign
let mut pw = PartialWitness::new();
2024-11-12 12:03:56 +01:00
// 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");
2024-11-08 12:23:55 +01:00
2025-01-10 11:30:04 +01:00
circ.sample_slot_assign_witness(&mut pw, &targets, &imported_circ_input)?;
2024-11-08 12:23:55 +01:00
// 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());
// Verify the proof
let verifier_data = data.verifier_data();
assert!(
verifier_data.verify(proof_with_pis).is_ok(),
"Merkle proof verification failed"
);
Ok(())
}
// reads the json input and verify (non-circuit)
2024-11-12 12:03:56 +01:00
// NOTE: expects that the json input proof uses the default params
2024-11-08 12:23:55 +01:00
#[test]
2025-01-10 11:30:04 +01:00
fn test_read_json_and_verify() -> anyhow::Result<()> {
2024-11-12 12:03:56 +01:00
let params = TestParams::default();
2024-11-08 12:23:55 +01:00
2024-11-12 12:03:56 +01:00
// 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");
2024-11-08 12:23:55 +01:00
// Verify the proof
2024-11-12 12:03:56 +01:00
let ver = verify_circuit_input(imported_circ_input, &params);
2024-11-08 12:23:55 +01:00
assert!(
ver,
"Merkle proof verification failed"
);
Ok(())
}
2024-11-26 09:53:47 +01:00
// test out custom default gate and generator serializers to export/import circuit data
#[test]
fn test_circuit_data_serializer() -> anyhow::Result<()> {
let params = TestParams::default();
// Create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let circuit_params = CircuitParams::default();
let circ = SampleCircuit::new(circuit_params.clone());
2025-01-10 11:30:04 +01:00
let mut targets = circ.sample_slot_circuit_with_public_input(&mut builder)?;
2024-11-26 09:53:47 +01:00
// Create a PartialWitness and assign
let mut pw = PartialWitness::new();
// gen circ input
let imported_circ_input: SampleCircuitInput<F, D> = gen_testing_circuit_input::<F,D>(&params);
2025-01-10 11:30:04 +01:00
circ.sample_slot_assign_witness(&mut pw, &targets, &imported_circ_input)?;
2024-11-26 09:53:47 +01:00
// 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 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 data = CircuitData::<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)?;
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"
);
Ok(())
}
2024-11-26 11:35:47 +01:00
// test proof with public input serialization
#[test]
fn test_proof_with_pi_serializer() -> anyhow::Result<()> {
let params = TestParams::default();
// Create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let circuit_params = CircuitParams::default();
let circ = SampleCircuit::new(circuit_params.clone());
2025-01-10 11:30:04 +01:00
let mut targets = circ.sample_slot_circuit_with_public_input(&mut builder)?;
2024-11-26 11:35:47 +01:00
// Create a PartialWitness and assign
let mut pw = PartialWitness::new();
// gen circ input
let imported_circ_input: SampleCircuitInput<F, D> = gen_testing_circuit_input::<F,D>(&params);
2025-01-10 11:30:04 +01:00
circ.sample_slot_assign_witness(&mut pw, &targets, &imported_circ_input)?;
2024-11-26 11:35:47 +01:00
// 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());
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());
// Verify the proof
let verifier_data = data.verifier_data();
assert!(
verifier_data.verify(proof_with_pis).is_ok(),
"Merkle proof verification failed"
);
Ok(())
}
2024-11-08 12:23:55 +01:00
}