From c6f749e2be79b5609b0377d77b570118ef49bea6 Mon Sep 17 00:00:00 2001 From: DoHoonKim Date: Mon, 6 Nov 2023 17:31:40 +0900 Subject: [PATCH] Fix ANDTable test case --- plonkish_backend/src/backend/hyperplonk.rs | 3 +- .../src/backend/hyperplonk/util.rs | 27 ++++------- .../lookup/lasso/memory_checking/prover.rs | 8 +--- .../lookup/lasso/memory_checking/verifier.rs | 6 ++- .../src/backend/lookup/lasso/test/mod.rs | 48 ++++++++++++++----- .../src/backend/lookup/lasso/verifier/mod.rs | 2 +- plonkish_backend/src/util/arithmetic.rs | 12 +++++ 7 files changed, 65 insertions(+), 41 deletions(-) diff --git a/plonkish_backend/src/backend/hyperplonk.rs b/plonkish_backend/src/backend/hyperplonk.rs index 93109bd..915c263 100644 --- a/plonkish_backend/src/backend/hyperplonk.rs +++ b/plonkish_backend/src/backend/hyperplonk.rs @@ -135,7 +135,8 @@ where + circuit_info.num_witness_polys.iter().sum::() + permutation_polys.len() + num_permutation_z_polys; - let lookup_points_offset = zero_check_opening_points_len(&expression, circuit_info.num_instances.len()); + let lookup_points_offset = + zero_check_opening_points_len(&expression, circuit_info.num_instances.len()); let lasso_lookup = &circuit_info.lasso_lookup[0]; let vp = HyperPlonkVerifierParam { diff --git a/plonkish_backend/src/backend/hyperplonk/util.rs b/plonkish_backend/src/backend/hyperplonk/util.rs index 4f2a2c8..bc59f27 100644 --- a/plonkish_backend/src/backend/hyperplonk/util.rs +++ b/plonkish_backend/src/backend/hyperplonk/util.rs @@ -93,8 +93,11 @@ pub fn vanilla_plonk_with_lasso_lookup_circuit_info( ) -> PlonkishCircuitInfo { let [pi, q_l, q_r, q_m, q_o, q_c, q_lookup, t_l, t_r, t_o, w_l, w_r, w_o] = &array::from_fn(|poly| Query::new(poly, Rotation::cur())).map(Expression::::Polynomial); - let lasso_lookup_input = w_l.clone(); - let lasso_lookup_indices = w_r.clone(); + let lasso_lookup_input = w_o.clone(); + let lasso_lookup_indices = Expression::DistributePowers( + vec![w_l.clone(), w_r.clone()], + Box::new(Expression::Constant(F::from_u128(1 << 64))), + ); let lasso_table = Box::new(AndTable::::new()); let chunk_bits = lasso_table.chunk_bits(); let num_vars = chunk_bits.iter().chain([&num_vars]).max().unwrap(); @@ -373,24 +376,10 @@ pub fn rand_vanilla_plonk_with_lasso_lookup_circuit( for poly in [10, 11, 12] { permutation.copy((poly, 1), (poly, 1)); } - let and_table = AndTable::::new(); - let subtable_poly = &and_table.subtable_polys()[0]; for idx in 0..size - 1 { - let (w_l, w_r) = { - let index = witness_rng.next_u64(); - let index_bits = fe_to_bits_le(F::from(index)); - assert_eq!(usize_from_bits_le(&index_bits) as u64, index); - let operands = index_bits[..64] - .chunks(16) - .map(|chunked_index_bits| { - let chunked_index = usize_from_bits_le(chunked_index_bits); - subtable_poly[chunked_index] - }) - .collect_vec(); - let value = and_table.combine_lookups(&operands); - (value, F::from(index)) - }; - let values = vec![(10, w_l), (11, w_r)]; + let [w_l, w_r] = [(); 2].map(|_| witness_rng.next_u64()); + let w_o = w_l & w_r; + let values = vec![(10, F::from(w_l)), (11, F::from(w_r)), (12, F::from(w_o))]; for (poly, value) in values { polys[poly][idx] = value; } diff --git a/plonkish_backend/src/backend/lookup/lasso/memory_checking/prover.rs b/plonkish_backend/src/backend/lookup/lasso/memory_checking/prover.rs index 1814c36..479b0c6 100644 --- a/plonkish_backend/src/backend/lookup/lasso/memory_checking/prover.rs +++ b/plonkish_backend/src/backend/lookup/lasso/memory_checking/prover.rs @@ -5,12 +5,8 @@ use itertools::{chain, Itertools}; use rayon::prelude::{IntoParallelIterator, ParallelIterator}; use crate::{ - backend::lookup::lasso::prover::Chunk, - pcs::Evaluation, - piop::gkr::prove_grand_product, - poly::multilinear::MultilinearPolynomial, - util::transcript::FieldTranscriptWrite, - Error, + backend::lookup::lasso::prover::Chunk, pcs::Evaluation, piop::gkr::prove_grand_product, + poly::multilinear::MultilinearPolynomial, util::transcript::FieldTranscriptWrite, Error, }; use super::MemoryGKR; diff --git a/plonkish_backend/src/backend/lookup/lasso/memory_checking/verifier.rs b/plonkish_backend/src/backend/lookup/lasso/memory_checking/verifier.rs index f5cdd44..e29df27 100644 --- a/plonkish_backend/src/backend/lookup/lasso/memory_checking/verifier.rs +++ b/plonkish_backend/src/backend/lookup/lasso/memory_checking/verifier.rs @@ -4,7 +4,11 @@ use halo2_curves::ff::PrimeField; use itertools::{chain, Itertools}; use crate::{ - pcs::Evaluation, piop::gkr::verify_grand_product, util::{transcript::FieldTranscriptRead, arithmetic::inner_product}, Error, poly::multilinear::MultilinearPolynomial, + pcs::Evaluation, + piop::gkr::verify_grand_product, + poly::multilinear::MultilinearPolynomial, + util::{arithmetic::inner_product, transcript::FieldTranscriptRead}, + Error, }; #[derive(Clone, Debug)] diff --git a/plonkish_backend/src/backend/lookup/lasso/test/mod.rs b/plonkish_backend/src/backend/lookup/lasso/test/mod.rs index d3471f1..57f64fd 100644 --- a/plonkish_backend/src/backend/lookup/lasso/test/mod.rs +++ b/plonkish_backend/src/backend/lookup/lasso/test/mod.rs @@ -1,12 +1,12 @@ use std::{iter, marker::PhantomData}; use halo2_curves::ff::PrimeField; -use itertools::Itertools; +use itertools::{izip, Itertools}; use crate::{ poly::multilinear::MultilinearPolynomial, util::{ - arithmetic::{inner_product, split_bits}, + arithmetic::{inner_product, split_bits, split_by_chunk_bits}, expression::Expression, }, }; @@ -22,13 +22,14 @@ impl AndTable { } } +/// T[X || Y] = T_1[X_1 || Y_1] + T_2[X_2 || Y_2] * 2^8 + ... + T_8[X_8 || Y_8] * 2^56 impl DecomposableTable for AndTable { fn num_chunks(&self) -> usize { - 4 + 8 } fn num_memories(&self) -> usize { - 4 + 8 } fn subtable_polys(&self) -> Vec> { @@ -43,23 +44,44 @@ impl DecomposableTable for AndTable { } fn chunk_bits(&self) -> Vec { - vec![16, 16, 16, 16] + vec![16; 8] } - fn combine_lookup_expressions(&self, expressions: Vec>) -> Expression { - Expression::DistributePowers( - expressions, - Box::new(Expression::Constant(F::from(2 << 16))), + fn subtable_indices(&self, index_bits: Vec) -> Vec> { + assert!(index_bits.len() % 2 == 0); + let chunk_bits = self + .chunk_bits() + .iter() + .map(|chunk_bits| chunk_bits / 2) + .collect_vec(); + let (lhs, rhs) = index_bits.split_at(index_bits.len() / 2); + izip!( + split_by_chunk_bits(lhs, &chunk_bits), + split_by_chunk_bits(rhs, &chunk_bits) ) + .map(|(chunked_lhs_bits, chunked_rhs_bits)| { + iter::empty() + .chain(chunked_lhs_bits) + .chain(chunked_rhs_bits) + .collect_vec() + }) + .collect_vec() + } + + fn combine_lookup_expressions(&self, expressions: Vec>) -> Expression { + Expression::DistributePowers(expressions, Box::new(Expression::Constant(F::from(1 << 8)))) } fn combine_lookups(&self, operands: &[F]) -> F { + let weight = F::from(1 << 8); inner_product( operands, - iter::successors(Some(F::ONE), |power_of_two| Some(power_of_two.double())) - .take(operands.len()) - .collect_vec() - .iter(), + iter::successors(Some(F::ONE), |power_of_weight| { + Some(*power_of_weight * weight) + }) + .take(operands.len()) + .collect_vec() + .iter(), ) } diff --git a/plonkish_backend/src/backend/lookup/lasso/verifier/mod.rs b/plonkish_backend/src/backend/lookup/lasso/verifier/mod.rs index 4f6d704..0b95825 100644 --- a/plonkish_backend/src/backend/lookup/lasso/verifier/mod.rs +++ b/plonkish_backend/src/backend/lookup/lasso/verifier/mod.rs @@ -15,7 +15,7 @@ use crate::{ }; use super::{ - memory_checking::verifier::{MemoryCheckingVerifier, Chunk, Memory}, + memory_checking::verifier::{Chunk, Memory, MemoryCheckingVerifier}, prover::Surge, DecomposableTable, }; diff --git a/plonkish_backend/src/util/arithmetic.rs b/plonkish_backend/src/util/arithmetic.rs index 3189b24..100ea8e 100644 --- a/plonkish_backend/src/util/arithmetic.rs +++ b/plonkish_backend/src/util/arithmetic.rs @@ -220,6 +220,18 @@ pub fn split_bits(item: usize, num_bits: usize) -> (usize, usize) { (high_chunk, low_chunk) } +pub fn split_by_chunk_bits(bits: &[bool], chunk_bits: &[usize]) -> Vec> { + let mut offset = 0; + let mut chunked_bits = vec![]; + chunk_bits.iter().for_each(|chunk_bits| { + let mut chunked = vec![true; *chunk_bits]; + chunked.copy_from_slice(&bits[offset..offset + chunk_bits]); + chunked_bits.push(chunked); + offset = offset + chunk_bits; + }); + chunked_bits +} + #[cfg(test)] mod test { use crate::util::arithmetic;