Skip to content

Commit f3bc38f

Browse files
committed
added serialization support for gates and gadgets
1 parent a34a23f commit f3bc38f

File tree

9 files changed

+210
-29
lines changed

9 files changed

+210
-29
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ edition = "2021"
1010
anyhow = { version = "1.0.40", default-features = false }
1111
itertools = { version = "0.10.0", default-features = false }
1212
num = { version = "0.4", default-features = false }
13-
plonky2 = { version = "0.1.2", default-features = false }
13+
plonky2 = { git = "https://github.com/mir-protocol/plonky2.git", default-features = false }
1414

1515
[dev-dependencies]
16-
plonky2 = { version = "0.1.2", default-features = false, features = ["gate_testing"] }
16+
plonky2 = { git = "https://github.com/mir-protocol/plonky2.git", features = ["gate_testing"] }
1717
rand = { version = "0.8.4", default-features = false, features = ["getrandom"] }

src/gadgets/arithmetic_u32.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
use alloc::string::{String, ToString};
12
use alloc::vec;
23
use alloc::vec::Vec;
4+
use plonky2::util::serialization::{IoResult, Buffer, Read, Write};
35
use core::marker::PhantomData;
46

57
use plonky2::field::extension::Extendable;
@@ -12,6 +14,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder;
1214
use crate::gates::add_many_u32::U32AddManyGate;
1315
use crate::gates::arithmetic_u32::U32ArithmeticGate;
1416
use crate::gates::subtraction_u32::U32SubtractionGate;
17+
use crate::serialization::{WriteU32, ReadU32};
1518
use crate::witness::GeneratedValuesU32;
1619

1720
#[derive(Clone, Copy, Debug)]
@@ -241,6 +244,23 @@ struct SplitToU32Generator<F: RichField + Extendable<D>, const D: usize> {
241244
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
242245
for SplitToU32Generator<F, D>
243246
{
247+
fn id(&self) -> String {
248+
"SplitToU32Generator".to_string()
249+
}
250+
251+
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
252+
dst.write_target(self.x)?;
253+
dst.write_target_u32(self.low)?;
254+
dst.write_target_u32(self.high)
255+
}
256+
257+
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
258+
let x = src.read_target()?;
259+
let low = src.read_target_u32()?;
260+
let high = src.read_target_u32()?;
261+
Ok(Self { x, low, high, _phantom: PhantomData })
262+
}
263+
244264
fn dependencies(&self) -> Vec<Target> {
245265
vec![self.x]
246266
}
@@ -254,6 +274,7 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
254274
out_buffer.set_u32_target(self.low, low);
255275
out_buffer.set_u32_target(self.high, high);
256276
}
277+
257278
}
258279

259280
#[cfg(test)]

src/gates/add_many_u32.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use alloc::boxed::Box;
21
use alloc::format;
3-
use alloc::string::String;
2+
use alloc::string::{String, ToString};
43
use alloc::vec::Vec;
4+
use plonky2::util::serialization::{IoResult, Buffer, Write, Read};
55
use core::marker::PhantomData;
66

77
use itertools::unfold;
@@ -11,7 +11,7 @@ use plonky2::gates::gate::Gate;
1111
use plonky2::gates::util::StridedConstraintConsumer;
1212
use plonky2::hash::hash_types::RichField;
1313
use plonky2::iop::ext_target::ExtensionTarget;
14-
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
14+
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
1515
use plonky2::iop::target::Target;
1616
use plonky2::iop::wire::Wire;
1717
use plonky2::iop::witness::{PartitionWitness, Witness, WitnessWrite};
@@ -91,6 +91,17 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32AddManyGate
9191
format!("{self:?}")
9292
}
9393

94+
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
95+
dst.write_usize(self.num_addends);
96+
dst.write_usize(self.num_ops)
97+
}
98+
99+
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
100+
let num_addends = src.read_usize()?;
101+
let num_ops = src.read_usize()?;
102+
Ok(Self { num_addends, num_ops, _phantom: PhantomData })
103+
}
104+
94105
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
95106
let mut constraints = Vec::with_capacity(self.num_constraints());
96107
for i in 0..self.num_ops {
@@ -236,19 +247,18 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32AddManyGate
236247
constraints
237248
}
238249

239-
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
250+
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
240251
(0..self.num_ops)
241252
.map(|i| {
242-
let g: Box<dyn WitnessGenerator<F>> = Box::new(
253+
WitnessGeneratorRef::new(
243254
U32AddManyGenerator {
244255
gate: *self,
245256
row,
246257
i,
247258
_phantom: PhantomData,
248259
}
249260
.adapter(),
250-
);
251-
g
261+
)
252262
})
253263
.collect()
254264
}
@@ -281,6 +291,23 @@ struct U32AddManyGenerator<F: RichField + Extendable<D>, const D: usize> {
281291
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
282292
for U32AddManyGenerator<F, D>
283293
{
294+
fn id(&self) -> String {
295+
"U32AddManyGenerator".to_string()
296+
}
297+
298+
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
299+
self.gate.serialize(dst)?;
300+
dst.write_usize(self.row)?;
301+
dst.write_usize(self.i)
302+
}
303+
304+
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
305+
let gate = U32AddManyGate::deserialize(src)?;
306+
let row = src.read_usize()?;
307+
let i = src.read_usize()?;
308+
Ok(Self { gate, row, i, _phantom: PhantomData })
309+
}
310+
284311
fn dependencies(&self) -> Vec<Target> {
285312
let local_target = |column| Target::wire(self.row, column);
286313

src/gates/arithmetic_u32.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use alloc::boxed::Box;
2-
use alloc::string::String;
1+
use alloc::string::{String, ToString};
32
use alloc::vec::Vec;
43
use alloc::{format, vec};
4+
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
55
use core::marker::PhantomData;
66

77
use itertools::unfold;
@@ -13,7 +13,7 @@ use plonky2::gates::packed_util::PackedEvaluableBase;
1313
use plonky2::gates::util::StridedConstraintConsumer;
1414
use plonky2::hash::hash_types::RichField;
1515
use plonky2::iop::ext_target::ExtensionTarget;
16-
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
16+
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
1717
use plonky2::iop::target::Target;
1818
use plonky2::iop::wire::Wire;
1919
use plonky2::iop::witness::{PartitionWitness, Witness, WitnessWrite};
@@ -93,6 +93,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32ArithmeticG
9393
format!("{self:?}")
9494
}
9595

96+
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
97+
dst.write_usize(self.num_ops)
98+
}
99+
100+
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
101+
let num_ops = src.read_usize()?;
102+
Ok(Self { num_ops, _phantom: PhantomData })
103+
}
104+
96105
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
97106
let mut constraints = Vec::with_capacity(self.num_constraints());
98107
for i in 0..self.num_ops {
@@ -240,10 +249,10 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32ArithmeticG
240249
constraints
241250
}
242251

243-
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
252+
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
244253
(0..self.num_ops)
245254
.map(|i| {
246-
let g: Box<dyn WitnessGenerator<F>> = Box::new(
255+
let g: WitnessGeneratorRef<F> = WitnessGeneratorRef::new(
247256
U32ArithmeticGenerator {
248257
gate: *self,
249258
row,
@@ -350,6 +359,10 @@ struct U32ArithmeticGenerator<F: RichField + Extendable<D>, const D: usize> {
350359
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
351360
for U32ArithmeticGenerator<F, D>
352361
{
362+
fn id(&self) -> String {
363+
"U32ArithmeticGenerator".to_string()
364+
}
365+
353366
fn dependencies(&self) -> Vec<Target> {
354367
let local_target = |column| Target::wire(self.row, column);
355368

@@ -411,6 +424,19 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
411424
out_buffer.set_wire(wire, output_limb);
412425
}
413426
}
427+
428+
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
429+
self.gate.serialize(dst)?;
430+
dst.write_usize(self.row)?;
431+
dst.write_usize(self.i)
432+
}
433+
434+
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
435+
let gate = U32ArithmeticGate::deserialize(src)?;
436+
let row = src.read_usize()?;
437+
let i = src.read_usize()?;
438+
Ok(Self { gate, row, i, _phantom: PhantomData })
439+
}
414440
}
415441

416442
#[cfg(test)]

src/gates/comparison.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use alloc::boxed::Box;
2-
use alloc::string::String;
1+
use alloc::string::{String, ToString};
32
use alloc::vec::Vec;
43
use alloc::{format, vec};
4+
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
55
use core::marker::PhantomData;
66

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

101+
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
102+
dst.write_usize(self.num_bits)?;
103+
dst.write_usize(self.num_chunks)?;
104+
Ok(())
105+
}
106+
107+
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
108+
let num_bits = src.read_usize()?;
109+
let num_chunks = src.read_usize()?;
110+
Ok(Self { num_bits, num_chunks, _phantom: PhantomData })
111+
}
112+
101113
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
102114
let mut constraints = Vec::with_capacity(self.num_constraints());
103115

@@ -287,12 +299,12 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ComparisonGate
287299
constraints
288300
}
289301

290-
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
302+
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
291303
let gen = ComparisonGenerator::<F, D> {
292304
row,
293305
gate: self.clone(),
294306
};
295-
vec![Box::new(gen.adapter())]
307+
vec![WitnessGeneratorRef::new(gen.adapter())]
296308
}
297309

298310
fn num_wires(&self) -> usize {
@@ -404,6 +416,10 @@ struct ComparisonGenerator<F: RichField + Extendable<D>, const D: usize> {
404416
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
405417
for ComparisonGenerator<F, D>
406418
{
419+
fn id(&self) -> String {
420+
"ComparisonGenerator".to_string()
421+
}
422+
407423
fn dependencies(&self) -> Vec<Target> {
408424
let local_target = |column| Target::wire(self.row, column);
409425

@@ -512,6 +528,18 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
512528
);
513529
}
514530
}
531+
532+
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
533+
dst.write_usize(self.row)?;
534+
self.gate.serialize(dst)
535+
}
536+
537+
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
538+
let row = src.read_usize()?;
539+
let gate = ComparisonGate::deserialize(src)?;
540+
Ok(Self { row, gate })
541+
}
542+
515543
}
516544

517545
#[cfg(test)]

src/gates/range_check_u32.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use alloc::boxed::Box;
2-
use alloc::string::String;
1+
use alloc::string::{String, ToString};
32
use alloc::vec::Vec;
43
use alloc::{format, vec};
4+
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
55
use core::marker::PhantomData;
66

77
use plonky2::field::extension::Extendable;
@@ -10,7 +10,7 @@ use plonky2::gates::gate::Gate;
1010
use plonky2::gates::util::StridedConstraintConsumer;
1111
use plonky2::hash::hash_types::RichField;
1212
use plonky2::iop::ext_target::ExtensionTarget;
13-
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
13+
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
1414
use plonky2::iop::target::Target;
1515
use plonky2::iop::witness::{PartitionWitness, Witness, WitnessWrite};
1616
use plonky2::plonk::circuit_builder::CircuitBuilder;
@@ -55,6 +55,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32RangeCheckG
5555
format!("{self:?}")
5656
}
5757

58+
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
59+
dst.write_usize(self.num_input_limbs)
60+
}
61+
62+
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
63+
let num_input_limbs = src.read_usize()?;
64+
Ok(Self { num_input_limbs, _phantom: PhantomData })
65+
}
66+
5867
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
5968
let mut constraints = Vec::with_capacity(self.num_constraints());
6069

@@ -138,9 +147,9 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32RangeCheckG
138147
constraints
139148
}
140149

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

146155
fn num_wires(&self) -> usize {
@@ -171,6 +180,10 @@ pub struct U32RangeCheckGenerator<F: RichField + Extendable<D>, const D: usize>
171180
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
172181
for U32RangeCheckGenerator<F, D>
173182
{
183+
fn id(&self) -> String {
184+
"U32RangeCheckGenerator".to_string()
185+
}
186+
174187
fn dependencies(&self) -> Vec<Target> {
175188
let num_input_limbs = self.gate.num_input_limbs;
176189
(0..num_input_limbs)
@@ -201,6 +214,18 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
201214
}
202215
}
203216
}
217+
218+
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
219+
dst.write_usize(self.row)?;
220+
self.gate.serialize(dst)
221+
}
222+
223+
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
224+
let row = src.read_usize()?;
225+
let gate = U32RangeCheckGate::deserialize(src)?;
226+
Ok(Self { row, gate })
227+
}
228+
204229
}
205230

206231
#[cfg(test)]

0 commit comments

Comments
 (0)