refactor utils and params
This commit is contained in:
parent
b1c13a9bc1
commit
5a13ac3650
|
@ -1,4 +1,6 @@
|
||||||
pub mod capped_tree_circuit;
|
pub mod capped_tree_circuit;
|
||||||
pub mod safe_tree_circuit;
|
pub mod safe_tree_circuit;
|
||||||
pub mod prove_single_cell;
|
pub mod prove_single_cell;
|
||||||
pub mod sample_cells;
|
pub mod sample_cells;
|
||||||
|
pub mod utils;
|
||||||
|
pub mod params;
|
|
@ -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<<BOT_DEPTH; //2^BOT_DEPTH
|
||||||
|
pub const N_BLOCKS: usize = 1<<(MAX_DEPTH - BOT_DEPTH); // 2^(MAX_DEPTH - BOT_DEPTH)
|
||||||
|
pub const N_CELLS: usize = N_CELLS_IN_BLOCKS * N_BLOCKS;
|
||||||
|
|
||||||
|
pub const DATASET_DEPTH: usize = 2;
|
||||||
|
pub const N_SAMPLES: usize = 5;
|
||||||
|
|
||||||
|
// hash function used. this is hackish way of doing it because
|
||||||
|
// H::Hash is not consistent with HashOut<F> and causing a lot of headache
|
||||||
|
// will look into this later.
|
||||||
|
pub type HF = PoseidonHash;
|
|
@ -29,18 +29,8 @@ use plonky2::plonk::config::PoseidonGoldilocksConfig;
|
||||||
|
|
||||||
use plonky2::hash::hashing::PlonkyPermutation;
|
use plonky2::hash::hashing::PlonkyPermutation;
|
||||||
use crate::circuits::safe_tree_circuit::{MerkleTreeCircuit, MerkleTreeTargets};
|
use crate::circuits::safe_tree_circuit::{MerkleTreeCircuit, MerkleTreeTargets};
|
||||||
|
use crate::circuits::utils::usize_to_bits_le_padded;
|
||||||
// constants and types used throughout the circuit
|
use crate::circuits::params::{MAX_DEPTH, BOT_DEPTH, N_FIELD_ELEMS_PER_CELL, N_CELLS_IN_BLOCKS, N_BLOCKS, N_CELLS, HF};
|
||||||
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<<BOT_DEPTH; //2^BOT_DEPTH
|
|
||||||
const N_BLOCKS: usize = 1<<(MAX_DEPTH - BOT_DEPTH); // 2^(MAX_DEPTH - BOT_DEPTH)
|
|
||||||
const N_CELLS: usize = N_CELLS_IN_BLOCKS * N_BLOCKS;
|
|
||||||
// hash function used. this is hackish way of doing it because
|
|
||||||
// H::Hash is not consistent with HashOut<F> and causing a lot of headache
|
|
||||||
// will look into this later.
|
|
||||||
type HF = PoseidonHash;
|
|
||||||
|
|
||||||
// ------ Slot Tree --------
|
// ------ Slot Tree --------
|
||||||
|
|
||||||
|
@ -157,9 +147,9 @@ impl<F: RichField, H: Hasher<F>> SlotTree<F, H> {
|
||||||
|
|
||||||
/// verify the given proof for slot tree, checks equality with given root
|
/// verify the given proof for slot tree, checks equality with given root
|
||||||
pub fn verify_cell_proof(&self, proof: MerkleProof<F, H>, root: HashOut<F>) -> Result<bool>{
|
pub fn verify_cell_proof(&self, proof: MerkleProof<F, H>, root: HashOut<F>) -> Result<bool>{
|
||||||
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 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;
|
let split_point = BOT_DEPTH;
|
||||||
|
|
||||||
|
@ -186,18 +176,18 @@ impl<F: RichField, H: Hasher<F>> SlotTree<F, H> {
|
||||||
return block_tree;
|
return block_tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an index to a vector of bits (LSB first) with padding.
|
// /// 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<bool> {
|
// pub(crate) fn usize_to_bits_le_padded(&self, index: usize, bit_length: usize) -> Vec<bool> {
|
||||||
let mut bits = Vec::with_capacity(bit_length);
|
// let mut bits = Vec::with_capacity(bit_length);
|
||||||
for i in 0..bit_length {
|
// for i in 0..bit_length {
|
||||||
bits.push(((index >> i) & 1) == 1);
|
// bits.push(((index >> i) & 1) == 1);
|
||||||
}
|
// }
|
||||||
// If index requires fewer bits, pad with `false`
|
// // If index requires fewer bits, pad with `false`
|
||||||
while bits.len() < bit_length {
|
// while bits.len() < bit_length {
|
||||||
bits.push(false);
|
// bits.push(false);
|
||||||
}
|
// }
|
||||||
bits
|
// bits
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
//------- single cell struct ------
|
//------- single cell struct ------
|
||||||
|
@ -329,14 +319,14 @@ impl<
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert `leaf_index` to binary bits and assign as path_bits
|
// 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() {
|
for (i, bit) in path_bits.iter().enumerate() {
|
||||||
pw.set_bool_target(targets.path_bits[i], *bit);
|
pw.set_bool_target(targets.path_bits[i], *bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get `last_index` (nleaves - 1) in binary bits and assign
|
// get `last_index` (nleaves - 1) in binary bits and assign
|
||||||
let last_index = N_CELLS - 1;
|
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() {
|
for (i, bit) in last_bits.iter().enumerate() {
|
||||||
pw.set_bool_target(targets.last_bits[i], *bit);
|
pw.set_bool_target(targets.last_bits[i], *bit);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ use plonky2::plonk::proof::{Proof, ProofWithPublicInputs};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
|
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
|
||||||
use serde::Serialize;
|
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::{MerkleTree, MerkleProofTarget};
|
||||||
use crate::merkle_tree::merkle_safe::{KEY_NONE,KEY_BOTTOM_LAYER};
|
use crate::merkle_tree::merkle_safe::{KEY_NONE,KEY_BOTTOM_LAYER};
|
||||||
|
@ -144,14 +145,14 @@ impl<
|
||||||
pw.set_hash_target(targets.leaf, leaf_hash);
|
pw.set_hash_target(targets.leaf, leaf_hash);
|
||||||
|
|
||||||
// Convert `leaf_index` to binary bits and assign as path_bits
|
// 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() {
|
for (i, bit) in path_bits.iter().enumerate() {
|
||||||
pw.set_bool_target(targets.path_bits[i], *bit);
|
pw.set_bool_target(targets.path_bits[i], *bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get `last_index` (nleaves - 1) in binary bits and assign
|
// get `last_index` (nleaves - 1) in binary bits and assign
|
||||||
let last_index = nleaves - 1;
|
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() {
|
for (i, bit) in last_bits.iter().enumerate() {
|
||||||
pw.set_bool_target(targets.last_bits[i], *bit);
|
pw.set_bool_target(targets.last_bits[i], *bit);
|
||||||
}
|
}
|
||||||
|
@ -234,25 +235,25 @@ impl<
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------- helper functions ---------
|
// --------- helper functions ---------
|
||||||
impl<
|
// impl<
|
||||||
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>,
|
||||||
> MerkleTreeCircuit<F, C, D, H> {
|
// > MerkleTreeCircuit<F, C, D, H> {
|
||||||
/// Converts an index to a vector of bits (LSB first) with padding.
|
// /// 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<bool> {
|
// pub(crate) fn usize_to_bits_le_padded(&self, index: usize, bit_length: usize) -> Vec<bool> {
|
||||||
let mut bits = Vec::with_capacity(bit_length);
|
// let mut bits = Vec::with_capacity(bit_length);
|
||||||
for i in 0..bit_length {
|
// for i in 0..bit_length {
|
||||||
bits.push(((index >> i) & 1) == 1);
|
// bits.push(((index >> i) & 1) == 1);
|
||||||
}
|
// }
|
||||||
// If index requires fewer bits, pad with `false`
|
// // If index requires fewer bits, pad with `false`
|
||||||
while bits.len() < bit_length {
|
// while bits.len() < bit_length {
|
||||||
bits.push(false);
|
// bits.push(false);
|
||||||
}
|
// }
|
||||||
bits
|
// bits
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
// NOTE: for now these tests don't check the reconstructed root is equal to expected_root
|
// NOTE: for now these tests don't check the reconstructed root is equal to expected_root
|
||||||
|
|
|
@ -27,15 +27,11 @@ use plonky2::field::goldilocks_field::GoldilocksField;
|
||||||
use plonky2::plonk::config::PoseidonGoldilocksConfig;
|
use plonky2::plonk::config::PoseidonGoldilocksConfig;
|
||||||
|
|
||||||
use plonky2::hash::hashing::PlonkyPermutation;
|
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};
|
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 --------
|
||||||
///dataset tree containing all slot trees
|
///dataset tree containing all slot trees
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -155,6 +151,78 @@ impl<F: RichField, H: Hasher<F>> DatasetTree<F, H> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------- single cell struct ------
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct DatasetTargets<
|
||||||
|
F: RichField + Extendable<D> + Poseidon2,
|
||||||
|
C: GenericConfig<D, F = F>,
|
||||||
|
const D: usize,
|
||||||
|
H: Hasher<F> + AlgebraicHasher<F>,
|
||||||
|
> {
|
||||||
|
// pub expected_dataset_root_target: HashOutTarget,
|
||||||
|
// pub slot_index: Target,
|
||||||
|
// pub entropy_target: Target,
|
||||||
|
// pub slot_root: HashOutTarget,
|
||||||
|
pub slot_proofs: Vec<SingleCellTargets<F, C, D, H>>,
|
||||||
|
|
||||||
|
|
||||||
|
// pub proof_target: MerkleProofTarget,
|
||||||
|
// pub leaf_target: Vec<Target>,
|
||||||
|
// pub path_bits: Vec<BoolTarget>,
|
||||||
|
// pub last_bits: Vec<BoolTarget>,
|
||||||
|
_phantom: PhantomData<(C,H)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
//------- circuit impl --------
|
||||||
|
impl<
|
||||||
|
F: RichField + Extendable<D> + Poseidon2,
|
||||||
|
C: GenericConfig<D, F=F>,
|
||||||
|
const D: usize,
|
||||||
|
H: Hasher<F> + AlgebraicHasher<F> + Hasher<F>,
|
||||||
|
> MerkleTreeCircuit<F, C, D, H> {
|
||||||
|
|
||||||
|
// the in-circuit sampling of a slot in a dataset
|
||||||
|
pub fn sample_slot_circuit(
|
||||||
|
&mut self,
|
||||||
|
builder: &mut CircuitBuilder::<F, D>,
|
||||||
|
)-> DatasetTargets<F,C,D,H>{
|
||||||
|
|
||||||
|
// 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::<F,C,D,H>{
|
||||||
|
// 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<F>,
|
||||||
|
targets: DatasetTargets<F,C,D,H>,
|
||||||
|
dataset_tree: DatasetTree<F,H>,
|
||||||
|
slot_index:usize,
|
||||||
|
entropy:usize,
|
||||||
|
){
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------- helper functions --------------
|
// --------- helper functions --------------
|
||||||
fn calculate_cell_index_bits<F: RichField>(p0: usize, p1: HashOut<F>, p2: usize) -> Vec<bool> {
|
fn calculate_cell_index_bits<F: RichField>(p0: usize, p1: HashOut<F>, p2: usize) -> Vec<bool> {
|
||||||
let p0_field = F::from_canonical_u64(p0 as u64);
|
let p0_field = F::from_canonical_u64(p0 as u64);
|
||||||
|
|
|
@ -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<bool> {
|
||||||
|
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
|
||||||
|
}
|
Loading…
Reference in New Issue