Skip to content

Commit

Permalink
Add LUT hash to remove CircuitBuilder overhead
Browse files Browse the repository at this point in the history
  • Loading branch information
Nashtare committed Jul 14, 2023
1 parent 8b35fef commit b193457
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
24 changes: 22 additions & 2 deletions plonky2/src/gates/lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use alloc::string::String;
use alloc::vec::Vec;
use core::usize;

use itertools::Itertools;
use keccak_hash::keccak;

use super::lookup_table::LookupTable;
use crate::field::extension::Extendable;
use crate::field::packed::PackedField;
Expand Down Expand Up @@ -31,13 +34,22 @@ pub struct LookupGate {
pub num_slots: usize,
/// LUT associated to the gate.
lut: LookupTable,
/// The Keccak hash of the lookup table.
lut_hash: [u8; 32],
}

impl LookupGate {
pub fn new_from_table(config: &CircuitConfig, lut: LookupTable) -> Self {
let table_bytes = lut
.iter()
.map(|(input, output)| [input.to_le_bytes(), output.to_le_bytes()].concat())

Check failure on line 45 in plonky2/src/gates/lookup.rs

View workflow job for this annotation

GitHub Actions / Formatting and Clippy

called `map(..).flatten()` on `Iterator`
.flatten()
.collect_vec();

Self {
num_slots: Self::num_slots(config),
lut,
lut_hash: keccak(&table_bytes).0,

Check failure on line 52 in plonky2/src/gates/lookup.rs

View workflow job for this annotation

GitHub Actions / Formatting and Clippy

the borrowed expression implements the required traits
}
}
pub(crate) fn num_slots(config: &CircuitConfig) -> usize {
Expand All @@ -56,14 +68,19 @@ impl LookupGate {

impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupGate {
fn id(&self) -> String {
format!("{self:?}")
// Custom implementation to not have the entire lookup table
format!(
"LookupGate {{num_slots: {}, lut_hash: {:?}}}",
self.num_slots, self.lut_hash
)
}

fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_slots)?;
for (i, lut) in common_data.luts.iter().enumerate() {
if lut == &self.lut {
return dst.write_usize(i);
dst.write_usize(i)?;
return dst.write_all(&self.lut_hash);
}
}

Expand All @@ -73,10 +90,13 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupGate {
fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let num_slots = src.read_usize()?;
let lut_index = src.read_usize()?;
let mut lut_hash = [0u8; 32];
src.read_exact(&mut lut_hash)?;

Ok(Self {
num_slots,
lut: common_data.luts[lut_index].clone(),
lut_hash,
})
}

Expand Down
23 changes: 21 additions & 2 deletions plonky2/src/gates/lookup_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use alloc::sync::Arc;
use alloc::vec::Vec;
use core::usize;

use itertools::Itertools;
use keccak_hash::keccak;
use plonky2_util::ceil_div_usize;

use crate::field::extension::Extendable;
Expand Down Expand Up @@ -33,15 +35,24 @@ pub struct LookupTableGate {
pub num_slots: usize,
/// Lookup table associated to the gate.
pub lut: LookupTable,
/// The Keccak hash of the lookup table.
lut_hash: [u8; 32],
/// First row of the lookup table.
last_lut_row: usize,
}

impl LookupTableGate {
pub fn new_from_table(config: &CircuitConfig, lut: LookupTable, last_lut_row: usize) -> Self {
let table_bytes = lut
.iter()
.map(|(input, output)| [input.to_le_bytes(), output.to_le_bytes()].concat())

Check failure on line 48 in plonky2/src/gates/lookup_table.rs

View workflow job for this annotation

GitHub Actions / Formatting and Clippy

called `map(..).flatten()` on `Iterator`
.flatten()
.collect_vec();

Self {
num_slots: Self::num_slots(config),
lut,
lut_hash: keccak(&table_bytes).0,

Check failure on line 55 in plonky2/src/gates/lookup_table.rs

View workflow job for this annotation

GitHub Actions / Formatting and Clippy

the borrowed expression implements the required traits
last_lut_row,
}
}
Expand Down Expand Up @@ -69,15 +80,20 @@ impl LookupTableGate {

impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupTableGate {
fn id(&self) -> String {
format!("{self:?}")
// Custom implementation to not have the entire lookup table
format!(
"LookupGate {{num_slots: {}, lut_hash: {:?}, last_lut_row: {}}}",
self.num_slots, self.lut_hash, self.last_lut_row
)
}

fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_slots)?;
dst.write_usize(self.last_lut_row)?;
for (i, lut) in common_data.luts.iter().enumerate() {
if lut == &self.lut {
return dst.write_usize(i);
dst.write_usize(i)?;
return dst.write_all(&self.lut_hash);
}
}

Expand All @@ -88,10 +104,13 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupTableGat
let num_slots = src.read_usize()?;
let last_lut_row = src.read_usize()?;
let lut_index = src.read_usize()?;
let mut lut_hash = [0u8; 32];
src.read_exact(&mut lut_hash)?;

Ok(Self {
num_slots,
lut: common_data.luts[lut_index].clone(),
lut_hash,
last_lut_row,
})
}
Expand Down

0 comments on commit b193457

Please sign in to comment.