diff --git a/codex-plonky2-circuits/src/circuits/mod.rs b/codex-plonky2-circuits/src/circuits/mod.rs index 744d84d..41bb46e 100644 --- a/codex-plonky2-circuits/src/circuits/mod.rs +++ b/codex-plonky2-circuits/src/circuits/mod.rs @@ -1,4 +1,6 @@ pub mod capped_tree_circuit; pub mod safe_tree_circuit; pub mod prove_single_cell; -pub mod sample_cells; \ No newline at end of file +pub mod sample_cells; +pub mod utils; +pub mod params; \ No newline at end of file diff --git a/codex-plonky2-circuits/src/circuits/params.rs b/codex-plonky2-circuits/src/circuits/params.rs new file mode 100644 index 0000000..1bfb1c4 --- /dev/null +++ b/codex-plonky2-circuits/src/circuits/params.rs @@ -0,0 +1,20 @@ +// global params for the circuits +// only change params here + +use plonky2::hash::poseidon::PoseidonHash; + +// constants and types used throughout the circuit +pub const N_FIELD_ELEMS_PER_CELL: usize = 4; +pub const BOT_DEPTH: usize = 5; // block depth - depth of the block merkle tree +pub const MAX_DEPTH: usize = 16; // depth of big tree (slot tree depth + block tree depth) +pub const N_CELLS_IN_BLOCKS: usize = 1< and causing a lot of headache +// will look into this later. +pub type HF = PoseidonHash; \ No newline at end of file diff --git a/codex-plonky2-circuits/src/circuits/prove_single_cell.rs b/codex-plonky2-circuits/src/circuits/prove_single_cell.rs index cdc53b9..13ef578 100644 --- a/codex-plonky2-circuits/src/circuits/prove_single_cell.rs +++ b/codex-plonky2-circuits/src/circuits/prove_single_cell.rs @@ -29,18 +29,8 @@ use plonky2::plonk::config::PoseidonGoldilocksConfig; use plonky2::hash::hashing::PlonkyPermutation; use crate::circuits::safe_tree_circuit::{MerkleTreeCircuit, MerkleTreeTargets}; - -// constants and types used throughout the circuit -pub const N_FIELD_ELEMS_PER_CELL: usize = 4; -pub const BOT_DEPTH: usize = 5; // block depth - depth of the block merkle tree -pub const MAX_DEPTH: usize = 16; // depth of big tree (slot tree depth + block tree depth) -const N_CELLS_IN_BLOCKS: usize = 1< and causing a lot of headache -// will look into this later. -type HF = PoseidonHash; +use crate::circuits::utils::usize_to_bits_le_padded; +use crate::circuits::params::{MAX_DEPTH, BOT_DEPTH, N_FIELD_ELEMS_PER_CELL, N_CELLS_IN_BLOCKS, N_BLOCKS, N_CELLS, HF}; // ------ Slot Tree -------- @@ -157,9 +147,9 @@ impl> SlotTree { /// verify the given proof for slot tree, checks equality with given root pub fn verify_cell_proof(&self, proof: MerkleProof, root: HashOut) -> Result{ - let mut block_path_bits = self.usize_to_bits_le_padded(proof.index, MAX_DEPTH); + let mut block_path_bits = usize_to_bits_le_padded(proof.index, MAX_DEPTH); let last_index = N_CELLS - 1; - let mut block_last_bits = self.usize_to_bits_le_padded(last_index, MAX_DEPTH); + let mut block_last_bits = usize_to_bits_le_padded(last_index, MAX_DEPTH); let split_point = BOT_DEPTH; @@ -186,18 +176,18 @@ impl> SlotTree { return block_tree; } - /// Converts an index to a vector of bits (LSB first) with padding. - pub(crate) fn usize_to_bits_le_padded(&self, index: usize, bit_length: usize) -> Vec { - let mut bits = Vec::with_capacity(bit_length); - for i in 0..bit_length { - bits.push(((index >> i) & 1) == 1); - } - // If index requires fewer bits, pad with `false` - while bits.len() < bit_length { - bits.push(false); - } - bits - } + // /// Converts an index to a vector of bits (LSB first) with padding. + // pub(crate) fn usize_to_bits_le_padded(&self, index: usize, bit_length: usize) -> Vec { + // let mut bits = Vec::with_capacity(bit_length); + // for i in 0..bit_length { + // bits.push(((index >> i) & 1) == 1); + // } + // // If index requires fewer bits, pad with `false` + // while bits.len() < bit_length { + // bits.push(false); + // } + // bits + // } } //------- single cell struct ------ @@ -329,14 +319,14 @@ impl< } // Convert `leaf_index` to binary bits and assign as path_bits - let path_bits = self.usize_to_bits_le_padded(leaf_index, MAX_DEPTH); + let path_bits = usize_to_bits_le_padded(leaf_index, MAX_DEPTH); for (i, bit) in path_bits.iter().enumerate() { pw.set_bool_target(targets.path_bits[i], *bit); } // get `last_index` (nleaves - 1) in binary bits and assign let last_index = N_CELLS - 1; - let last_bits = self.usize_to_bits_le_padded(last_index, MAX_DEPTH); + let last_bits = usize_to_bits_le_padded(last_index, MAX_DEPTH); for (i, bit) in last_bits.iter().enumerate() { pw.set_bool_target(targets.last_bits[i], *bit); } diff --git a/codex-plonky2-circuits/src/circuits/safe_tree_circuit.rs b/codex-plonky2-circuits/src/circuits/safe_tree_circuit.rs index 04c8f75..96e4bbf 100644 --- a/codex-plonky2-circuits/src/circuits/safe_tree_circuit.rs +++ b/codex-plonky2-circuits/src/circuits/safe_tree_circuit.rs @@ -18,6 +18,7 @@ use plonky2::plonk::proof::{Proof, ProofWithPublicInputs}; use std::marker::PhantomData; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use serde::Serialize; +use crate::circuits::utils::usize_to_bits_le_padded; use crate::merkle_tree::merkle_safe::{MerkleTree, MerkleProofTarget}; use crate::merkle_tree::merkle_safe::{KEY_NONE,KEY_BOTTOM_LAYER}; @@ -144,14 +145,14 @@ impl< pw.set_hash_target(targets.leaf, leaf_hash); // Convert `leaf_index` to binary bits and assign as path_bits - let path_bits = self.usize_to_bits_le_padded(leaf_index, depth); + let path_bits = usize_to_bits_le_padded(leaf_index, depth); for (i, bit) in path_bits.iter().enumerate() { pw.set_bool_target(targets.path_bits[i], *bit); } // get `last_index` (nleaves - 1) in binary bits and assign let last_index = nleaves - 1; - let last_bits = self.usize_to_bits_le_padded(last_index, depth); + let last_bits = usize_to_bits_le_padded(last_index, depth); for (i, bit) in last_bits.iter().enumerate() { pw.set_bool_target(targets.last_bits[i], *bit); } @@ -234,25 +235,25 @@ impl< } // --------- helper functions --------- -impl< - F: RichField + Extendable + Poseidon2, - C: GenericConfig, - const D: usize, - H: Hasher + AlgebraicHasher, -> MerkleTreeCircuit { - /// Converts an index to a vector of bits (LSB first) with padding. - pub(crate) fn usize_to_bits_le_padded(&self, index: usize, bit_length: usize) -> Vec { - let mut bits = Vec::with_capacity(bit_length); - for i in 0..bit_length { - bits.push(((index >> i) & 1) == 1); - } - // If index requires fewer bits, pad with `false` - while bits.len() < bit_length { - bits.push(false); - } - bits - } -} +// impl< +// F: RichField + Extendable + Poseidon2, +// C: GenericConfig, +// const D: usize, +// H: Hasher + AlgebraicHasher, +// > MerkleTreeCircuit { +// /// Converts an index to a vector of bits (LSB first) with padding. +// pub(crate) fn usize_to_bits_le_padded(&self, index: usize, bit_length: usize) -> Vec { +// let mut bits = Vec::with_capacity(bit_length); +// for i in 0..bit_length { +// bits.push(((index >> i) & 1) == 1); +// } +// // If index requires fewer bits, pad with `false` +// while bits.len() < bit_length { +// bits.push(false); +// } +// bits +// } +// } // NOTE: for now these tests don't check the reconstructed root is equal to expected_root diff --git a/codex-plonky2-circuits/src/circuits/sample_cells.rs b/codex-plonky2-circuits/src/circuits/sample_cells.rs index 4b28b45..b6d0dd3 100644 --- a/codex-plonky2-circuits/src/circuits/sample_cells.rs +++ b/codex-plonky2-circuits/src/circuits/sample_cells.rs @@ -27,15 +27,11 @@ use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::plonk::config::PoseidonGoldilocksConfig; use plonky2::hash::hashing::PlonkyPermutation; -use crate::circuits::prove_single_cell::{MAX_DEPTH, SlotTree}; +use crate::circuits::prove_single_cell::{SingleCellTargets, SlotTree}; +use crate::circuits::params::{MAX_DEPTH, BOT_DEPTH, N_FIELD_ELEMS_PER_CELL, N_CELLS_IN_BLOCKS, N_BLOCKS, N_CELLS, HF, DATASET_DEPTH, N_SAMPLES}; + use crate::circuits::safe_tree_circuit::{MerkleTreeCircuit, MerkleTreeTargets}; -// constatnts and types -const DATASET_DEPTH: usize = 2; -const N_SAMPLES: usize = 5; - -type HF = PoseidonHash; - // ------ Dataset Tree -------- ///dataset tree containing all slot trees #[derive(Clone)] @@ -155,6 +151,78 @@ impl> DatasetTree { } } +//------- single cell struct ------ + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct DatasetTargets< + F: RichField + Extendable + Poseidon2, + C: GenericConfig, + const D: usize, + H: Hasher + AlgebraicHasher, +> { + // pub expected_dataset_root_target: HashOutTarget, + // pub slot_index: Target, + // pub entropy_target: Target, + // pub slot_root: HashOutTarget, + pub slot_proofs: Vec>, + + + // pub proof_target: MerkleProofTarget, + // pub leaf_target: Vec, + // pub path_bits: Vec, + // pub last_bits: Vec, + _phantom: PhantomData<(C,H)>, +} + +//------- circuit impl -------- +impl< + F: RichField + Extendable + Poseidon2, + C: GenericConfig, + const D: usize, + H: Hasher + AlgebraicHasher + Hasher, +> MerkleTreeCircuit { + + // the in-circuit sampling of a slot in a dataset + pub fn sample_slot_circuit( + &mut self, + builder: &mut CircuitBuilder::, + )-> DatasetTargets{ + + // Create virtual targets + // let slot_root = builder.add_virtual_hash(); + let mut slot_proofs =vec![]; + for i in 0..N_SAMPLES{ + let proof_i = self.prove_single_cell2(builder); + slot_proofs.push(proof_i); + } + + DatasetTargets::{ + // expected_dataset_root_target: HashOutTarget {}, + // slot_index: Default::default(), + // entropy_target: Default::default(), + // slot_root: HashOutTarget {}, + slot_proofs, + _phantom: Default::default(), + } + } + + // assign the witnesses to the target + // takes the dataset tree, slot index, and entropy + pub fn sample_slot_assign_witness( + &mut self, + pw: &mut PartialWitness, + targets: DatasetTargets, + dataset_tree: DatasetTree, + slot_index:usize, + entropy:usize, + ){ + + + } + +} + + // --------- helper functions -------------- fn calculate_cell_index_bits(p0: usize, p1: HashOut, p2: usize) -> Vec { let p0_field = F::from_canonical_u64(p0 as u64); diff --git a/codex-plonky2-circuits/src/circuits/utils.rs b/codex-plonky2-circuits/src/circuits/utils.rs new file mode 100644 index 0000000..77f62e6 --- /dev/null +++ b/codex-plonky2-circuits/src/circuits/utils.rs @@ -0,0 +1,17 @@ + + + +// --------- helper functions --------- + +/// Converts an index to a vector of bits (LSB first) with padding. +pub(crate) fn usize_to_bits_le_padded(index: usize, bit_length: usize) -> Vec { + let mut bits = Vec::with_capacity(bit_length); + for i in 0..bit_length { + bits.push(((index >> i) & 1) == 1); + } + // If index requires fewer bits, pad with `false` + while bits.len() < bit_length { + bits.push(false); + } + bits +} \ No newline at end of file