mirror of
https://github.com/logos-storage/proof-aggregation.git
synced 2026-01-02 13:53:13 +00:00
add generic circuit helper and refactor.
This commit is contained in:
parent
65508f3da9
commit
c4eefceba8
105
codex-plonky2-circuits/src/circuit_helper/mod.rs
Normal file
105
codex-plonky2-circuits/src/circuit_helper/mod.rs
Normal file
@ -0,0 +1,105 @@
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::iop::witness::PartialWitness;
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, ProverCircuitData, VerifierCircuitData};
|
||||
use plonky2::plonk::config::GenericConfig;
|
||||
use plonky2::plonk::proof::ProofWithPublicInputs;
|
||||
use plonky2_field::extension::Extendable;
|
||||
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
|
||||
use crate::error::CircuitError;
|
||||
use crate::Result;
|
||||
|
||||
/// Plonky2Circuit is the trait used to define the logic of the circuit and assign witnesses
|
||||
/// to that circuit instance.
|
||||
pub trait Plonky2Circuit<
|
||||
F: RichField + Extendable<D> + Poseidon2,
|
||||
C: GenericConfig<D, F = F>,
|
||||
const D: usize,
|
||||
> {
|
||||
type Targets;
|
||||
type Input:Clone;
|
||||
|
||||
/// build the circuit with standard config
|
||||
fn build_with_standard_config(
|
||||
&self,
|
||||
) -> Result<(Self::Targets,CircuitData<F, C, D>)>{
|
||||
self.build(CircuitConfig::standard_recursion_config())
|
||||
}
|
||||
|
||||
/// build the circuit
|
||||
fn build(
|
||||
&self,
|
||||
circuit_config: CircuitConfig,
|
||||
) -> Result<(Self::Targets,CircuitData<F, C, D>)>{
|
||||
let mut builder = CircuitBuilder::<F, D>::new(circuit_config);
|
||||
|
||||
let targets = self.add_targets(&mut builder, true)?;
|
||||
|
||||
Ok((targets,builder.build::<C>()))
|
||||
}
|
||||
|
||||
/// build the circuit logic and return targets to be assigned later
|
||||
/// based on register_pi, registers the public input or not.
|
||||
fn add_targets(
|
||||
&self,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
register_pi: bool
|
||||
) -> Result<Self::Targets>;
|
||||
|
||||
/// assign the actual witness values for the current instance of the circuit.
|
||||
fn assign_targets(
|
||||
&self,
|
||||
pw: &mut PartialWitness<F>,
|
||||
targets: &Self::Targets,
|
||||
input: &Self::Input,
|
||||
) -> Result<()>;
|
||||
|
||||
/// get the common data for the circuit with standard config
|
||||
fn get_common_data_standard_config(
|
||||
&self
|
||||
) -> Result<CircuitData<F, C, D>>{
|
||||
self.get_common_data(CircuitConfig::standard_recursion_config())
|
||||
}
|
||||
|
||||
/// get the common data for the circuit
|
||||
fn get_common_data(
|
||||
&self,
|
||||
circuit_config: CircuitConfig,
|
||||
) -> Result<CircuitData<F, C, D>>{
|
||||
let mut builder = CircuitBuilder::<F, D>::new(circuit_config);
|
||||
|
||||
self.add_targets(&mut builder, true)?;
|
||||
|
||||
let circ_data = builder.build::<C>();
|
||||
|
||||
Ok(circ_data)
|
||||
}
|
||||
|
||||
/// generates a proof for the circuit using the given targets, input and prover circuit data
|
||||
fn prove(
|
||||
&self,
|
||||
targets: &Self::Targets,
|
||||
input: &Self::Input,
|
||||
prover_circuit_data: ProverCircuitData<F, C, D>
|
||||
)-> Result<ProofWithPublicInputs<F, C, D>>{
|
||||
let mut pw = PartialWitness::new();
|
||||
self.assign_targets(&mut pw, targets, input)?;
|
||||
|
||||
let proof = prover_circuit_data.prove(pw).map_err(
|
||||
|e| CircuitError::ProofGenerationError(e.to_string())
|
||||
)?;
|
||||
|
||||
Ok(proof)
|
||||
}
|
||||
|
||||
/// verify the given proof with the verifier circuit data
|
||||
fn verify(
|
||||
proof_with_pi: ProofWithPublicInputs<F, C, D>,
|
||||
verifier_circuit_data: VerifierCircuitData<F, C, D>
|
||||
) -> Result<()>{
|
||||
verifier_circuit_data.verify(proof_with_pi).map_err( |e|
|
||||
CircuitError::InvalidProofError(e.to_string())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// https://github.com/codex-storage/codex-storage-proofs-circuits/blob/master/circuit/codex/merkle.circom
|
||||
|
||||
use plonky2::{
|
||||
field::{extension::Extendable, types::Field},
|
||||
field::extension::Extendable,
|
||||
hash::hash_types::{HashOutTarget, RichField, NUM_HASH_OUT_ELTS},
|
||||
iop::target::BoolTarget,
|
||||
plonk::{
|
||||
|
||||
@ -11,7 +11,6 @@ use plonky2::{
|
||||
field::extension::Extendable,
|
||||
hash::{
|
||||
hash_types::{HashOut, HashOutTarget, NUM_HASH_OUT_ELTS, RichField},
|
||||
hashing::PlonkyPermutation,
|
||||
},
|
||||
iop::{
|
||||
target::{BoolTarget, Target},
|
||||
@ -19,7 +18,6 @@ use plonky2::{
|
||||
},
|
||||
plonk::circuit_builder::CircuitBuilder,
|
||||
};
|
||||
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData};
|
||||
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
|
||||
|
||||
@ -33,6 +31,7 @@ use crate::{
|
||||
Result,
|
||||
error::CircuitError,
|
||||
};
|
||||
use crate::circuit_helper::Plonky2Circuit;
|
||||
|
||||
/// circuit for sampling a slot in a dataset merkle tree
|
||||
#[derive(Clone, Debug)]
|
||||
@ -168,7 +167,6 @@ impl<
|
||||
// Create virtual target for slot root and index
|
||||
let slot_root = builder.add_virtual_hash();
|
||||
let slot_index = builder.add_virtual_target();// public input
|
||||
// let slot_index = builder.add_virtual_public_input();// public input
|
||||
|
||||
// dataset path bits (binary decomposition of leaf_index)
|
||||
let d_path_bits = builder.split_le(slot_index,max_log2_n_slots);
|
||||
@ -200,7 +198,6 @@ impl<
|
||||
|
||||
// expected Merkle root
|
||||
let d_expected_root = builder.add_virtual_hash(); // public input
|
||||
// let d_expected_root = builder.add_virtual_hash_public_input(); // public input
|
||||
|
||||
// check equality with expected root
|
||||
for i in 0..NUM_HASH_OUT_ELTS {
|
||||
@ -212,7 +209,6 @@ impl<
|
||||
let mut data_targets =vec![];
|
||||
let mut slot_sample_proofs = vec![];
|
||||
let entropy_target = builder.add_virtual_hash(); // public input
|
||||
// let entropy_target = builder.add_virtual_hash_public_input(); // public input
|
||||
|
||||
// virtual target for n_cells_per_slot
|
||||
let n_cells_per_slot = builder.add_virtual_target();
|
||||
@ -229,7 +225,7 @@ impl<
|
||||
let mut b_mask_bits = builder.split_le(slot_last_index,max_depth);
|
||||
|
||||
// last and mask bits for the slot tree
|
||||
let mut s_last_bits = b_last_bits.split_off(block_tree_depth);
|
||||
let s_last_bits = b_last_bits.split_off(block_tree_depth);
|
||||
let mut s_mask_bits = b_mask_bits.split_off(block_tree_depth);
|
||||
|
||||
// pad mask bits with 0
|
||||
@ -238,7 +234,7 @@ impl<
|
||||
|
||||
for i in 0..n_samples{
|
||||
// cell data targets
|
||||
let mut data_i = (0..n_field_elems_per_cell).map(|_| builder.add_virtual_target()).collect::<Vec<_>>();
|
||||
let data_i = (0..n_field_elems_per_cell).map(|_| builder.add_virtual_target()).collect::<Vec<_>>();
|
||||
// hash the cell data
|
||||
let mut hash_inputs:Vec<Target>= Vec::new();
|
||||
hash_inputs.extend_from_slice(&data_i);
|
||||
@ -256,13 +252,13 @@ impl<
|
||||
}
|
||||
// paths for block and slot
|
||||
let mut b_path_bits = self.calculate_cell_index_bits(builder, &entropy_target, &d_targets.leaf, &ctr, mask_bits.clone())?;
|
||||
let mut s_path_bits = b_path_bits.split_off(block_tree_depth);
|
||||
let s_path_bits = b_path_bits.split_off(block_tree_depth);
|
||||
|
||||
let mut b_merkle_path = MerkleProofTarget {
|
||||
let b_merkle_path = MerkleProofTarget {
|
||||
path: (0..block_tree_depth).map(|_| builder.add_virtual_hash()).collect(),
|
||||
};
|
||||
|
||||
let mut s_merkle_path = MerkleProofTarget {
|
||||
let s_merkle_path = MerkleProofTarget {
|
||||
path: (0..(max_depth - block_tree_depth)).map(|_| builder.add_virtual_hash()).collect(),
|
||||
};
|
||||
|
||||
@ -323,7 +319,7 @@ impl<
|
||||
}
|
||||
|
||||
/// calculate the cell index = H( entropy | slotRoot | counter ) `mod` nCells
|
||||
pub fn calculate_cell_index_bits(&self, builder: &mut CircuitBuilder<F, D>, entropy: &HashOutTarget, slot_root: &HashOutTarget, ctr: &HashOutTarget, mask_bits: Vec<BoolTarget>) -> Result<Vec<BoolTarget>> {
|
||||
fn calculate_cell_index_bits(&self, builder: &mut CircuitBuilder<F, D>, entropy: &HashOutTarget, slot_root: &HashOutTarget, ctr: &HashOutTarget, mask_bits: Vec<BoolTarget>) -> Result<Vec<BoolTarget>> {
|
||||
let mut hash_inputs:Vec<Target>= Vec::new();
|
||||
hash_inputs.extend_from_slice(&entropy.elements);
|
||||
hash_inputs.extend_from_slice(&slot_root.elements);
|
||||
@ -421,3 +417,27 @@ impl<
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Implements the Plonky2Circuit trait
|
||||
impl<
|
||||
F: RichField + Extendable<D> + Poseidon2,
|
||||
C: GenericConfig<D, F = F>,
|
||||
const D: usize,
|
||||
H: AlgebraicHasher<F>,
|
||||
> Plonky2Circuit<F,C,D> for SampleCircuit<F,D,H> {
|
||||
type Targets = SampleTargets;
|
||||
type Input = SampleCircuitInput<F, D>;
|
||||
|
||||
fn add_targets(&self, builder: &mut CircuitBuilder<F, D>, register_pi: bool) -> Result<Self::Targets> {
|
||||
let targets = if register_pi {
|
||||
self.sample_slot_circuit_with_public_input(builder)
|
||||
} else { self.sample_slot_circuit(builder) };
|
||||
|
||||
targets
|
||||
}
|
||||
|
||||
fn assign_targets(&self, pw: &mut PartialWitness<F>, targets: &Self::Targets, input: &Self::Input) -> Result<()> {
|
||||
self.sample_slot_assign_witness(pw,targets,input)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
pub mod circuits;
|
||||
pub mod recursion;
|
||||
pub mod error;
|
||||
pub mod circuit_helper;
|
||||
|
||||
pub type Result<T> = core::result::Result<T, error::CircuitError>;
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
pub mod dummy_gen;
|
||||
pub mod conditional_verifier;
|
||||
pub mod conditional_verifier;
|
||||
Loading…
x
Reference in New Issue
Block a user