Serialize Lookup gates and generators

This commit is contained in:
Robin Salen 2023-05-01 11:43:36 +02:00
parent 35abffd5fc
commit 7e80b42a83
No known key found for this signature in database
GPG Key ID: FB87BACFB3CB2007
4 changed files with 103 additions and 14 deletions

View File

@ -1,4 +1,3 @@
use alloc::boxed::Box;
use alloc::format;
use alloc::string::String;
use alloc::sync::Arc;
@ -12,7 +11,7 @@ use crate::gates::packed_util::PackedEvaluableBase;
use crate::gates::util::StridedConstraintConsumer;
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder;
@ -21,6 +20,7 @@ use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked,
};
use crate::util::serialization::{Buffer, IoResult, Read, Write};
/// A gate which stores (input, output) lookup pairs made elsewhere in the trace. It doesn't check any constraints itself.
#[derive(Debug, Clone)]
@ -57,6 +57,21 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupGate {
format!("{self:?}")
}
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
dst.write_usize(self.num_slots)?;
dst.write_lut(&self.lut)
}
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let num_slots = src.read_usize()?;
let lut = src.read_lut()?;
Ok(Self {
num_slots,
lut: Arc::new(lut),
})
}
fn eval_unfiltered(&self, _vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
// No main trace constraints for lookups.
vec![]
@ -83,18 +98,17 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupGate {
vec![]
}
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
(0..self.num_slots)
.map(|i| {
let g: Box<dyn WitnessGenerator<F>> = Box::new(
WitnessGeneratorRef::new(
LookupGenerator {
row,
lut: self.lut.clone(),
slot_nb: i,
}
.adapter(),
);
g
)
})
.collect()
}
@ -125,7 +139,7 @@ impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D> for
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Default)]
pub struct LookupGenerator {
row: usize,
lut: Arc<Vec<(u16, u16)>>,
@ -133,6 +147,10 @@ pub struct LookupGenerator {
}
impl<F: RichField> SimpleGenerator<F> for LookupGenerator {
fn id(&self) -> String {
"LookupGenerator".to_string()
}
fn dependencies(&self) -> Vec<Target> {
vec![Target::wire(
self.row,
@ -162,4 +180,22 @@ impl<F: RichField> SimpleGenerator<F> for LookupGenerator {
let out_wire = Target::wire(self.row, LookupGate::wire_ith_looking_out(self.slot_nb));
out_buffer.set_target(out_wire, output_val);
}
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
dst.write_usize(self.row)?;
dst.write_lut(&self.lut)?;
dst.write_usize(self.slot_nb)
}
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let row = src.read_usize()?;
let lut = src.read_lut()?;
let slot_nb = src.read_usize()?;
Ok(Self {
row,
lut: Arc::new(lut),
slot_nb,
})
}
}

View File

@ -1,4 +1,3 @@
use alloc::boxed::Box;
use alloc::format;
use alloc::string::String;
use alloc::sync::Arc;
@ -14,7 +13,7 @@ use crate::gates::packed_util::PackedEvaluableBase;
use crate::gates::util::StridedConstraintConsumer;
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder;
@ -23,6 +22,7 @@ use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked,
};
use crate::util::serialization::{Buffer, IoResult, Read, Write};
/// A gate which stores the set of (input, output) value pairs of a lookup table, and their multiplicities.
#[derive(Debug, Clone)]
@ -74,6 +74,24 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupTableGat
format!("{self:?}")
}
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
dst.write_usize(self.num_slots)?;
dst.write_lut(&self.lut)?;
dst.write_usize(self.last_lut_row)
}
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let num_slots = src.read_usize()?;
let lut = src.read_lut()?;
let last_lut_row = src.read_usize()?;
Ok(Self {
num_slots,
lut: Arc::new(lut),
last_lut_row,
})
}
fn eval_unfiltered(&self, _vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
// No main trace constraints for the lookup table.
vec![]
@ -100,10 +118,10 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupTableGat
vec![]
}
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
(0..self.num_slots)
.map(|i| {
let g: Box<dyn WitnessGenerator<F>> = Box::new(
WitnessGeneratorRef::new(
LookupTableGenerator {
row,
lut: self.lut.clone(),
@ -112,8 +130,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupTableGat
last_lut_row: self.last_lut_row,
}
.adapter(),
);
g
)
})
.collect()
}
@ -144,7 +161,7 @@ impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D> for
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Default)]
pub struct LookupTableGenerator {
row: usize,
lut: Arc<Vec<(u16, u16)>>,
@ -154,6 +171,10 @@ pub struct LookupTableGenerator {
}
impl<F: RichField> SimpleGenerator<F> for LookupTableGenerator {
fn id(&self) -> String {
"LookupTableGenerator".to_string()
}
fn dependencies(&self) -> Vec<Target> {
vec![]
}
@ -182,4 +203,28 @@ impl<F: RichField> SimpleGenerator<F> for LookupTableGenerator {
out_buffer.set_target(slot_output_target, F::ZERO);
}
}
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
dst.write_usize(self.row)?;
dst.write_lut(&self.lut)?;
dst.write_usize(self.slot_nb)?;
dst.write_usize(self.num_slots)?;
dst.write_usize(self.last_lut_row)
}
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let row = src.read_usize()?;
let lut = src.read_lut()?;
let slot_nb = src.read_usize()?;
let num_slots = src.read_usize()?;
let last_lut_row = src.read_usize()?;
Ok(Self {
row,
lut: Arc::new(lut),
slot_nb,
num_slots,
last_lut_row,
})
}
}

View File

@ -71,6 +71,8 @@ pub mod default {
use crate::gates::constant::ConstantGate;
use crate::gates::coset_interpolation::CosetInterpolationGate;
use crate::gates::exponentiation::ExponentiationGate;
use crate::gates::lookup::LookupGate;
use crate::gates::lookup_table::LookupTableGate;
use crate::gates::multiplication_extension::MulExtensionGate;
use crate::gates::noop::NoopGate;
use crate::gates::poseidon::PoseidonGate;
@ -92,6 +94,8 @@ pub mod default {
ConstantGate,
CosetInterpolationGate<F, D>,
ExponentiationGate<F, D>,
LookupGate,
LookupTableGate,
MulExtensionGate<D>,
NoopGate,
PoseidonMdsGate<F, D>,

View File

@ -111,6 +111,8 @@ pub mod default {
use crate::gates::base_sum::BaseSplitGenerator;
use crate::gates::coset_interpolation::InterpolationGenerator;
use crate::gates::exponentiation::ExponentiationGenerator;
use crate::gates::lookup::LookupGenerator;
use crate::gates::lookup_table::LookupTableGenerator;
use crate::gates::multiplication_extension::MulExtensionGenerator;
use crate::gates::poseidon::PoseidonGenerator;
use crate::gates::poseidon_mds::PoseidonMdsGenerator;
@ -147,6 +149,8 @@ pub mod default {
EqualityGenerator,
ExponentiationGenerator<F, D>,
InterpolationGenerator<F, D>,
LookupGenerator,
LookupTableGenerator,
LowHighGenerator,
MulExtensionGenerator<F, D>,
NonzeroTestGenerator,