Skip to content

Commit

Permalink
Merge pull request #1 from succinctlabs/kevjue/serialize
Browse files Browse the repository at this point in the history
Add serialization support
  • Loading branch information
npwardberkeley authored May 19, 2023
2 parents a34a23f + dde8b31 commit 945ff60
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 29 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ edition = "2021"
anyhow = { version = "1.0.40", default-features = false }
itertools = { version = "0.10.0", default-features = false }
num = { version = "0.4", default-features = false }
plonky2 = { version = "0.1.2", default-features = false }
plonky2 = { git = "https://github.com/mir-protocol/plonky2.git" }

[dev-dependencies]
plonky2 = { version = "0.1.2", default-features = false, features = ["gate_testing"] }
plonky2 = { git = "https://github.com/mir-protocol/plonky2.git", default-features = false, features = ["gate_testing"] }
rand = { version = "0.8.4", default-features = false, features = ["getrandom"] }
20 changes: 20 additions & 0 deletions src/gadgets/arithmetic_u32.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use alloc::string::{String, ToString};
use alloc::vec;
use alloc::vec::Vec;
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
use core::marker::PhantomData;

use plonky2::field::extension::Extendable;
Expand All @@ -12,6 +14,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder;
use crate::gates::add_many_u32::U32AddManyGate;
use crate::gates::arithmetic_u32::U32ArithmeticGate;
use crate::gates::subtraction_u32::U32SubtractionGate;
use crate::serialization::{ReadU32, WriteU32};
use crate::witness::GeneratedValuesU32;

#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -241,6 +244,23 @@ struct SplitToU32Generator<F: RichField + Extendable<D>, const D: usize> {
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
for SplitToU32Generator<F, D>
{
fn id(&self) -> String {
"SplitToU32Generator".to_string()
}

fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
dst.write_target(self.x)?;
dst.write_target_u32(self.low)?;
dst.write_target_u32(self.high)
}

fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let x = src.read_target()?;
let low = src.read_target_u32()?;
let high = src.read_target_u32()?;
Ok(Self { x, low, high, _phantom: PhantomData })
}

fn dependencies(&self) -> Vec<Target> {
vec![self.x]
}
Expand Down
41 changes: 34 additions & 7 deletions src/gates/add_many_u32.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloc::boxed::Box;
use alloc::format;
use alloc::string::String;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
use core::marker::PhantomData;

use itertools::unfold;
Expand All @@ -11,7 +11,7 @@ use plonky2::gates::gate::Gate;
use plonky2::gates::util::StridedConstraintConsumer;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
use plonky2::iop::target::Target;
use plonky2::iop::wire::Wire;
use plonky2::iop::witness::{PartitionWitness, Witness, WitnessWrite};
Expand Down Expand Up @@ -91,6 +91,17 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32AddManyGate
format!("{self:?}")
}

fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
dst.write_usize(self.num_addends)?;
dst.write_usize(self.num_ops)
}

fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let num_addends = src.read_usize()?;
let num_ops = src.read_usize()?;
Ok(Self { num_addends, num_ops, _phantom: PhantomData })
}

fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
let mut constraints = Vec::with_capacity(self.num_constraints());
for i in 0..self.num_ops {
Expand Down Expand Up @@ -236,19 +247,18 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32AddManyGate
constraints
}

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_ops)
.map(|i| {
let g: Box<dyn WitnessGenerator<F>> = Box::new(
WitnessGeneratorRef::new(
U32AddManyGenerator {
gate: *self,
row,
i,
_phantom: PhantomData,
}
.adapter(),
);
g
)
})
.collect()
}
Expand Down Expand Up @@ -281,6 +291,23 @@ struct U32AddManyGenerator<F: RichField + Extendable<D>, const D: usize> {
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
for U32AddManyGenerator<F, D>
{
fn id(&self) -> String {
"U32AddManyGenerator".to_string()
}

fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
self.gate.serialize(dst)?;
dst.write_usize(self.row)?;
dst.write_usize(self.i)
}

fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let gate = U32AddManyGate::deserialize(src)?;
let row = src.read_usize()?;
let i = src.read_usize()?;
Ok(Self { gate, row, i, _phantom: PhantomData })
}

fn dependencies(&self) -> Vec<Target> {
let local_target = |column| Target::wire(self.row, column);

Expand Down
36 changes: 31 additions & 5 deletions src/gates/arithmetic_u32.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloc::boxed::Box;
use alloc::string::String;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use alloc::{format, vec};
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
use core::marker::PhantomData;

use itertools::unfold;
Expand All @@ -13,7 +13,7 @@ use plonky2::gates::packed_util::PackedEvaluableBase;
use plonky2::gates::util::StridedConstraintConsumer;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
use plonky2::iop::target::Target;
use plonky2::iop::wire::Wire;
use plonky2::iop::witness::{PartitionWitness, Witness, WitnessWrite};
Expand Down Expand Up @@ -93,6 +93,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32ArithmeticG
format!("{self:?}")
}

fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
dst.write_usize(self.num_ops)
}

fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let num_ops = src.read_usize()?;
Ok(Self { num_ops, _phantom: PhantomData })
}

fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
let mut constraints = Vec::with_capacity(self.num_constraints());
for i in 0..self.num_ops {
Expand Down Expand Up @@ -240,10 +249,10 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32ArithmeticG
constraints
}

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_ops)
.map(|i| {
let g: Box<dyn WitnessGenerator<F>> = Box::new(
let g: WitnessGeneratorRef<F> = WitnessGeneratorRef::new(
U32ArithmeticGenerator {
gate: *self,
row,
Expand Down Expand Up @@ -350,6 +359,10 @@ struct U32ArithmeticGenerator<F: RichField + Extendable<D>, const D: usize> {
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
for U32ArithmeticGenerator<F, D>
{
fn id(&self) -> String {
"U32ArithmeticGenerator".to_string()
}

fn dependencies(&self) -> Vec<Target> {
let local_target = |column| Target::wire(self.row, column);

Expand Down Expand Up @@ -411,6 +424,19 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
out_buffer.set_wire(wire, output_limb);
}
}

fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
self.gate.serialize(dst)?;
dst.write_usize(self.row)?;
dst.write_usize(self.i)
}

fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let gate = U32ArithmeticGate::deserialize(src)?;
let row = src.read_usize()?;
let i = src.read_usize()?;
Ok(Self { gate, row, i, _phantom: PhantomData })
}
}

#[cfg(test)]
Expand Down
38 changes: 33 additions & 5 deletions src/gates/comparison.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloc::boxed::Box;
use alloc::string::String;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use alloc::{format, vec};
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
use core::marker::PhantomData;

use plonky2::field::extension::Extendable;
Expand All @@ -12,7 +12,7 @@ use plonky2::gates::packed_util::PackedEvaluableBase;
use plonky2::gates::util::StridedConstraintConsumer;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
use plonky2::iop::target::Target;
use plonky2::iop::wire::Wire;
use plonky2::iop::witness::{PartitionWitness, Witness, WitnessWrite};
Expand Down Expand Up @@ -98,6 +98,18 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ComparisonGate
format!("{self:?}<D={D}>")
}

fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
dst.write_usize(self.num_bits)?;
dst.write_usize(self.num_chunks)?;
Ok(())
}

fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let num_bits = src.read_usize()?;
let num_chunks = src.read_usize()?;
Ok(Self { num_bits, num_chunks, _phantom: PhantomData })
}

fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
let mut constraints = Vec::with_capacity(self.num_constraints());

Expand Down Expand Up @@ -287,12 +299,12 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ComparisonGate
constraints
}

fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
let gen = ComparisonGenerator::<F, D> {
row,
gate: self.clone(),
};
vec![Box::new(gen.adapter())]
vec![WitnessGeneratorRef::new(gen.adapter())]
}

fn num_wires(&self) -> usize {
Expand Down Expand Up @@ -404,6 +416,10 @@ struct ComparisonGenerator<F: RichField + Extendable<D>, const D: usize> {
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
for ComparisonGenerator<F, D>
{
fn id(&self) -> String {
"ComparisonGenerator".to_string()
}

fn dependencies(&self) -> Vec<Target> {
let local_target = |column| Target::wire(self.row, column);

Expand Down Expand Up @@ -512,6 +528,18 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
);
}
}

fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
dst.write_usize(self.row)?;
self.gate.serialize(dst)
}

fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let row = src.read_usize()?;
let gate = ComparisonGate::deserialize(src)?;
Ok(Self { row, gate })
}

}

#[cfg(test)]
Expand Down
35 changes: 30 additions & 5 deletions src/gates/range_check_u32.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloc::boxed::Box;
use alloc::string::String;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use alloc::{format, vec};
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
use core::marker::PhantomData;

use plonky2::field::extension::Extendable;
Expand All @@ -10,7 +10,7 @@ use plonky2::gates::gate::Gate;
use plonky2::gates::util::StridedConstraintConsumer;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
use plonky2::iop::target::Target;
use plonky2::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use plonky2::plonk::circuit_builder::CircuitBuilder;
Expand Down Expand Up @@ -55,6 +55,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32RangeCheckG
format!("{self:?}")
}

fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
dst.write_usize(self.num_input_limbs)
}

fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let num_input_limbs = src.read_usize()?;
Ok(Self { num_input_limbs, _phantom: PhantomData })
}

fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
let mut constraints = Vec::with_capacity(self.num_constraints());

Expand Down Expand Up @@ -138,9 +147,9 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32RangeCheckG
constraints
}

fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
let gen = U32RangeCheckGenerator { gate: *self, row };
vec![Box::new(gen.adapter())]
vec![WitnessGeneratorRef::new(gen.adapter())]
}

fn num_wires(&self) -> usize {
Expand Down Expand Up @@ -171,6 +180,10 @@ pub struct U32RangeCheckGenerator<F: RichField + Extendable<D>, const D: usize>
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
for U32RangeCheckGenerator<F, D>
{
fn id(&self) -> String {
"U32RangeCheckGenerator".to_string()
}

fn dependencies(&self) -> Vec<Target> {
let num_input_limbs = self.gate.num_input_limbs;
(0..num_input_limbs)
Expand Down Expand Up @@ -201,6 +214,18 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
}
}
}

fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
self.gate.serialize(dst)?;
dst.write_usize(self.row)
}

fn deserialize(src: &mut Buffer) -> IoResult<Self> {
let gate = U32RangeCheckGate::deserialize(src)?;
let row = src.read_usize()?;
Ok(Self { row, gate })
}

}

#[cfg(test)]
Expand Down
Loading

0 comments on commit 945ff60

Please sign in to comment.