add dataset level proof

This commit is contained in:
M Alghazwi 2024-10-21 13:31:54 +02:00
parent 0fcf280f6c
commit 3c5a130a70
3 changed files with 34 additions and 8 deletions

View File

@ -94,7 +94,7 @@ fn build_circuit<F, C, const D: usize, H>(
// For each proof, create targets, add constraints, and assign witnesses // For each proof, create targets, add constraints, and assign witnesses
for &leaf_index in leaf_indices.iter() { for &leaf_index in leaf_indices.iter() {
// Build the circuit for each proof // Build the circuit for each proof
let mut targets = circuit_instance.build_circuit(&mut builder); let (mut targets, _root) = circuit_instance.build_circuit(&mut builder);
// Assign witnesses for each proof // Assign witnesses for each proof
circuit_instance.assign_witness(&mut pw, &mut targets, leaf_index)?; circuit_instance.assign_witness(&mut pw, &mut targets, leaf_index)?;

View File

@ -66,7 +66,7 @@ impl<
pub fn build_circuit( pub fn build_circuit(
&mut self, &mut self,
builder: &mut CircuitBuilder::<F, D> builder: &mut CircuitBuilder::<F, D>
) -> MerkleTreeTargets<F, C, D, H>{ ) -> (MerkleTreeTargets<F, C, { D }, H>, HashOutTarget) {
// Retrieve tree depth // Retrieve tree depth
let depth = self.tree.depth(); let depth = self.tree.depth();
@ -94,10 +94,10 @@ impl<
}; };
// Add Merkle proof verification constraints to the circuit // Add Merkle proof verification constraints to the circuit
Self::reconstruct_merkle_root_circuit(builder, &mut targets); let expected_root_target = Self::reconstruct_merkle_root_circuit(builder, &mut targets);
// Return MerkleTreeTargets // Return MerkleTreeTargets
targets (targets, expected_root_target)
} }
/// assign the witness values in the circuit targets /// assign the witness values in the circuit targets
@ -268,7 +268,7 @@ mod tests {
tree: tree.clone(), tree: tree.clone(),
_phantom: PhantomData, _phantom: PhantomData,
}; };
let mut targets = circuit_instance.build_circuit(&mut builder); let (mut targets, expected_root_target) = circuit_instance.build_circuit(&mut builder);
// create a PartialWitness and assign // create a PartialWitness and assign
let mut pw = PartialWitness::new(); let mut pw = PartialWitness::new();
@ -324,7 +324,7 @@ mod tests {
tree: tree.clone(), tree: tree.clone(),
_phantom: PhantomData, _phantom: PhantomData,
}; };
let mut targets = circuit_instance.build_circuit(&mut builder); let (mut targets, expected_root_target) = circuit_instance.build_circuit(&mut builder);
let data = builder.build::<C>(); let data = builder.build::<C>();

View File

@ -7,7 +7,7 @@
use anyhow::Result; use anyhow::Result;
use plonky2::field::extension::Extendable; use plonky2::field::extension::Extendable;
use plonky2::hash::hash_types::{HashOut, RichField}; use plonky2::hash::hash_types::{HashOut, HashOutTarget, NUM_HASH_OUT_ELTS, RichField};
use plonky2::iop::target::{BoolTarget, Target}; use plonky2::iop::target::{BoolTarget, Target};
use plonky2::iop::witness::{PartialWitness, WitnessWrite, Witness}; use plonky2::iop::witness::{PartialWitness, WitnessWrite, Witness};
use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_builder::CircuitBuilder;
@ -205,13 +205,15 @@ impl<
//------- single cell struct ------ //------- single cell struct ------
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone)]
pub struct DatasetTargets< pub struct DatasetTargets<
F: RichField + Extendable<D> + Poseidon2, F: RichField + Extendable<D> + Poseidon2,
C: GenericConfig<D, F = F>, C: GenericConfig<D, F = F>,
const D: usize, const D: usize,
H: Hasher<F> + AlgebraicHasher<F>, H: Hasher<F> + AlgebraicHasher<F>,
> { > {
pub dataset_proof: MerkleTreeTargets<F, C, D, H>,
pub dataset_root: HashOutTarget,
pub slot_proofs: Vec<SingleCellTargets<F, C, D, H>>, pub slot_proofs: Vec<SingleCellTargets<F, C, D, H>>,
_phantom: PhantomData<(C,H)>, _phantom: PhantomData<(C,H)>,
@ -231,6 +233,16 @@ impl<
builder: &mut CircuitBuilder::<F, D>, builder: &mut CircuitBuilder::<F, D>,
)-> DatasetTargets<F,C,D,H>{ )-> DatasetTargets<F,C,D,H>{
let (dataset_proof, dataset_root_target) = self.tree.build_circuit(builder);
// expected Merkle root
let dataset_expected_root = builder.add_virtual_hash();
// check equality with expected root
for i in 0..NUM_HASH_OUT_ELTS {
builder.connect(dataset_expected_root.elements[i], dataset_root_target.elements[i]);
}
let mut slot_proofs =vec![]; let mut slot_proofs =vec![];
for i in 0..N_SAMPLES{ for i in 0..N_SAMPLES{
let proof_i = SlotTreeCircuit::<F,C,D,H>::prove_single_cell(builder); let proof_i = SlotTreeCircuit::<F,C,D,H>::prove_single_cell(builder);
@ -238,6 +250,8 @@ impl<
} }
DatasetTargets::<F,C,D,H>{ DatasetTargets::<F,C,D,H>{
dataset_proof,
dataset_root: dataset_expected_root,
slot_proofs, slot_proofs,
_phantom: Default::default(), _phantom: Default::default(),
} }
@ -252,9 +266,21 @@ impl<
slot_index:usize, slot_index:usize,
entropy:usize, entropy:usize,
){ ){
// assign witness for dataset level target (proving slot root is in dataset tree)
self.tree.assign_witness(pw,&mut targets.dataset_proof,slot_index);
// assign the expected Merkle root of dataset to the target
let expected_root = self.tree.tree.root().unwrap();
let expected_root_hash_out = expected_root.to_vec();
for j in 0..expected_root_hash_out.len() {
pw.set_target(targets.dataset_root.elements[j], expected_root_hash_out[j]);
}
// the sampled slot
let slot = &self.slot_trees[slot_index]; let slot = &self.slot_trees[slot_index];
let slot_root = slot.tree.tree.root().unwrap(); let slot_root = slot.tree.tree.root().unwrap();
// do the sample N times
for i in 0..N_SAMPLES { for i in 0..N_SAMPLES {
let cell_index_bits = calculate_cell_index_bits(entropy, slot_root, i); let cell_index_bits = calculate_cell_index_bits(entropy, slot_root, i);
let cell_index = bits_le_padded_to_usize(&cell_index_bits); let cell_index = bits_le_padded_to_usize(&cell_index_bits);