refactor tests to follow changes in circuit impl

This commit is contained in:
M Alghazwi 2025-01-14 11:13:51 +01:00
parent c8a8ec0f5e
commit 209eda8240
No known key found for this signature in database
GPG Key ID: 646E567CAD7DB607
13 changed files with 347 additions and 314 deletions

View File

@ -6,7 +6,7 @@ use codex_plonky2_circuits::circuits::sample_cells::Cell;
use plonky2_field::types::Sample;
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
use crate::merkle_tree::merkle_safe::{MerkleProof, MerkleTree};
use crate::params::{InputParams,Params, HF};
use crate::params::{InputParams, HF};
use crate::sponge::hash_bytes_no_padding;
use crate::utils::{bits_le_padded_to_usize, calculate_cell_index_bits, usize_to_bits_le};

View File

@ -3,7 +3,6 @@ use plonky2::plonk::config::{GenericConfig, Hasher};
use plonky2_field::extension::Extendable;
use plonky2_field::types::Field;
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
use codex_plonky2_circuits::circuits::params::CircuitParams;
use crate::params::{Params,InputParams};
use crate::utils::{bits_le_padded_to_usize, calculate_cell_index_bits, ceiling_log2, usize_to_bits_le};
use crate::merkle_tree::merkle_safe::MerkleProof;

View File

@ -2,7 +2,7 @@
pub mod gen_input;
pub mod params;
pub mod utils;
// pub mod recursion;
pub mod recursion;
pub mod sponge;
pub mod merkle_tree;
pub mod data_structs;

View File

@ -38,9 +38,9 @@ pub fn build_circuit<
const D: usize,
H: AlgebraicHasher<F>,
>(
builder: &mut CircuitBuilder::<F, D>,
builder: &mut CircuitBuilder<F, D>,
depth: usize,
) -> Result<(MerkleTreeTargets, HashOutTarget)> {
) -> (MerkleTreeTargets, HashOutTarget) {
// Create virtual targets
let leaf = builder.add_virtual_hash();
@ -69,10 +69,10 @@ pub fn build_circuit<
};
// Add Merkle proof verification constraints to the circuit
let reconstructed_root_target = MerkleTreeCircuit::<F,D,H>::reconstruct_merkle_root_circuit_with_mask(builder, &mut targets, depth)?;
let reconstructed_root_target = MerkleTreeCircuit::<F,D,H>::reconstruct_merkle_root_circuit_with_mask(builder, &mut targets, depth).unwrap();
// Return MerkleTreeTargets
Ok((targets, reconstructed_root_target))
(targets, reconstructed_root_target)
}
/// assign the witness values in the circuit targets
@ -176,7 +176,7 @@ mod tests {
// create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let (mut targets, reconstructed_root_target) = build_circuit::<F,D,H>(&mut builder, max_depth)?;
let (mut targets, reconstructed_root_target) = build_circuit::<F,D,H>(&mut builder, max_depth);
// expected Merkle root
let expected_root = builder.add_virtual_hash();
@ -252,7 +252,7 @@ mod tests {
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let (mut targets, reconstructed_root_target) = build_circuit::<F,D,H>(&mut builder, max_depth)?;
let (mut targets, reconstructed_root_target) = build_circuit::<F,D,H>(&mut builder, max_depth);
// expected Merkle root
let expected_root_target = builder.add_virtual_hash();
@ -276,7 +276,7 @@ mod tests {
let mut pw = PartialWitness::new();
let path_bits = usize_to_bits_le(leaf_index, max_depth);
let last_index = (nleaves - 1) as usize;
let last_index = nleaves - 1;
let last_bits = usize_to_bits_le(last_index, max_depth);
let mask_bits = usize_to_bits_le(last_index, max_depth+1);

View File

@ -5,8 +5,6 @@ use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use std::env;
use anyhow::{Result, Context};
use codex_plonky2_circuits::circuits::params::CircuitParams;
use plonky2_field::goldilocks_field::GoldilocksField;
use plonky2_poseidon2::config::Poseidon2GoldilocksConfig;
// test types
pub const D: usize = 2;

View File

@ -10,34 +10,28 @@ mod tests {
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::plonk::config::GenericConfig;
use codex_plonky2_circuits::params::{F, D, C, Plonky2Proof};
use crate::params::{F, D, C, HF};
use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion;
use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash};
use crate::gen_input::gen_testing_circuit_input;
use crate::params::TestParams;
use crate::params::Params;
use codex_plonky2_circuits::recursion::cyclic::CyclicCircuit;
/// Uses cyclic recursion to sample the dataset
#[test]
fn test_cyclic_recursion() -> Result<()> {
// const D: usize = 2;
// type C = PoseidonGoldilocksConfig;
// type F = <C as GenericConfig<D>>::F;
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let one = builder.one();
let inner_sampling_circuit = SamplingRecursion::default();
let mut params = TestParams::default();
params.n_samples = 10;
let circ_input = gen_testing_circuit_input::<F,D>(&params);
let mut cyclic_circ = CyclicCircuit::new(inner_sampling_circuit);
let mut params = Params::default();
let inner_sampling_circuit = SamplingRecursion::<F,D,HF,C>::new(params.circuit_params);
let circ_input = gen_testing_circuit_input::<F,D>(&params.input_params);
let s = Instant::now();
cyclic_circ.build_circuit()?;
let mut cyclic_circ = CyclicCircuit::<F,D,_,C>::build_circuit::<HF>(inner_sampling_circuit)?;
println!("build = {:?}", s.elapsed());
let s = Instant::now();
let proof = cyclic_circ.prove_one_layer(&circ_input)?;
@ -51,12 +45,12 @@ mod tests {
);
println!("verify = {:?}", s.elapsed());
// check public input hash is correct
let mut hash_input = vec![];
hash_input.push(circ_input.slot_index);
hash_input.extend_from_slice(&circ_input.dataset_root.elements);
hash_input.extend_from_slice(&circ_input.entropy.elements);
// let hash_res = PoseidonHash::hash_no_pad(&hash_input);
let hash_res = hash_n_to_hash_no_pad::<F, PoseidonPermutation<F>>(&hash_input);
let zero_hash = HashOut::<F>::ZERO;
let mut hash_input2 = vec![];
@ -65,7 +59,11 @@ mod tests {
let hash_res = hash_n_to_hash_no_pad::<F, PoseidonPermutation<F>>(&hash_input2);
println!("hash input = {:?}", hash_res.elements);
assert_eq!(
proof.public_inputs[0..4].to_vec(),
hash_res.elements.to_vec(),
"public input hash incorrect"
);
Ok(())
}
@ -73,30 +71,24 @@ mod tests {
/// Uses cyclic recursion to sample the dataset n times
#[test]
fn test_cyclic_recursion_n_layers() -> Result<()> {
// const D: usize = 2;
// type C = PoseidonGoldilocksConfig;
// type F = <C as GenericConfig<D>>::F;
const N : usize = 2;
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let one = builder.one();
let inner_sampling_circuit = SamplingRecursion::default();
let mut params = TestParams::default();
params.n_samples = 10;
let mut params = Params::default();
let inner_sampling_circuit = SamplingRecursion::<F,D,HF,C>::new(params.circuit_params);
let mut circ_inputs = vec![];
for i in 0..N {
circ_inputs.push(gen_testing_circuit_input::<F, D>(&params));
circ_inputs.push(gen_testing_circuit_input::<F, D>(&params.input_params));
}
let mut cyclic_circ = CyclicCircuit::new(inner_sampling_circuit);
let s = Instant::now();
cyclic_circ.build_circuit()?;
let mut cyclic_circ = CyclicCircuit::<F,D,_,C>::build_circuit::<HF>(inner_sampling_circuit)?;
println!("build = {:?}", s.elapsed());
let s = Instant::now();
let proof = cyclic_circ.prove_n_layers(N,circ_inputs)?;
let proof = cyclic_circ.prove_n_layers(circ_inputs)?;
println!("prove = {:?}", s.elapsed());
println!("num of pi = {}", proof.public_inputs.len());
println!("pub input: {:?}", proof.public_inputs);

View File

@ -1,4 +1,5 @@
pub mod simple_recursion;
pub mod simple_tree;
pub mod cyclic_recursion;
pub mod tree_recursion1;
pub mod tree_recursion2;
pub mod tree1;
pub mod tree2;

View File

@ -1,149 +1,43 @@
// tests for simple recursion approaches
use std::time::Instant;
use plonky2::hash::hash_types::HashOut;
use plonky2::hash::hash_types::{HashOut, NUM_HASH_OUT_ELTS};
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData};
use plonky2::plonk::config::AlgebraicHasher;
use plonky2_field::types::Field;
use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion;
use codex_plonky2_circuits::recursion::simple::simple_recursion::{aggregate_sampling_proofs, SimpleRecursionCircuit, SimpleRecursionInput};
use codex_plonky2_circuits::recursion::simple::simple_tree_recursion::aggregate_sampling_proofs_tree;
use plonky2_poseidon2::serialization::{DefaultGateSerializer, DefaultGeneratorSerializer};
use codex_plonky2_circuits::recursion::simple::simple_recursion::{SimpleRecursionCircuit, SimpleRecursionInput};
use codex_plonky2_circuits::recursion::simple::simple_recursion_hashed_pi::{SimpleRecursionCircuitHashedPI, SimpleRecursionInputHashedPI};
use crate::gen_input::{build_circuit, prove_circuit};
use crate::json::write_bytes_to_file;
use crate::params::{C, D, F};
use crate::params::{C, D, F, HF, Params};
// Test simple recursion
// test the simple recursion approach
#[test]
fn test_simple_recursion() -> anyhow::Result<()> {
// number of samples in each proof
let n_samples = 10;
// number of inner proofs:
let n_inner = 4;
let mut data: Option<CircuitData<F, C, D>> = None;
// get proofs
let mut proofs_with_pi = vec![];
for i in 0..n_inner{
// build the circuit
let (data_i, pw) = build_circuit(n_samples, i)?;
// prove
proofs_with_pi.push(prove_circuit(&data_i, &pw)?);
data = Some(data_i);
}
println!("num of public inputs inner proof = {}", proofs_with_pi[0].public_inputs.len());
// Create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
// Create a PartialWitness
let mut pw_agg = PartialWitness::new();
// aggregate proofs
aggregate_sampling_proofs(&proofs_with_pi, &data.unwrap().verifier_data(), &mut builder, &mut pw_agg)?;
let data_agg = builder.build::<C>();
// Prove the circuit with the assigned witness
let start_time = Instant::now();
let proof_with_pis_agg = data_agg.prove(pw_agg)?;
println!("prove_time = {:?}", start_time.elapsed());
println!("num of public inputs = {}", proof_with_pis_agg.public_inputs.len());
// Verify the proof
let verifier_data = data_agg.verifier_data();
assert!(
verifier_data.verify(proof_with_pis_agg).is_ok(),
"Merkle proof verification failed"
);
Ok(())
}
// Test simple tree recursion
#[test]
fn test_simple_tree_recursion() -> anyhow::Result<()> {
// number of samples in each proof
let n_samples = 10;
// number of inner proofs:
let n_inner = 4;
let mut data: Option<CircuitData<F, C, D>> = None;
// get proofs
let mut proofs_with_pi = vec![];
for i in 0..n_inner{
// build the circuit
let (data_i, pw) = build_circuit(n_samples, i)?;
proofs_with_pi.push(prove_circuit(&data_i, &pw)?);
data = Some(data_i);
}
let data = data.unwrap();
println!("inner circuit size = {:?}", data.common.degree_bits());
// serialization
// let gate_serializer = DefaultGateSerializer;
// let generator_serializer =DefaultGeneratorSerializer::<C, D>::default();
// let data_bytes = data.to_bytes(&gate_serializer, &generator_serializer).unwrap();
// println!("inner proof circuit data size = {} bytes", data_bytes.len());
// let file_path = "inner_circ_data.bin";
// // Write data to the file
// write_bytes_to_file(data_bytes, file_path).unwrap();
// println!("Data written to {}", file_path);
let start_time = Instant::now();
let (proof, vd_agg) = aggregate_sampling_proofs_tree(&proofs_with_pi, data)?;
println!("prove_time = {:?}", start_time.elapsed());
println!("num of public inputs = {}", proof.public_inputs.len());
println!("agg pub input = {:?}", proof.public_inputs);
println!("outer circuit size = {:?}", vd_agg.common.degree_bits());
// serialization
// // let gate_serializer = DefaultGateSerializer;
// // let generator_serializer =DefaultGeneratorSerializer::<C, D>::default();
// let outer_data_bytes = vd_agg.to_bytes(&gate_serializer, &generator_serializer).unwrap();
// println!("outer proof circuit data size = {} bytes", outer_data_bytes.len());
// let file_path = "outer_circ_data.bin";
// // Write data to the file
// write_bytes_to_file(outer_data_bytes, file_path).unwrap();
// println!("Data written to {}", file_path);
// Verify the proof
let verifier_data = vd_agg.verifier_data();
assert!(
verifier_data.verify(proof).is_ok(),
"Merkle proof verification failed"
);
Ok(())
}
// test another approach of the simple recursion
#[test]
pub fn test_simple_recursion_approach2()-> anyhow::Result<()>{
pub fn test_simple_recursion()-> anyhow::Result<()>{
// number of samples in each proof
let n_samples = 5;
// number of inner proofs:
const n_inner: usize = 4;
const N_INNER: usize = 4;
let mut data: Option<CircuitData<F, C, D>> = None;
// get proofs
let mut proofs_with_pi = vec![];
for i in 0..n_inner{
for i in 0..N_INNER {
// build the circuit
let (data_i, pw) = build_circuit(n_samples, i)?;
proofs_with_pi.push(prove_circuit(&data_i, &pw)?);
data = Some(data_i);
}
let data = data.unwrap();
println!("inner circuit size = {:?}", data.common.degree_bits());
// careful here, the sampling recursion is the default so proofs should be for circuit
// with default params
let sampling_inner_circ = SamplingRecursion::default();
let rec_circuit = SimpleRecursionCircuit::<_,n_inner>::new(sampling_inner_circ);
let sampling_inner_circ = SamplingRecursion::<F,D,HF,C>::new(Params::default().circuit_params);
let rec_circuit = SimpleRecursionCircuit::<F,D, _, N_INNER, C>::new(sampling_inner_circ);
// Create the circuit
let config = CircuitConfig::standard_recursion_config();
@ -156,7 +50,7 @@ pub fn test_simple_recursion_approach2()-> anyhow::Result<()>{
let start = Instant::now();
let agg_data = builder.build::<C>();
println!("build time = {:?}", start.elapsed());
println!("circuit size = {:?}", data.common.degree_bits());
println!("agg circuit size = {:?}", agg_data.common.degree_bits());
let mut default_entropy = HashOut::ZERO;
default_entropy.elements[0] = F::from_canonical_u64(1234567);
@ -172,13 +66,97 @@ pub fn test_simple_recursion_approach2()-> anyhow::Result<()>{
let start = Instant::now();
let proof = agg_data.prove(pw)?;
println!("prove time = {:?}", start.elapsed());
println!("public input count = {:?}", proof.public_inputs.len());
// Verify the proof
let verifier_data = agg_data.verifier_data();
assert!(
verifier_data.verify(proof).is_ok(),
"Merkle proof verification failed"
"proof verification failed"
);
Ok(())
}
// test the simple recursion approach with hashed public input
#[test]
pub fn test_simple_recursion_with_hashed_pi()-> anyhow::Result<()>{
// number of samples in each proof
let n_samples = 5;
// number of inner proofs:
const N_INNER: usize = 4;
let mut data: Option<CircuitData<F, C, D>> = None;
// get proofs
let mut proofs_with_pi = vec![];
for i in 0..N_INNER {
// build the circuit
let (data_i, pw) = build_circuit(n_samples, i)?;
proofs_with_pi.push(prove_circuit(&data_i, &pw)?);
data = Some(data_i);
}
let data = data.unwrap();
println!("inner circuit size = {:?}", data.common.degree_bits());
// careful here, the sampling recursion is the default so proofs should be for circuit
// with default params
let sampling_inner_circ = SamplingRecursion::<F,D,HF,C>::new(Params::default().circuit_params);
let rec_circuit = SimpleRecursionCircuitHashedPI::<F,D, _, N_INNER, C>::new(sampling_inner_circ);
// Create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
// Create a PartialWitness
let mut pw = PartialWitness::new();
let targets = rec_circuit.build_circuit::<HF>(&mut builder)?;
let start = Instant::now();
let agg_data = builder.build::<C>();
println!("build time = {:?}", start.elapsed());
println!("agg circuit size = {:?}", agg_data.common.degree_bits());
let mut default_entropy = HashOut::ZERO;
default_entropy.elements[0] = F::from_canonical_u64(1234567);
let w = SimpleRecursionInputHashedPI{
proofs: proofs_with_pi.clone(),
verifier_data: data.verifier_data(),
};
rec_circuit.assign_witness(&mut pw,&targets,w)?;
let start = Instant::now();
let proof = agg_data.prove(pw)?;
println!("prove time = {:?}", start.elapsed());
println!("public input count = {:?}", proof.public_inputs.len());
// Verify the proof
let verifier_data = agg_data.verifier_data();
assert!(
verifier_data.verify(proof.clone()).is_ok(),
"proof verification failed"
);
let inner_pi: Vec<F> = proofs_with_pi.iter()
.flat_map(|p| p.public_inputs.iter())
.cloned()
.collect();
assert!(
check_agg_proof_hash::<HF>(inner_pi, proof.public_inputs),
"public input verification failed"
);
Ok(())
}
pub fn check_agg_proof_hash<H: AlgebraicHasher<F>>(inner_pi: Vec<F>, agg_pi: Vec<F>) -> bool{
if agg_pi.len() != NUM_HASH_OUT_ELTS {
return false;
}
let expected = H::hash_no_pad(&inner_pi);
expected == HashOut::from_vec(agg_pi)
}

View File

@ -0,0 +1,64 @@
// tests for simple recursion approaches
use std::time::Instant;
use plonky2::plonk::circuit_data::{CircuitData};
use crate::gen_input::{build_circuit, prove_circuit};
use codex_plonky2_circuits::recursion::simple::simple_tree_recursion::aggregate_sampling_proofs_tree;
use crate::params::{C, D, F,HF};
// Test simple tree recursion
#[test]
fn test_simple_tree_recursion() -> anyhow::Result<()> {
// number of samples in each proof
let n_samples = 5;
// number of inner proofs:
let n_inner = 4;
let mut data: Option<CircuitData<F, C, D>> = None;
// get proofs
let mut proofs_with_pi = vec![];
for i in 0..n_inner{
// build the circuit
let (data_i, pw) = build_circuit(n_samples, i)?;
proofs_with_pi.push(prove_circuit(&data_i, &pw)?);
data = Some(data_i);
}
let data = data.unwrap();
println!("inner circuit size = {:?}", data.common.degree_bits());
// serialization
// let gate_serializer = DefaultGateSerializer;
// let generator_serializer =DefaultGeneratorSerializer::<C, D>::default();
// let data_bytes = data.to_bytes(&gate_serializer, &generator_serializer).unwrap();
// println!("inner proof circuit data size = {} bytes", data_bytes.len());
// let file_path = "inner_circ_data.bin";
// // Write data to the file
// write_bytes_to_file(data_bytes, file_path).unwrap();
// println!("Data written to {}", file_path);
let start_time = Instant::now();
let (proof, vd_agg) = aggregate_sampling_proofs_tree::<F,D,C,HF>(&proofs_with_pi, data.verifier_data())?;
println!("prove_time = {:?}", start_time.elapsed());
println!("num of public inputs = {}", proof.public_inputs.len());
println!("agg pub input = {:?}", proof.public_inputs);
println!("outer circuit size = {:?}", vd_agg.common.degree_bits());
// serialization
// // let gate_serializer = DefaultGateSerializer;
// // let generator_serializer =DefaultGeneratorSerializer::<C, D>::default();
// let outer_data_bytes = vd_agg.to_bytes(&gate_serializer, &generator_serializer).unwrap();
// println!("outer proof circuit data size = {} bytes", outer_data_bytes.len());
// let file_path = "outer_circ_data.bin";
// // Write data to the file
// write_bytes_to_file(outer_data_bytes, file_path).unwrap();
// println!("Data written to {}", file_path);
// Verify the proof
let verifier_data = vd_agg;//.verifier_data();
assert!(
verifier_data.verify(proof).is_ok(),
"Merkle proof verification failed"
);
Ok(())
}

View File

@ -3,47 +3,35 @@
#[cfg(test)]
mod tests {
use std::time::Instant;
use anyhow::{anyhow, Result};
use plonky2::hash::poseidon::PoseidonHash;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData};
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut, Hasher, PoseidonGoldilocksConfig};
use plonky2::plonk::config::{GenericConfig, GenericHashOut, Hasher};
use plonky2_field::types::Field;
use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit, SampleCircuitInput};
use codex_plonky2_circuits::params::{F, D, C, Plonky2Proof};
use codex_plonky2_circuits::circuits::sample_cells::SampleCircuitInput;
use crate::params::{C, D, F, HF, Params};
use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion;
use codex_plonky2_circuits::recursion::circuits::inner_circuit::InnerCircuit;
use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash};
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
use crate::gen_input::get_m_default_circ_input;
use codex_plonky2_circuits::recursion::tree_recursion::{NodeCircuit, TreeRecursion};
use codex_plonky2_circuits::recursion::tree1::tree_circuit::TreeRecursion;
/// Uses node recursion to sample the dataset
#[test]
fn test_node_recursion() -> Result<()> {
// const D: usize = 2;
// type C = PoseidonGoldilocksConfig;
// type F = <C as GenericConfig<D>>::F;
fn test_tree1_node_recursion() -> anyhow::Result<()> {
const M: usize = 1;
const N: usize = 2;
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let one = builder.one();
let default_params = Params::default().circuit_params;
let inner_sampling_circuit = SamplingRecursion::<F,D,HF,C>::new(default_params);
let inner_sampling_circuit = SamplingRecursion::default();
let mut node = NodeCircuit::<_,M,N>::new(inner_sampling_circuit);
let mut tree_circ = TreeRecursion::new(node);
let circ_input = get_m_default_circ_input::<M>();
let s = Instant::now();
tree_circ.build()?;
let mut tree_circ = TreeRecursion::<F,D,_,M,N,C>::build::<HF>(inner_sampling_circuit)?;
println!("build = {:?}", s.elapsed());
println!("tree circuit size = {:?}", tree_circ.node_circ.cyclic_circuit_data.common.degree_bits());
let s = Instant::now();
let proof = tree_circ.prove(&circ_input,None, true)?;
println!("prove = {:?}", s.elapsed());
println!("num of pi = {}", proof.public_inputs.len());
println!("pub input: {:?}", proof.public_inputs);
let s = Instant::now();
assert!(
tree_circ.verify_proof(proof).is_ok(),
@ -56,40 +44,32 @@ mod tests {
/// Uses node recursion to sample the dataset
#[test]
fn test_tree_recursion_approach1() -> Result<()> {
// const D: usize = 2;
// type C = PoseidonGoldilocksConfig;
// type F = <C as GenericConfig<D>>::F;
fn test_tree_recursion_approach1() -> anyhow::Result<()> {
const M: usize = 1;
const N: usize = 2;
const DEPTH: usize = 3;
const TOTAL_INPUT: usize = (N.pow(DEPTH as u32) - 1) / (N - 1);
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let inner_sampling_circuit = SamplingRecursion::default();
let mut node = NodeCircuit::<_,M,N>::new(inner_sampling_circuit);
let mut tree_circ = TreeRecursion::new(node);
let default_params = Params::default().circuit_params;
let inner_sampling_circuit = SamplingRecursion::<F,D,HF,C>::new(default_params);
let all_circ_input = get_m_default_circ_input::<TOTAL_INPUT>().to_vec();
let s = Instant::now();
tree_circ.build()?;
let mut tree_circ = TreeRecursion::<F,D,_,M,N,C>::build::<HF>(inner_sampling_circuit)?;
println!("build = {:?}", s.elapsed());
println!("tree circuit size = {:?}", tree_circ.node_circ.cyclic_circuit_data.common.degree_bits());
let s = Instant::now();
let proof = tree_circ.prove_tree(all_circ_input.clone(),DEPTH)?;
println!("prove = {:?}", s.elapsed());
println!("num of pi = {}", proof.public_inputs.len());
println!("pub input: {:?}", proof.public_inputs);
// Extract the final public input hash from the proof
let final_proof_hash = &proof.public_inputs[0..4];
// Recompute the expected final public input hash (outside the circuit)
let expected_hash = compute_expected_pub_input_hash::<SamplingRecursion>(
let expected_hash = compute_expected_pub_input_hash(
&all_circ_input,
DEPTH,
M,
@ -112,8 +92,8 @@ mod tests {
/// Recursively compute the final public input hash for a single node in the recursion tree.
/// This is the same logic from `NodeCircuit::build_circuit`
/// TODO: optimize this
fn compute_node_hash<I: InnerCircuit<Input = SampleCircuitInput<F,D>>>(
all_circ_inputs: &[I::Input],
fn compute_node_hash(
all_circ_inputs: &[SampleCircuitInput<F, D>],
depth: usize,
current_depth: usize,
node_idx: usize,
@ -133,12 +113,12 @@ mod tests {
let mut pi_vec = vec![inp.slot_index];
pi_vec.extend_from_slice(&inp.dataset_root.elements);
pi_vec.extend_from_slice(&inp.entropy.elements);
let hash_res = PoseidonHash::hash_no_pad(&pi_vec);
let hash_res = HF::hash_no_pad(&pi_vec);
outer_pi_hashes.extend_from_slice(&hash_res.elements);
}
// hash all these M hashes into one
let outer_pi_hash = PoseidonHash::hash_no_pad(&outer_pi_hashes);
let outer_pi_hash = HF::hash_no_pad(&outer_pi_hashes);
let is_leaf = current_depth == depth - 1;
@ -153,11 +133,11 @@ mod tests {
let mut inner_pub_input_hashes = vec![];
for i in child_start..child_start + N {
let child_hash = compute_node_hash::<I>(all_circ_inputs, depth, next_depth, i, M, N);
let child_hash = compute_node_hash(all_circ_inputs, depth, next_depth, i, M, N);
inner_pub_input_hashes.extend_from_slice(&child_hash);
}
let inner_pub_input_hash = PoseidonHash::hash_no_pad(&inner_pub_input_hashes);
let inner_pub_input_hash = HF::hash_no_pad(&inner_pub_input_hashes);
inner_pub_input_hash.elements
};
@ -166,20 +146,20 @@ mod tests {
final_input.extend_from_slice(&outer_pi_hash.elements);
final_input.extend_from_slice(&inner_pi_hash_or_zero);
let final_hash = PoseidonHash::hash_no_pad(&final_input);
let final_hash = HF::hash_no_pad(&final_input);
final_hash.elements
}
/// Compute the expected public input hash for the entire recursion tree.
/// This function calls `compute_node_hash` starting from the root (layer 0, node 0).
pub fn compute_expected_pub_input_hash<I: InnerCircuit<Input = SampleCircuitInput<F,D>>>(
all_circ_inputs: &[I::Input],
pub fn compute_expected_pub_input_hash(
all_circ_inputs: &[SampleCircuitInput<F, D>],
depth: usize,
M: usize,
N: usize,
) -> Result<Vec<F>> {
) -> anyhow::Result<Vec<F>> {
// The root node is at layer = 0 and node_idx = 0
let final_hash = compute_node_hash::<I>(all_circ_inputs, depth, 0, 0, M, N);
let final_hash = compute_node_hash(all_circ_inputs, depth, 0, 0, M, N);
Ok(final_hash.to_vec())
}
}

View File

@ -3,41 +3,38 @@
#[cfg(test)]
mod tests {
use std::time::Instant;
use anyhow::{anyhow, Result};
use plonky2::hash::hash_types::HashOut;
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData};
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut, Hasher, PoseidonGoldilocksConfig};
use plonky2::plonk::proof::ProofWithPublicInputs;
use codex_plonky2_circuits::circuits::params::CircuitParams;
use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit, SampleCircuitInput};
use codex_plonky2_circuits::params::{F, D, C, Plonky2Proof};
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::plonk::config::{GenericConfig, Hasher};
use plonky2::plonk::proof::{ProofWithPublicInputs};
use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit;
use crate::params::{F, D, C, HF};
use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion;
use codex_plonky2_circuits::recursion::circuits::inner_circuit::InnerCircuit;
use codex_plonky2_circuits::recursion::leaf_circuit::{LeafCircuit, LeafInput};
use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash};
use codex_plonky2_circuits::recursion::tree2::leaf_circuit::{LeafCircuit, LeafInput};
// use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash};
use crate::gen_input::gen_testing_circuit_input;
use crate::params::TestParams;
use codex_plonky2_circuits::recursion::tree_recursion2::{NodeCircuit as nodeC, TreeRecursion as TR};
use codex_plonky2_circuits::recursion::tree2::utils::{get_dummy_leaf_proof, get_dummy_node_proof};
use crate::gen_input::get_m_default_circ_input;
use crate::params::Params;
use codex_plonky2_circuits::recursion::tree2::{node_circuit::NodeCircuit, tree_circuit::TreeRecursion};
use codex_plonky2_circuits::recursion::tree2::dummy_gen::DummyProofGen;
use codex_plonky2_circuits::circuits::utils::vec_to_array;
/// Uses node recursion to sample the dataset
#[test]
fn test_leaf_circuit() -> Result<()> {
// const D: usize = 2;
// type C = PoseidonGoldilocksConfig;
// type F = <C as GenericConfig<D>>::F;
fn test_leaf_circuit() -> anyhow::Result<()> {
const M: usize = 1;
const N: usize = 2;
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let params = TestParams::default();
let params = Params::default();
let one_circ_input = gen_testing_circuit_input::<F,D>(&params);
let samp_circ = SampleCircuit::<F,D>::new(CircuitParams::default());
let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut builder);
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 builder)?;
let mut pw = PartialWitness::<F>::new();
samp_circ.sample_slot_assign_witness(&mut pw,&inner_tar,&one_circ_input);
let inner_d = builder.build::<C>();
@ -50,21 +47,20 @@ mod tests {
let config2 = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config2);
let inner_circ = SamplingRecursion::default();
let leaf_circuit = LeafCircuit::new(inner_circ);
let inner_circ = SamplingRecursion::<F,D,HF,C>::new(Params::default().circuit_params);
let leaf_circuit = LeafCircuit::<F,D,_>::new(inner_circ);
let s = Instant::now();
let leaf_tar = leaf_circuit.build(&mut builder)?;
let leaf_tar = leaf_circuit.build::<C,HF>(&mut builder)?;
let circ_data = builder.build::<C>();
println!("build = {:?}", s.elapsed());
println!("sampling circuit size = {:?}", circ_data.common.degree_bits());
let s = Instant::now();
// let proof = tree_circ.prove(&[leaf_in],None, true)?;
let mut pw = PartialWitness::<F>::new();
leaf_circuit.assign_targets(&mut pw, &leaf_tar, &leaf_in)?;
leaf_circuit.assign_targets::<C,HF>(&mut pw, &leaf_tar, &leaf_in)?;
let proof = circ_data.prove(pw)?;
println!("prove = {:?}", s.elapsed());
println!("num of pi = {}", proof.public_inputs.len());
println!("pub input: {:?}", proof.public_inputs);
let s = Instant::now();
assert!(
circ_data.verify(proof).is_ok(),
@ -76,8 +72,7 @@ mod tests {
}
#[test]
fn test_node_circuit_approach2() -> Result<()> {
// use predefined: C, D, F c
fn test_node_circuit_approach2() -> anyhow::Result<()> {
const N: usize = 2; // binary tree
let config = CircuitConfig::standard_recursion_config();
@ -85,11 +80,10 @@ mod tests {
//------------ sampling inner circuit ----------------------
// Circuit that does the sampling - default input
let mut params = TestParams::default();
// params.n_samples = 10;
let one_circ_input = gen_testing_circuit_input::<F,D>(&params);
let samp_circ = SampleCircuit::<F,D>::new(CircuitParams::default());
let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut sampling_builder);
let mut params = Params::default();
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);
@ -98,8 +92,8 @@ mod tests {
// ------------------- leaf --------------------
// leaf circuit that verifies the sampling proof
let inner_circ = SamplingRecursion::default();
let leaf_circuit = LeafCircuit::new(inner_circ);
let inner_circ = SamplingRecursion::<F,D,HF,C>::new(Params::default().circuit_params);
let leaf_circuit = LeafCircuit::<F,D,_>::new(inner_circ);
let leaf_in = LeafInput{
inner_proof,
@ -109,17 +103,17 @@ mod tests {
let mut leaf_builder = CircuitBuilder::<F, D>::new(config);
// build
let s = Instant::now();
let leaf_targets = leaf_circuit.build(&mut leaf_builder)?;
let leaf_targets = leaf_circuit.build::<C,HF>(&mut leaf_builder)?;
let leaf_circ_data = leaf_builder.build::<C>();
println!("build = {:?}", s.elapsed());
println!("leaf circuit size = {:?}", leaf_circ_data.common.degree_bits());
// prove
let s = Instant::now();
let mut pw = PartialWitness::<F>::new();
leaf_circuit.assign_targets(&mut pw, &leaf_targets, &leaf_in)?;
leaf_circuit.assign_targets::<C,HF>(&mut pw, &leaf_targets, &leaf_in)?;
let leaf_proof = leaf_circ_data.prove(pw)?;
println!("prove = {:?}", s.elapsed());
println!("num of pi = {}", leaf_proof.public_inputs.len());
println!("pub input: {:?}", leaf_proof.public_inputs);
// verify
let s = Instant::now();
assert!(
@ -132,34 +126,30 @@ mod tests {
// node circuit that verifies leafs or itself
// build
let s = Instant::now();
let mut node = nodeC::build_circuit()?;
let mut node = NodeCircuit::<F,D,C,N>::build_circuit::<_,HF>(leaf_circuit)?;
println!("build = {:?}", s.elapsed());
println!("leaf circuit size = {:?}", node.node_data.node_circuit_data.common.degree_bits());
// prove leaf
let s = Instant::now();
let mut pw = PartialWitness::<F>::new();
let leaf_proofs: [ProofWithPublicInputs<F, C, D>; N] = (0..N)
let leaf_proofs: [ProofWithPublicInputs<F, C, D>; N] =
vec_to_array::<N, ProofWithPublicInputs<F, C, D>>(
(0..N)
.map(|_| {
leaf_proof.clone()
})
.collect::<Vec<_>>()
.try_into()
.map_err(|_| anyhow!("Expected exactly M inner circuits"))?;
let dummy_node_proof = get_dummy_node_proof(
)?;
let dummy_node_proofs: [ProofWithPublicInputs<F, C, D>; N] =
DummyProofGen::<F, D, C>::gen_n_dummy_node_proofs::<N>(
&node.node_data.inner_node_common_data,
&node.node_data.node_circuit_data.verifier_only,
);
let dummy_node_proofs: [ProofWithPublicInputs<F, C, D>; N] = (0..N)
.map(|_| {
dummy_node_proof.clone()
})
.collect::<Vec<_>>()
.try_into()
.map_err(|_| anyhow!("Expected exactly M inner circuits"))?;
nodeC::<N>::assign_targets(
)?;
NodeCircuit::<F,D,C,N>::assign_targets(
node.node_targets.clone(), //targets
Some(leaf_proofs), // leaf proofs
Some(dummy_node_proofs), // node proofs (dummy here)
leaf_proofs, // leaf proofs
dummy_node_proofs, // node proofs (dummy here)
&node.node_data.leaf_circuit_data.verifier_only, // leaf verifier data
&mut pw, // partial witness
true // is leaf
@ -167,7 +157,6 @@ mod tests {
let node_proof = node.node_data.node_circuit_data.prove(pw)?;
println!("prove = {:?}", s.elapsed());
println!("num of pi = {}", node_proof.public_inputs.len());
println!("pub input: {:?}", node_proof.public_inputs);
let s = Instant::now();
assert!(
node.node_data.node_circuit_data.verify(node_proof.clone()).is_ok(),
@ -175,30 +164,26 @@ mod tests {
);
println!("verify = {:?}", s.elapsed());
// prove node
let s = Instant::now();
let mut pw = PartialWitness::<F>::new();
let node_proofs: [ProofWithPublicInputs<F, C, D>; N] = (0..N)
let node_proofs: [ProofWithPublicInputs<F, C, D>; N] =
vec_to_array::<N, ProofWithPublicInputs<F, C, D>>(
(0..N)
.map(|_| {
node_proof.clone()
})
.collect::<Vec<_>>()
.try_into()
.map_err(|_| anyhow!("Expected exactly M inner circuits"))?;
let dummy_leaf_proof = get_dummy_leaf_proof(
)?;
let dummy_leaf_proofs: [ProofWithPublicInputs<F, C, D>; N] =
DummyProofGen::<F, D, C>::gen_n_dummy_leaf_proofs::<N>(
&node.node_data.leaf_circuit_data.common
);
let dummy_leaf_proofs: [ProofWithPublicInputs<F, C, D>; N] = (0..N)
.map(|_| {
dummy_leaf_proof.clone()
})
.collect::<Vec<_>>()
.try_into()
.map_err(|_| anyhow!("Expected exactly M inner circuits"))?;
nodeC::<N>::assign_targets(
)?;
NodeCircuit::<F,D,C,N>::assign_targets(
node.node_targets.clone(), //targets
Some(dummy_leaf_proofs), // leaf proofs
Some(node_proofs), // node proofs (dummy here)
dummy_leaf_proofs, // leaf proofs
node_proofs, // node proofs (dummy here)
&node.node_data.leaf_circuit_data.verifier_only, // leaf verifier data
&mut pw, // partial witness
false // is leaf
@ -207,7 +192,6 @@ mod tests {
// let node_proof = node_d.prove(pw)?;
println!("prove = {:?}", s.elapsed());
println!("num of pi = {}", node_proof.public_inputs.len());
println!("pub input: {:?}", node_proof.public_inputs);
let s = Instant::now();
assert!(
node.node_data.node_circuit_data.verify(node_proof.clone()).is_ok(),
@ -219,8 +203,7 @@ mod tests {
}
#[test]
fn test_tree_recursion_approach2() -> Result<()> {
// use predefined: C, D, F c
fn test_tree_recursion_approach2() -> anyhow::Result<()> {
const N: usize = 2; // binary tree
const K: usize = 4; // number of leaves/slots sampled - should be power of 2
@ -229,22 +212,21 @@ mod tests {
//------------ sampling inner circuit ----------------------
// Circuit that does the sampling - default input
let mut params = TestParams::default();
params.n_samples = 10;
let one_circ_input = gen_testing_circuit_input::<F,D>(&params);
let samp_circ = SampleCircuit::<F,D>::new(CircuitParams::default());
let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut sampling_builder);
let mut params = Params::default();
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);
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)?;
// ------------------- leaf --------------------
// leaf circuit that verifies the sampling proof
let inner_circ = SamplingRecursion::default();
let leaf_circuit = LeafCircuit::new(inner_circ);
let inner_circ = SamplingRecursion::<F,D,HF,C>::new(Params::default().circuit_params);
let leaf_circuit = LeafCircuit::<F,D,_>::new(inner_circ);
let leaf_in = LeafInput{
inner_proof,
@ -254,18 +236,17 @@ mod tests {
let mut leaf_builder = CircuitBuilder::<F, D>::new(config);
// build
let s = Instant::now();
let leaf_targets = leaf_circuit.build(&mut leaf_builder)?;
let leaf_targets = leaf_circuit.build::<C,HF>(&mut leaf_builder)?;
let leaf_circ_data = leaf_builder.build::<C>();
println!("build = {:?}", s.elapsed());
println!("leaf circuit degree bits = {:?}", leaf_circ_data.common.degree_bits());
println!("leaf circuit size = {:?}", leaf_circ_data.common.degree_bits());
// prove
let s = Instant::now();
let mut pw = PartialWitness::<F>::new();
leaf_circuit.assign_targets(&mut pw, &leaf_targets, &leaf_in)?;
leaf_circuit.assign_targets::<C,HF>(&mut pw, &leaf_targets, &leaf_in)?;
let leaf_proof = leaf_circ_data.prove(pw)?;
println!("prove = {:?}", s.elapsed());
println!("num of pi = {}", leaf_proof.public_inputs.len());
println!("pub input: {:?}", leaf_proof.public_inputs);
// verify
let s = Instant::now();
assert!(
@ -278,30 +259,73 @@ mod tests {
// node circuit that verifies leafs or itself
// build
let s = Instant::now();
let mut tree = TR::<N>::build()?;
let mut tree = TreeRecursion::<F,D,C,N>::build::<_,HF>(leaf_circuit)?;
println!("build = {:?}", s.elapsed());
println!("tree circuit degree bits = {:?}", tree.node.node_data.node_circuit_data.common.degree_bits());
println!("node circuit degree bits = {:?}", tree.node.node_data.node_circuit_data.common.degree_bits());
// prove leaf
let s = Instant::now();
// let mut pw = PartialWitness::<F>::new();
let leaf_proofs: Vec<ProofWithPublicInputs<F, C, D>> = (0..K)
.map(|_| {
leaf_proof.clone()
})
.collect::<Vec<_>>();
let tree_root_proof = tree.prove_tree(leaf_proofs)?;
let tree_root_proof = tree.prove_tree(leaf_proofs.clone())?;
println!("prove = {:?}", s.elapsed());
println!("num of pi = {}", tree_root_proof.public_inputs.len());
println!("pub input: {:?}", tree_root_proof.public_inputs);
let s = Instant::now();
assert!(
tree.verify_proof(tree_root_proof.clone()).is_ok(),
tree.verify_proof(tree_root_proof.clone(),false).is_ok(),
"proof verification failed"
);
assert_eq!(
tree_root_proof.public_inputs[0..4].to_vec(),
get_expected_tree_root_pi_hash::<N>(leaf_proofs),
"Public input of tree_root_proof does not match the expected root hash"
);
println!("verify = {:?}", s.elapsed());
Ok(())
}
// ------------ Public Input Verification ------------
/// Recompute the expected root public input hash outside the circuit
fn get_expected_tree_root_pi_hash<const N:usize>(leaf_proofs: Vec<ProofWithPublicInputs<F, C, D>>)
-> Vec<F>{
// Step 1: Extract relevant public inputs from each leaf proof
// Assuming the first public input is the hash used for tree hashing
let mut current_hashes: Vec<HashOut<F>> = leaf_proofs
.iter()
.map(|p|HashOut::from_vec(p.public_inputs.clone())) // Adjust index if different
.collect();
// Step 2: Iteratively compute parent hashes until one root hash remains
while current_hashes.len() > 1 {
let mut next_level_hashes = Vec::new();
for chunk in current_hashes.chunks(N) {
// Ensure each chunk has exactly N elements
assert!(
chunk.len() == N,
"Number of proofs is not divisible by N"
);
// collect field elements
let chunk_f: Vec<F> = chunk.iter()
.flat_map(|h| h.elements.iter().cloned())
.collect();
// Compute Poseidon2 hash of the concatenated chunk
let hash = HF::hash_no_pad(&chunk_f);
next_level_hashes.push(hash);
}
current_hashes = next_level_hashes;
}
// The final hash is the expected root hash
current_hashes[0].elements.to_vec()
}
}

View File

@ -12,7 +12,6 @@ use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
use codex_plonky2_circuits::circuits::sample_cells::SampleCircuitInput;
use plonky2::plonk::proof::CompressedProofWithPublicInputs;
use serde_json::to_writer_pretty;
use crate::params::InputParams;
// Function to export proof with public input to json file
fn export_proof_with_pi_to_json<F, C, const D: usize>(
@ -46,9 +45,8 @@ pub fn read_bytes_from_file<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
#[cfg(test)]
mod tests {
use super::*;
use crate::params::{C, D, F, HF, InputParams, Params};
use crate::params::{C, D, F, HF, Params};
use std::time::Instant;
use codex_plonky2_circuits::circuits::params::CircuitParams;
use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit;
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;

View File

@ -2,7 +2,6 @@ use plonky2::hash::hash_types::{HashOut, RichField};
use plonky2_field::extension::Extendable;
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
use crate::params::HF;
use anyhow::Result;
use plonky2::hash::hashing::PlonkyPermutation;
use crate::sponge::hash_n_with_padding;