mirror of
https://github.com/logos-storage/proof-aggregation.git
synced 2026-01-03 06:13:11 +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
|
// https://github.com/codex-storage/codex-storage-proofs-circuits/blob/master/circuit/codex/merkle.circom
|
||||||
|
|
||||||
use plonky2::{
|
use plonky2::{
|
||||||
field::{extension::Extendable, types::Field},
|
field::extension::Extendable,
|
||||||
hash::hash_types::{HashOutTarget, RichField, NUM_HASH_OUT_ELTS},
|
hash::hash_types::{HashOutTarget, RichField, NUM_HASH_OUT_ELTS},
|
||||||
iop::target::BoolTarget,
|
iop::target::BoolTarget,
|
||||||
plonk::{
|
plonk::{
|
||||||
|
|||||||
@ -11,7 +11,6 @@ use plonky2::{
|
|||||||
field::extension::Extendable,
|
field::extension::Extendable,
|
||||||
hash::{
|
hash::{
|
||||||
hash_types::{HashOut, HashOutTarget, NUM_HASH_OUT_ELTS, RichField},
|
hash_types::{HashOut, HashOutTarget, NUM_HASH_OUT_ELTS, RichField},
|
||||||
hashing::PlonkyPermutation,
|
|
||||||
},
|
},
|
||||||
iop::{
|
iop::{
|
||||||
target::{BoolTarget, Target},
|
target::{BoolTarget, Target},
|
||||||
@ -19,7 +18,6 @@ use plonky2::{
|
|||||||
},
|
},
|
||||||
plonk::circuit_builder::CircuitBuilder,
|
plonk::circuit_builder::CircuitBuilder,
|
||||||
};
|
};
|
||||||
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData};
|
|
||||||
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
|
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||||
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
|
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
|
||||||
|
|
||||||
@ -33,6 +31,7 @@ use crate::{
|
|||||||
Result,
|
Result,
|
||||||
error::CircuitError,
|
error::CircuitError,
|
||||||
};
|
};
|
||||||
|
use crate::circuit_helper::Plonky2Circuit;
|
||||||
|
|
||||||
/// circuit for sampling a slot in a dataset merkle tree
|
/// circuit for sampling a slot in a dataset merkle tree
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -168,7 +167,6 @@ impl<
|
|||||||
// Create virtual target for slot root and index
|
// Create virtual target for slot root and index
|
||||||
let slot_root = builder.add_virtual_hash();
|
let slot_root = builder.add_virtual_hash();
|
||||||
let slot_index = builder.add_virtual_target();// public input
|
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)
|
// dataset path bits (binary decomposition of leaf_index)
|
||||||
let d_path_bits = builder.split_le(slot_index,max_log2_n_slots);
|
let d_path_bits = builder.split_le(slot_index,max_log2_n_slots);
|
||||||
@ -200,7 +198,6 @@ impl<
|
|||||||
|
|
||||||
// expected Merkle root
|
// expected Merkle root
|
||||||
let d_expected_root = builder.add_virtual_hash(); // public input
|
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
|
// check equality with expected root
|
||||||
for i in 0..NUM_HASH_OUT_ELTS {
|
for i in 0..NUM_HASH_OUT_ELTS {
|
||||||
@ -212,7 +209,6 @@ impl<
|
|||||||
let mut data_targets =vec![];
|
let mut data_targets =vec![];
|
||||||
let mut slot_sample_proofs = 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
|
||||||
// let entropy_target = builder.add_virtual_hash_public_input(); // public input
|
|
||||||
|
|
||||||
// virtual target for n_cells_per_slot
|
// virtual target for n_cells_per_slot
|
||||||
let n_cells_per_slot = builder.add_virtual_target();
|
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);
|
let mut b_mask_bits = builder.split_le(slot_last_index,max_depth);
|
||||||
|
|
||||||
// last and mask bits for the slot tree
|
// 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);
|
let mut s_mask_bits = b_mask_bits.split_off(block_tree_depth);
|
||||||
|
|
||||||
// pad mask bits with 0
|
// pad mask bits with 0
|
||||||
@ -238,7 +234,7 @@ impl<
|
|||||||
|
|
||||||
for i in 0..n_samples{
|
for i in 0..n_samples{
|
||||||
// cell data targets
|
// 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
|
// hash the cell data
|
||||||
let mut hash_inputs:Vec<Target>= Vec::new();
|
let mut hash_inputs:Vec<Target>= Vec::new();
|
||||||
hash_inputs.extend_from_slice(&data_i);
|
hash_inputs.extend_from_slice(&data_i);
|
||||||
@ -256,13 +252,13 @@ impl<
|
|||||||
}
|
}
|
||||||
// paths for block and slot
|
// 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 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(),
|
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(),
|
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
|
/// 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();
|
let mut hash_inputs:Vec<Target>= Vec::new();
|
||||||
hash_inputs.extend_from_slice(&entropy.elements);
|
hash_inputs.extend_from_slice(&entropy.elements);
|
||||||
hash_inputs.extend_from_slice(&slot_root.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 circuits;
|
||||||
pub mod recursion;
|
pub mod recursion;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
pub mod circuit_helper;
|
||||||
|
|
||||||
pub type Result<T> = core::result::Result<T, error::CircuitError>;
|
pub type Result<T> = core::result::Result<T, error::CircuitError>;
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
pub mod dummy_gen;
|
pub mod dummy_gen;
|
||||||
pub mod conditional_verifier;
|
pub mod conditional_verifier;
|
||||||
Loading…
x
Reference in New Issue
Block a user