mirror of
https://github.com/logos-storage/proof-aggregation.git
synced 2026-01-02 13:53:13 +00:00
improve serialization or circuit data, targets, and proofs.
This commit is contained in:
parent
6a119c3d4c
commit
937610d8c4
@ -7,6 +7,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::config::{AlgebraicHasher, Hasher};
|
||||
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
|
||||
use codex_plonky2_circuits::circuits::merkle_circuit::{MerkleProofTarget, MerkleTreeCircuit, MerkleTreeTargets};
|
||||
use codex_plonky2_circuits::circuits::serialization::SerializableHashOutTarget;
|
||||
use codex_plonky2_circuits::circuits::utils::{assign_bool_targets, assign_hash_out_targets};
|
||||
use codex_plonky2_circuits::error::CircuitError;
|
||||
use crate::utils::usize_to_bits_le;
|
||||
@ -51,7 +52,7 @@ pub fn build_circuit<
|
||||
|
||||
// Merkle path (sibling hashes from leaf to root)
|
||||
let merkle_path = MerkleProofTarget {
|
||||
path: (0..depth).map(|_| builder.add_virtual_hash()).collect(),
|
||||
path: (0..depth).map(|_| builder.add_virtual_hash()).map(SerializableHashOutTarget::from).collect(),
|
||||
};
|
||||
|
||||
// create MerkleTreeTargets struct
|
||||
@ -107,10 +108,10 @@ pub fn assign_witness<
|
||||
// assign the Merkle path (sibling hashes) to the targets
|
||||
for i in 0..targets.merkle_path.path.len() {
|
||||
if i>=witnesses.merkle_path.len() { // pad with zeros
|
||||
assign_hash_out_targets(pw, &targets.merkle_path.path[i], &HashOut::from_vec([F::ZERO; NUM_HASH_OUT_ELTS].to_vec()))?;
|
||||
assign_hash_out_targets(pw, &targets.merkle_path.path[i].0, &HashOut::from_vec([F::ZERO; NUM_HASH_OUT_ELTS].to_vec()))?;
|
||||
continue
|
||||
}
|
||||
assign_hash_out_targets(pw, &targets.merkle_path.path[i], &witnesses.merkle_path[i])?;
|
||||
assign_hash_out_targets(pw, &targets.merkle_path.path[i].0, &witnesses.merkle_path[i])?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -8,12 +8,14 @@ use std::fs::File;
|
||||
use std::io::{BufReader, Write};
|
||||
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>, filename: &str) -> anyhow::Result<()>{
|
||||
> (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);
|
||||
|
||||
@ -21,7 +23,8 @@ pub fn export_circ_input_to_json<
|
||||
let json_data = serde_json::to_string_pretty(&serializable_circ_input)?;
|
||||
|
||||
// Write to file
|
||||
let mut file = File::create(filename)?;
|
||||
ensure_parent_directory_exists(CIRC_INPUT_JSON)?;
|
||||
let mut file = File::create(CIRC_INPUT_JSON)?;
|
||||
file.write_all(json_data.as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
@ -31,11 +34,11 @@ pub fn export_circ_input_to_json<
|
||||
pub fn generate_and_export_circ_input_to_json<
|
||||
F: RichField + Extendable<D> + Poseidon2 + Serialize,
|
||||
const D: usize,
|
||||
>(params: &InputParams, filename: &str) -> anyhow::Result<()> {
|
||||
>(params: &InputParams) -> anyhow::Result<()> {
|
||||
|
||||
let circ_input = gen_testing_circuit_input::<F,D>(params);
|
||||
|
||||
export_circ_input_to_json(circ_input, filename)?;
|
||||
export_circ_input_to_json(circ_input)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -266,10 +269,8 @@ impl<> SerializableCircuitInput {
|
||||
}
|
||||
|
||||
/// 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>(
|
||||
filename: &str,
|
||||
) -> anyhow::Result<SampleCircuitInput<F, D>> {
|
||||
let file = File::open(filename)?;
|
||||
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)?;
|
||||
let reader = BufReader::new(file);
|
||||
let serializable_circ_input: SerializableCircuitInput = serde_json::from_reader(reader)?;
|
||||
|
||||
|
||||
11
proof-input/src/serialization/file_paths.rs
Normal file
11
proof-input/src/serialization/file_paths.rs
Normal file
@ -0,0 +1,11 @@
|
||||
/// 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.json";
|
||||
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.json";
|
||||
pub const PROOF_JSON: &str = "verifier_data/proof.json";
|
||||
|
||||
|
||||
|
||||
@ -1,35 +1,18 @@
|
||||
use serde::Serialize;
|
||||
use std::fs::File;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{fs, io};
|
||||
use std::io::BufWriter;
|
||||
use std::path::Path;
|
||||
use anyhow::Context;
|
||||
use crate::gen_input::gen_testing_circuit_input;
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::plonk::config::GenericConfig;
|
||||
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 codex_plonky2_circuits::circuits::sample_cells::SampleCircuitInput;
|
||||
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: &ProofWithPublicInputs<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(())
|
||||
}
|
||||
use serde::de::DeserializeOwned;
|
||||
use plonky2_poseidon2::serialization::{DefaultGateSerializer, DefaultGeneratorSerializer};
|
||||
use crate::serialization::file_paths::{PROOF_JSON, PROVER_CIRC_DATA_JSON, TARGETS_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<()> {
|
||||
@ -41,6 +24,138 @@ 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 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,
|
||||
{
|
||||
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(PROOF_JSON , &proof_serialized).expect("Unable to write file");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -59,7 +174,7 @@ mod tests {
|
||||
// Create Params
|
||||
let params = Params::default().input_params;
|
||||
// Export the circuit input to JSON
|
||||
generate_and_export_circ_input_to_json::<F,D>(¶ms, "input.json")?;
|
||||
generate_and_export_circ_input_to_json::<F,D>(¶ms)?;
|
||||
|
||||
println!("Circuit input exported to input.json");
|
||||
|
||||
@ -70,7 +185,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()?;
|
||||
println!("circuit input imported successfully");
|
||||
|
||||
Ok(())
|
||||
@ -84,11 +199,11 @@ mod tests {
|
||||
|
||||
// Export the circuit input to JSON
|
||||
let original_circ_input = gen_testing_circuit_input(¶ms);
|
||||
export_circ_input_to_json(original_circ_input.clone(), "input.json")?;
|
||||
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("input.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
|
||||
@ -116,7 +231,7 @@ mod tests {
|
||||
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")?;
|
||||
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)?;
|
||||
@ -137,7 +252,7 @@ mod tests {
|
||||
let params = Params::default().input_params;
|
||||
|
||||
// Import the circuit input from JSON
|
||||
let imported_circ_input: SampleCircuitInput<F, D> = import_circ_input_from_json("input.json")?;
|
||||
let imported_circ_input: SampleCircuitInput<F, D> = import_circ_input_from_json()?;
|
||||
println!("circuit input imported from input.json");
|
||||
|
||||
// Verify the proof
|
||||
@ -219,8 +334,7 @@ mod tests {
|
||||
println!("prove_time = {:?}", start_time.elapsed());
|
||||
println!("Proof size: {} bytes", proof_with_pis.to_bytes().len());
|
||||
|
||||
let filename = "proof_with_pi.json";
|
||||
export_proof_with_pi_to_json(&proof_with_pis,filename)?;
|
||||
export_proof_with_pi(&proof_with_pis)?;
|
||||
println!("Proof size: {} bytes", proof_with_pis.to_bytes().len());
|
||||
|
||||
// Verify the proof
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
pub mod circuit_input;
|
||||
pub mod json;
|
||||
pub mod file_paths;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user