Merge pull request #1111 from topos-protocol/lookup_serial

Lookup serialization
This commit is contained in:
Nicholas Ward 2023-07-24 13:29:10 -07:00 committed by GitHub
commit bfa7ab369e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 533 additions and 374 deletions

View File

@ -837,6 +837,7 @@ where
buffer.write_prover_only_circuit_data( buffer.write_prover_only_circuit_data(
&wrapper.circuit.prover_only, &wrapper.circuit.prover_only,
generator_serializer, generator_serializer,
&wrapper.circuit.common,
)?; )?;
buffer.write_verifier_only_circuit_data(&wrapper.circuit.verifier_only)?; buffer.write_verifier_only_circuit_data(&wrapper.circuit.verifier_only)?;
buffer.write_target_proof_with_public_inputs(&wrapper.proof_with_pis_target)?; buffer.write_target_proof_with_public_inputs(&wrapper.proof_with_pis_target)?;

View File

@ -248,18 +248,18 @@ where
fn test_serialization<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>( fn test_serialization<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>(
proof: &ProofWithPublicInputs<F, C, D>, proof: &ProofWithPublicInputs<F, C, D>,
vd: &VerifierOnlyCircuitData<C, D>, vd: &VerifierOnlyCircuitData<C, D>,
cd: &CommonCircuitData<F, D>, common_data: &CommonCircuitData<F, D>,
) -> Result<()> { ) -> Result<()> {
let proof_bytes = proof.to_bytes(); let proof_bytes = proof.to_bytes();
info!("Proof length: {} bytes", proof_bytes.len()); info!("Proof length: {} bytes", proof_bytes.len());
let proof_from_bytes = ProofWithPublicInputs::from_bytes(proof_bytes, cd)?; let proof_from_bytes = ProofWithPublicInputs::from_bytes(proof_bytes, common_data)?;
assert_eq!(proof, &proof_from_bytes); assert_eq!(proof, &proof_from_bytes);
let now = std::time::Instant::now(); let now = std::time::Instant::now();
let compressed_proof = proof.clone().compress(&vd.circuit_digest, cd)?; let compressed_proof = proof.clone().compress(&vd.circuit_digest, common_data)?;
let decompressed_compressed_proof = compressed_proof let decompressed_compressed_proof = compressed_proof
.clone() .clone()
.decompress(&vd.circuit_digest, cd)?; .decompress(&vd.circuit_digest, common_data)?;
info!("{:.4}s to compress proof", now.elapsed().as_secs_f64()); info!("{:.4}s to compress proof", now.elapsed().as_secs_f64());
assert_eq!(proof, &decompressed_compressed_proof); assert_eq!(proof, &decompressed_compressed_proof);
@ -269,11 +269,11 @@ fn test_serialization<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>,
compressed_proof_bytes.len() compressed_proof_bytes.len()
); );
let compressed_proof_from_bytes = let compressed_proof_from_bytes =
CompressedProofWithPublicInputs::from_bytes(compressed_proof_bytes, cd)?; CompressedProofWithPublicInputs::from_bytes(compressed_proof_bytes, common_data)?;
assert_eq!(compressed_proof, compressed_proof_from_bytes); assert_eq!(compressed_proof, compressed_proof_from_bytes);
let gate_serializer = DefaultGateSerializer; let gate_serializer = DefaultGateSerializer;
let common_data_bytes = cd let common_data_bytes = common_data
.to_bytes(&gate_serializer) .to_bytes(&gate_serializer)
.map_err(|_| anyhow::Error::msg("CommonCircuitData serialization failed."))?; .map_err(|_| anyhow::Error::msg("CommonCircuitData serialization failed."))?;
info!( info!(
@ -283,7 +283,7 @@ fn test_serialization<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>,
let common_data_from_bytes = let common_data_from_bytes =
CommonCircuitData::<F, D>::from_bytes(common_data_bytes, &gate_serializer) CommonCircuitData::<F, D>::from_bytes(common_data_bytes, &gate_serializer)
.map_err(|_| anyhow::Error::msg("CommonCircuitData deserialization failed."))?; .map_err(|_| anyhow::Error::msg("CommonCircuitData deserialization failed."))?;
assert_eq!(cd, &common_data_from_bytes); assert_eq!(common_data, &common_data_from_bytes);
Ok(()) Ok(())
} }
@ -312,35 +312,35 @@ pub fn benchmark_function(
}; };
// Start with a dummy proof of specified size // Start with a dummy proof of specified size
let inner = dummy_proof_function(config, log2_inner_size)?; let inner = dummy_proof_function(config, log2_inner_size)?;
let (_, _, cd) = &inner; let (_, _, common_data) = &inner;
info!( info!(
"Initial {} degree {} = 2^{}", "Initial {} degree {} = 2^{}",
name, name,
cd.degree(), common_data.degree(),
cd.degree_bits() common_data.degree_bits()
); );
// Recursively verify the proof // Recursively verify the proof
let middle = recursive_proof::<F, C, C, D>(&inner, config, None)?; let middle = recursive_proof::<F, C, C, D>(&inner, config, None)?;
let (_, _, cd) = &middle; let (_, _, common_data) = &middle;
info!( info!(
"Single recursion {} degree {} = 2^{}", "Single recursion {} degree {} = 2^{}",
name, name,
cd.degree(), common_data.degree(),
cd.degree_bits() common_data.degree_bits()
); );
// Add a second layer of recursion to shrink the proof size further // Add a second layer of recursion to shrink the proof size further
let outer = recursive_proof::<F, C, C, D>(&middle, config, None)?; let outer = recursive_proof::<F, C, C, D>(&middle, config, None)?;
let (proof, vd, cd) = &outer; let (proof, vd, common_data) = &outer;
info!( info!(
"Double recursion {} degree {} = 2^{}", "Double recursion {} degree {} = 2^{}",
name, name,
cd.degree(), common_data.degree(),
cd.degree_bits() common_data.degree_bits()
); );
test_serialization(proof, vd, cd)?; test_serialization(proof, vd, common_data)?;
Ok(()) Ok(())
} }

View File

@ -14,7 +14,7 @@ use plonky2::iop::generator::{
use plonky2::iop::target::Target; use plonky2::iop::target::Target;
use plonky2::iop::witness::{PartialWitness, PartitionWitness, Witness, WitnessWrite}; use plonky2::iop::witness::{PartialWitness, PartitionWitness, Witness, WitnessWrite};
use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData}; use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData};
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, PoseidonGoldilocksConfig}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, PoseidonGoldilocksConfig};
use plonky2::recursion::dummy_circuit::DummyProofGenerator; use plonky2::recursion::dummy_circuit::DummyProofGenerator;
use plonky2::util::serialization::{ use plonky2::util::serialization::{
@ -32,7 +32,7 @@ struct SquareRootGenerator<F: RichField + Extendable<D>, const D: usize> {
_phantom: PhantomData<F>, _phantom: PhantomData<F>,
} }
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D>
for SquareRootGenerator<F, D> for SquareRootGenerator<F, D>
{ {
fn id(&self) -> String { fn id(&self) -> String {
@ -52,12 +52,12 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
out_buffer.set_target(self.x, x); out_buffer.set_target(self.x, x);
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target(self.x)?; dst.write_target(self.x)?;
dst.write_target(self.x_squared) dst.write_target(self.x_squared)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let x = src.read_target()?; let x = src.read_target()?;
let x_squared = src.read_target()?; let x_squared = src.read_target()?;
Ok(Self { Ok(Self {

View File

@ -11,6 +11,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::{BoolTarget, Target}; use crate::iop::target::{BoolTarget, Target};
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> { impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
@ -379,7 +380,7 @@ pub struct EqualityGenerator {
inv: Target, inv: Target,
} }
impl<F: RichField> SimpleGenerator<F> for EqualityGenerator { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for EqualityGenerator {
fn id(&self) -> String { fn id(&self) -> String {
"EqualityGenerator".to_string() "EqualityGenerator".to_string()
} }
@ -398,14 +399,14 @@ impl<F: RichField> SimpleGenerator<F> for EqualityGenerator {
out_buffer.set_target(self.inv, inv); out_buffer.set_target(self.inv, inv);
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target(self.x)?; dst.write_target(self.x)?;
dst.write_target(self.y)?; dst.write_target(self.y)?;
dst.write_target_bool(self.equal)?; dst.write_target_bool(self.equal)?;
dst.write_target(self.inv) dst.write_target(self.inv)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let x = src.read_target()?; let x = src.read_target()?;
let y = src.read_target()?; let y = src.read_target()?;
let equal = src.read_target_bool()?; let equal = src.read_target_bool()?;

View File

@ -12,6 +12,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::util::bits_u64; use crate::util::bits_u64;
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
@ -501,7 +502,7 @@ pub struct QuotientGeneratorExtension<const D: usize> {
quotient: ExtensionTarget<D>, quotient: ExtensionTarget<D>,
} }
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D>
for QuotientGeneratorExtension<D> for QuotientGeneratorExtension<D>
{ {
fn id(&self) -> String { fn id(&self) -> String {
@ -521,13 +522,13 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
out_buffer.set_extension_target(self.quotient, quotient) out_buffer.set_extension_target(self.quotient, quotient)
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target_ext(self.numerator)?; dst.write_target_ext(self.numerator)?;
dst.write_target_ext(self.denominator)?; dst.write_target_ext(self.denominator)?;
dst.write_target_ext(self.quotient) dst.write_target_ext(self.quotient)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let numerator = src.read_target_ext()?; let numerator = src.read_target_ext()?;
let denominator = src.read_target_ext()?; let denominator = src.read_target_ext()?;
let quotient = src.read_target_ext()?; let quotient = src.read_target_ext()?;

View File

@ -7,6 +7,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::{BoolTarget, Target}; use crate::iop::target::{BoolTarget, Target};
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> { impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
@ -60,7 +61,7 @@ pub struct LowHighGenerator {
high: Target, high: Target,
} }
impl<F: RichField> SimpleGenerator<F> for LowHighGenerator { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for LowHighGenerator {
fn id(&self) -> String { fn id(&self) -> String {
"LowHighGenerator".to_string() "LowHighGenerator".to_string()
} }
@ -78,14 +79,14 @@ impl<F: RichField> SimpleGenerator<F> for LowHighGenerator {
out_buffer.set_target(self.high, F::from_canonical_u64(high)); out_buffer.set_target(self.high, F::from_canonical_u64(high));
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target(self.integer)?; dst.write_target(self.integer)?;
dst.write_usize(self.n_log)?; dst.write_usize(self.n_log)?;
dst.write_target(self.low)?; dst.write_target(self.low)?;
dst.write_target(self.high) dst.write_target(self.high)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let integer = src.read_target()?; let integer = src.read_target()?;
let n_log = src.read_usize()?; let n_log = src.read_usize()?;
let low = src.read_target()?; let low = src.read_target()?;

View File

@ -5,13 +5,13 @@ use core::borrow::Borrow;
use itertools::Itertools; use itertools::Itertools;
use crate::field::extension::Extendable; use crate::field::extension::Extendable;
use crate::field::types::Field;
use crate::gates::base_sum::BaseSumGate; use crate::gates::base_sum::BaseSumGate;
use crate::hash::hash_types::RichField; use crate::hash::hash_types::RichField;
use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::{BoolTarget, Target}; use crate::iop::target::{BoolTarget, Target};
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::util::log_floor; use crate::util::log_floor;
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
@ -86,7 +86,9 @@ pub struct BaseSumGenerator<const B: usize> {
limbs: Vec<BoolTarget>, limbs: Vec<BoolTarget>,
} }
impl<F: Field, const B: usize> SimpleGenerator<F> for BaseSumGenerator<B> { impl<F: RichField + Extendable<D>, const B: usize, const D: usize> SimpleGenerator<F, D>
for BaseSumGenerator<B>
{
fn id(&self) -> String { fn id(&self) -> String {
"BaseSumGenerator".to_string() "BaseSumGenerator".to_string()
} }
@ -108,12 +110,12 @@ impl<F: Field, const B: usize> SimpleGenerator<F> for BaseSumGenerator<B> {
out_buffer.set_target(Target::wire(self.row, BaseSumGate::<B>::WIRE_SUM), sum); out_buffer.set_target(Target::wire(self.row, BaseSumGate::<B>::WIRE_SUM), sum);
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
dst.write_target_bool_vec(&self.limbs) dst.write_target_bool_vec(&self.limbs)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let limbs = src.read_target_bool_vec()?; let limbs = src.read_target_bool_vec()?;
Ok(Self { row, limbs }) Ok(Self { row, limbs })
@ -123,6 +125,7 @@ impl<F: Field, const B: usize> SimpleGenerator<F> for BaseSumGenerator<B> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use anyhow::Result; use anyhow::Result;
use plonky2_field::types::Field;
use rand::rngs::OsRng; use rand::rngs::OsRng;
use rand::Rng; use rand::Rng;

View File

@ -8,6 +8,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::{BoolTarget, Target}; use crate::iop::target::{BoolTarget, Target};
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::util::ceil_div_usize; use crate::util::ceil_div_usize;
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
@ -62,7 +63,7 @@ pub struct SplitGenerator {
bits: Vec<Target>, bits: Vec<Target>,
} }
impl<F: RichField> SimpleGenerator<F> for SplitGenerator { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for SplitGenerator {
fn id(&self) -> String { fn id(&self) -> String {
"SplitGenerator".to_string() "SplitGenerator".to_string()
} }
@ -86,12 +87,12 @@ impl<F: RichField> SimpleGenerator<F> for SplitGenerator {
); );
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target(self.integer)?; dst.write_target(self.integer)?;
dst.write_target_vec(&self.bits) dst.write_target_vec(&self.bits)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let integer = src.read_target()?; let integer = src.read_target()?;
let bits = src.read_target_vec()?; let bits = src.read_target_vec()?;
Ok(Self { integer, bits }) Ok(Self { integer, bits })
@ -105,7 +106,7 @@ pub struct WireSplitGenerator {
num_limbs: usize, num_limbs: usize,
} }
impl<F: RichField> SimpleGenerator<F> for WireSplitGenerator { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for WireSplitGenerator {
fn id(&self) -> String { fn id(&self) -> String {
"WireSplitGenerator".to_string() "WireSplitGenerator".to_string()
} }
@ -141,13 +142,13 @@ impl<F: RichField> SimpleGenerator<F> for WireSplitGenerator {
); );
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target(self.integer)?; dst.write_target(self.integer)?;
dst.write_usize_vec(&self.gates)?; dst.write_usize_vec(&self.gates)?;
dst.write_usize(self.num_limbs) dst.write_usize(self.num_limbs)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let integer = src.read_target()?; let integer = src.read_target()?;
let gates = src.read_usize_vec()?; let gates = src.read_usize_vec()?;
let num_limbs = src.read_usize()?; let num_limbs = src.read_usize()?;

View File

@ -13,7 +13,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRe
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
use crate::plonk::vars::{ use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked, EvaluationVarsBasePacked,
@ -60,11 +60,11 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticGate
format!("{self:?}") format!("{self:?}")
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_ops) dst.write_usize(self.num_ops)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let num_ops = src.read_usize()?; let num_ops = src.read_usize()?;
Ok(Self { num_ops }) Ok(Self { num_ops })
} }
@ -126,7 +126,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticGate
constraints constraints
} }
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
(0..self.num_ops) (0..self.num_ops)
.map(|i| { .map(|i| {
WitnessGeneratorRef::new( WitnessGeneratorRef::new(
@ -188,7 +188,7 @@ pub struct ArithmeticBaseGenerator<F: RichField + Extendable<D>, const D: usize>
i: usize, i: usize,
} }
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D>
for ArithmeticBaseGenerator<F, D> for ArithmeticBaseGenerator<F, D>
{ {
fn id(&self) -> String { fn id(&self) -> String {
@ -221,14 +221,14 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
out_buffer.set_target(output_target, computed_output) out_buffer.set_target(output_target, computed_output)
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
dst.write_field(self.const_0)?; dst.write_field(self.const_0)?;
dst.write_field(self.const_1)?; dst.write_field(self.const_1)?;
dst.write_usize(self.i) dst.write_usize(self.i)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let const_0 = src.read_field()?; let const_0 = src.read_field()?;
let const_1 = src.read_field()?; let const_1 = src.read_field()?;

View File

@ -12,7 +12,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRe
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
@ -56,11 +56,11 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExte
format!("{self:?}") format!("{self:?}")
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_ops) dst.write_usize(self.num_ops)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let num_ops = src.read_usize()?; let num_ops = src.read_usize()?;
Ok(Self { num_ops }) Ok(Self { num_ops })
} }
@ -131,7 +131,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExte
constraints constraints
} }
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
(0..self.num_ops) (0..self.num_ops)
.map(|i| { .map(|i| {
WitnessGeneratorRef::new( WitnessGeneratorRef::new(
@ -172,7 +172,7 @@ pub struct ArithmeticExtensionGenerator<F: RichField + Extendable<D>, const D: u
i: usize, i: usize,
} }
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D>
for ArithmeticExtensionGenerator<F, D> for ArithmeticExtensionGenerator<F, D>
{ {
fn id(&self) -> String { fn id(&self) -> String {
@ -214,14 +214,14 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
out_buffer.set_extension_target(output_target, computed_output) out_buffer.set_extension_target(output_target, computed_output)
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
dst.write_field(self.const_0)?; dst.write_field(self.const_0)?;
dst.write_field(self.const_1)?; dst.write_field(self.const_1)?;
dst.write_usize(self.i) dst.write_usize(self.i)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let const_0 = src.read_field()?; let const_0 = src.read_field()?;
let const_1 = src.read_field()?; let const_1 = src.read_field()?;

View File

@ -15,7 +15,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRe
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
use crate::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_circuit}; use crate::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_circuit};
use crate::plonk::vars::{ use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
@ -55,11 +55,11 @@ impl<F: RichField + Extendable<D>, const D: usize, const B: usize> Gate<F, D> fo
format!("{self:?} + Base: {B}") format!("{self:?} + Base: {B}")
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_limbs) dst.write_usize(self.num_limbs)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let num_limbs = src.read_usize()?; let num_limbs = src.read_usize()?;
Ok(Self { num_limbs }) Ok(Self { num_limbs })
} }
@ -118,7 +118,7 @@ impl<F: RichField + Extendable<D>, const D: usize, const B: usize> Gate<F, D> fo
constraints constraints
} }
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
let gen = BaseSplitGenerator::<B> { let gen = BaseSplitGenerator::<B> {
row, row,
num_limbs: self.num_limbs, num_limbs: self.num_limbs,
@ -175,7 +175,9 @@ pub struct BaseSplitGenerator<const B: usize> {
num_limbs: usize, num_limbs: usize,
} }
impl<F: RichField, const B: usize> SimpleGenerator<F> for BaseSplitGenerator<B> { impl<F: RichField + Extendable<D>, const B: usize, const D: usize> SimpleGenerator<F, D>
for BaseSplitGenerator<B>
{
fn id(&self) -> String { fn id(&self) -> String {
"BaseSplitGenerator".to_string() "BaseSplitGenerator".to_string()
} }
@ -209,12 +211,12 @@ impl<F: RichField, const B: usize> SimpleGenerator<F> for BaseSplitGenerator<B>
} }
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
dst.write_usize(self.num_limbs) dst.write_usize(self.num_limbs)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let num_limbs = src.read_usize()?; let num_limbs = src.read_usize()?;
Ok(Self { row, num_limbs }) Ok(Self { row, num_limbs })

View File

@ -13,6 +13,7 @@ use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget; use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::WitnessGeneratorRef; use crate::iop::generator::WitnessGeneratorRef;
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::vars::{ use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked, EvaluationVarsBasePacked,
@ -46,11 +47,11 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ConstantGate {
format!("{self:?}") format!("{self:?}")
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_consts) dst.write_usize(self.num_consts)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let num_consts = src.read_usize()?; let num_consts = src.read_usize()?;
Ok(Self { num_consts }) Ok(Self { num_consts })
} }
@ -90,7 +91,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ConstantGate {
.collect() .collect()
} }
fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
vec![] vec![]
} }

View File

@ -17,6 +17,7 @@ use crate::iop::target::Target;
use crate::iop::wire::Wire; use crate::iop::wire::Wire;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
@ -168,14 +169,14 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for CosetInterpola
format!("{self:?}<D={D}>") format!("{self:?}<D={D}>")
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.subgroup_bits)?; dst.write_usize(self.subgroup_bits)?;
dst.write_usize(self.degree)?; dst.write_usize(self.degree)?;
dst.write_usize(self.barycentric_weights.len())?; dst.write_usize(self.barycentric_weights.len())?;
dst.write_field_vec(&self.barycentric_weights) dst.write_field_vec(&self.barycentric_weights)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let subgroup_bits = src.read_usize()?; let subgroup_bits = src.read_usize()?;
let degree = src.read_usize()?; let degree = src.read_usize()?;
let length = src.read_usize()?; let length = src.read_usize()?;
@ -362,7 +363,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for CosetInterpola
constraints constraints
} }
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
let gen = InterpolationGenerator::<F, D>::new(row, self.clone()); let gen = InterpolationGenerator::<F, D>::new(row, self.clone());
vec![WitnessGeneratorRef::new(gen.adapter())] vec![WitnessGeneratorRef::new(gen.adapter())]
} }
@ -406,7 +407,7 @@ impl<F: RichField + Extendable<D>, const D: usize> InterpolationGenerator<F, D>
} }
} }
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D>
for InterpolationGenerator<F, D> for InterpolationGenerator<F, D>
{ {
fn id(&self) -> String { fn id(&self) -> String {
@ -496,14 +497,14 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
out_buffer.set_ext_wires(evaluation_value_wires, computed_eval); out_buffer.set_ext_wires(evaluation_value_wires, computed_eval);
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
self.gate.serialize(dst) self.gate.serialize(dst, _common_data)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let gate = CosetInterpolationGate::deserialize(src)?; let gate = CosetInterpolationGate::deserialize(src, _common_data)?;
Ok(Self::new(row, gate)) Ok(Self::new(row, gate))
} }
} }

View File

@ -17,7 +17,7 @@ use crate::iop::target::Target;
use crate::iop::wire::Wire; use crate::iop::wire::Wire;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
use crate::plonk::vars::{ use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked, EvaluationVarsBasePacked,
@ -76,11 +76,11 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for Exponentiation
format!("{self:?}<D={D}>") format!("{self:?}<D={D}>")
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_power_bits) dst.write_usize(self.num_power_bits)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let num_power_bits = src.read_usize()?; let num_power_bits = src.read_usize()?;
Ok(Self::new(num_power_bits)) Ok(Self::new(num_power_bits))
} }
@ -173,7 +173,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for Exponentiation
constraints constraints
} }
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
let gen = ExponentiationGenerator::<F, D> { let gen = ExponentiationGenerator::<F, D> {
row, row,
gate: self.clone(), gate: self.clone(),
@ -243,7 +243,7 @@ pub struct ExponentiationGenerator<F: RichField + Extendable<D>, const D: usize>
gate: ExponentiationGate<F, D>, gate: ExponentiationGate<F, D>,
} }
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D>
for ExponentiationGenerator<F, D> for ExponentiationGenerator<F, D>
{ {
fn id(&self) -> String { fn id(&self) -> String {
@ -295,14 +295,14 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
out_buffer.set_wire(output_wire, intermediate_values[num_power_bits - 1]); out_buffer.set_wire(output_wire, intermediate_values[num_power_bits - 1]);
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
self.gate.serialize(dst) self.gate.serialize(dst, _common_data)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let gate = ExponentiationGate::deserialize(src)?; let gate = ExponentiationGate::deserialize(src, _common_data)?;
Ok(Self { row, gate }) Ok(Self { row, gate })
} }
} }

View File

@ -19,6 +19,7 @@ use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget; use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::WitnessGeneratorRef; use crate::iop::generator::WitnessGeneratorRef;
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::vars::{ use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
}; };
@ -28,9 +29,9 @@ use crate::util::serialization::{Buffer, IoResult};
pub trait Gate<F: RichField + Extendable<D>, const D: usize>: 'static + Send + Sync { pub trait Gate<F: RichField + Extendable<D>, const D: usize>: 'static + Send + Sync {
fn id(&self) -> String; fn id(&self) -> String;
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()>; fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()>;
fn deserialize(src: &mut Buffer) -> IoResult<Self> fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self>
where where
Self: Sized; Self: Sized;
@ -175,7 +176,7 @@ pub trait Gate<F: RichField + Extendable<D>, const D: usize>: 'static + Send + S
/// The generators used to populate the witness. /// The generators used to populate the witness.
/// Note: This should return exactly 1 generator per operation in the gate. /// Note: This should return exactly 1 generator per operation in the gate.
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>>; fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>>;
/// The number of wires used by this gate. /// The number of wires used by this gate.
fn num_wires(&self) -> usize; fn num_wires(&self) -> usize;

View File

@ -1,9 +1,11 @@
use alloc::format; use alloc::format;
use alloc::string::String; use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::usize; use core::usize;
use itertools::Itertools;
use keccak_hash::keccak;
use super::lookup_table::LookupTable; use super::lookup_table::LookupTable;
use crate::field::extension::Extendable; use crate::field::extension::Extendable;
use crate::field::packed::PackedField; use crate::field::packed::PackedField;
@ -16,7 +18,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRe
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
use crate::plonk::vars::{ use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked, EvaluationVarsBasePacked,
@ -32,13 +34,21 @@ pub struct LookupGate {
pub num_slots: usize, pub num_slots: usize,
/// LUT associated to the gate. /// LUT associated to the gate.
lut: LookupTable, lut: LookupTable,
/// The Keccak hash of the lookup table.
lut_hash: [u8; 32],
} }
impl LookupGate { impl LookupGate {
pub fn new_from_table(config: &CircuitConfig, lut: LookupTable) -> Self { pub fn new_from_table(config: &CircuitConfig, lut: LookupTable) -> Self {
let table_bytes = lut
.iter()
.flat_map(|(input, output)| [input.to_le_bytes(), output.to_le_bytes()].concat())
.collect_vec();
Self { Self {
num_slots: Self::num_slots(config), num_slots: Self::num_slots(config),
lut, lut,
lut_hash: keccak(table_bytes).0,
} }
} }
pub(crate) fn num_slots(config: &CircuitConfig) -> usize { pub(crate) fn num_slots(config: &CircuitConfig) -> usize {
@ -57,21 +67,35 @@ impl LookupGate {
impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupGate { impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupGate {
fn id(&self) -> String { 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>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_slots)?; dst.write_usize(self.num_slots)?;
dst.write_lut(&self.lut) for (i, lut) in common_data.luts.iter().enumerate() {
if lut == &self.lut {
dst.write_usize(i)?;
return dst.write_all(&self.lut_hash);
}
}
panic!("The associated lookup table couldn't be found.")
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let num_slots = src.read_usize()?; let num_slots = src.read_usize()?;
let lut = src.read_lut()?; let lut_index = src.read_usize()?;
let mut lut_hash = [0u8; 32];
src.read_exact(&mut lut_hash)?;
Ok(Self { Ok(Self {
num_slots, num_slots,
lut: Arc::new(lut), lut: common_data.luts[lut_index].clone(),
lut_hash,
}) })
} }
@ -101,7 +125,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupGate {
vec![] vec![]
} }
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
(0..self.num_slots) (0..self.num_slots)
.map(|i| { .map(|i| {
WitnessGeneratorRef::new( WitnessGeneratorRef::new(
@ -149,7 +173,7 @@ pub struct LookupGenerator {
slot_nb: usize, slot_nb: usize,
} }
impl<F: RichField> SimpleGenerator<F> for LookupGenerator { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for LookupGenerator {
fn id(&self) -> String { fn id(&self) -> String {
"LookupGenerator".to_string() "LookupGenerator".to_string()
} }
@ -165,39 +189,47 @@ impl<F: RichField> SimpleGenerator<F> for LookupGenerator {
let get_wire = |wire: usize| -> F { witness.get_target(Target::wire(self.row, wire)) }; let get_wire = |wire: usize| -> F { witness.get_target(Target::wire(self.row, wire)) };
let input_val = get_wire(LookupGate::wire_ith_looking_inp(self.slot_nb)); let input_val = get_wire(LookupGate::wire_ith_looking_inp(self.slot_nb));
let output_val = if input_val let (input, output) = self.lut[input_val.to_canonical_u64() as usize];
== F::from_canonical_u16(self.lut[input_val.to_canonical_u64() as usize].0) if input_val == F::from_canonical_u16(input) {
{ let output_val = F::from_canonical_u16(output);
F::from_canonical_u16(self.lut[input_val.to_canonical_u64() as usize].1)
let out_wire = Target::wire(self.row, LookupGate::wire_ith_looking_out(self.slot_nb));
out_buffer.set_target(out_wire, output_val);
} else { } else {
let mut cur_idx = 0; for (input, output) in self.lut.iter() {
while input_val != F::from_canonical_u16(self.lut[cur_idx].0) if input_val == F::from_canonical_u16(*input) {
&& cur_idx < self.lut.len() let output_val = F::from_canonical_u16(*output);
{
cur_idx += 1; let out_wire =
Target::wire(self.row, LookupGate::wire_ith_looking_out(self.slot_nb));
out_buffer.set_target(out_wire, output_val);
return;
}
} }
assert!(cur_idx < self.lut.len(), "Incorrect input value provided"); panic!("Incorrect input value provided");
F::from_canonical_u16(self.lut[cur_idx].1)
}; };
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<()> { fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
dst.write_lut(&self.lut)?; dst.write_usize(self.slot_nb)?;
dst.write_usize(self.slot_nb) for (i, lut) in common_data.luts.iter().enumerate() {
if lut == &self.lut {
return dst.write_usize(i);
}
}
panic!("The associated lookup table couldn't be found.")
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let lut = src.read_lut()?;
let slot_nb = src.read_usize()?; let slot_nb = src.read_usize()?;
let lut_index = src.read_usize()?;
Ok(Self { Ok(Self {
row, row,
lut: Arc::new(lut), lut: common_data.luts[lut_index].clone(),
slot_nb, slot_nb,
}) })
} }

View File

@ -4,6 +4,8 @@ use alloc::sync::Arc;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::usize; use core::usize;
use itertools::Itertools;
use keccak_hash::keccak;
use plonky2_util::ceil_div_usize; use plonky2_util::ceil_div_usize;
use crate::field::extension::Extendable; use crate::field::extension::Extendable;
@ -17,7 +19,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRe
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
use crate::plonk::vars::{ use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked, EvaluationVarsBasePacked,
@ -33,15 +35,23 @@ pub struct LookupTableGate {
pub num_slots: usize, pub num_slots: usize,
/// Lookup table associated to the gate. /// Lookup table associated to the gate.
pub lut: LookupTable, pub lut: LookupTable,
/// The Keccak hash of the lookup table.
lut_hash: [u8; 32],
/// First row of the lookup table. /// First row of the lookup table.
last_lut_row: usize, last_lut_row: usize,
} }
impl LookupTableGate { impl LookupTableGate {
pub fn new_from_table(config: &CircuitConfig, lut: LookupTable, last_lut_row: usize) -> Self { pub fn new_from_table(config: &CircuitConfig, lut: LookupTable, last_lut_row: usize) -> Self {
let table_bytes = lut
.iter()
.flat_map(|(input, output)| [input.to_le_bytes(), output.to_le_bytes()].concat())
.collect_vec();
Self { Self {
num_slots: Self::num_slots(config), num_slots: Self::num_slots(config),
lut, lut,
lut_hash: keccak(table_bytes).0,
last_lut_row, last_lut_row,
} }
} }
@ -69,23 +79,37 @@ impl LookupTableGate {
impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupTableGate { impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupTableGate {
fn id(&self) -> String { 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>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_slots)?; dst.write_usize(self.num_slots)?;
dst.write_lut(&self.lut)?; dst.write_usize(self.last_lut_row)?;
dst.write_usize(self.last_lut_row) for (i, lut) in common_data.luts.iter().enumerate() {
if lut == &self.lut {
dst.write_usize(i)?;
return dst.write_all(&self.lut_hash);
}
}
panic!("The associated lookup table couldn't be found.")
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let num_slots = src.read_usize()?; let num_slots = src.read_usize()?;
let lut = src.read_lut()?;
let last_lut_row = 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 { Ok(Self {
num_slots, num_slots,
lut: Arc::new(lut), lut: common_data.luts[lut_index].clone(),
lut_hash,
last_lut_row, last_lut_row,
}) })
} }
@ -116,7 +140,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupTableGat
vec![] vec![]
} }
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
(0..self.num_slots) (0..self.num_slots)
.map(|i| { .map(|i| {
WitnessGeneratorRef::new( WitnessGeneratorRef::new(
@ -168,7 +192,7 @@ pub struct LookupTableGenerator {
last_lut_row: usize, last_lut_row: usize,
} }
impl<F: RichField> SimpleGenerator<F> for LookupTableGenerator { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for LookupTableGenerator {
fn id(&self) -> String { fn id(&self) -> String {
"LookupTableGenerator".to_string() "LookupTableGenerator".to_string()
} }
@ -187,14 +211,9 @@ impl<F: RichField> SimpleGenerator<F> for LookupTableGenerator {
Target::wire(self.row, LookupTableGate::wire_ith_looked_out(self.slot_nb)); Target::wire(self.row, LookupTableGate::wire_ith_looked_out(self.slot_nb));
if slot < self.lut.len() { if slot < self.lut.len() {
out_buffer.set_target( let (input, output) = self.lut[slot];
slot_input_target, out_buffer.set_target(slot_input_target, F::from_canonical_usize(input as usize));
F::from_canonical_usize(self.lut[slot].0 as usize), out_buffer.set_target(slot_output_target, F::from_canonical_usize(output as usize));
);
out_buffer.set_target(
slot_output_target,
F::from_canonical_usize(self.lut[slot].1.into()),
);
} else { } else {
// Pad with zeros. // Pad with zeros.
out_buffer.set_target(slot_input_target, F::ZERO); out_buffer.set_target(slot_input_target, F::ZERO);
@ -202,24 +221,30 @@ impl<F: RichField> SimpleGenerator<F> for LookupTableGenerator {
} }
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
dst.write_lut(&self.lut)?;
dst.write_usize(self.slot_nb)?; dst.write_usize(self.slot_nb)?;
dst.write_usize(self.num_slots)?; dst.write_usize(self.num_slots)?;
dst.write_usize(self.last_lut_row) 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);
}
}
panic!("The associated lookup table couldn't be found.")
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let lut = src.read_lut()?;
let slot_nb = src.read_usize()?; let slot_nb = src.read_usize()?;
let num_slots = src.read_usize()?; let num_slots = src.read_usize()?;
let last_lut_row = src.read_usize()?; let last_lut_row = src.read_usize()?;
let lut_index = src.read_usize()?;
Ok(Self { Ok(Self {
row, row,
lut: Arc::new(lut), lut: common_data.luts[lut_index].clone(),
slot_nb, slot_nb,
num_slots, num_slots,
last_lut_row, last_lut_row,

View File

@ -12,7 +12,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRe
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
@ -53,11 +53,11 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for MulExtensionGa
format!("{self:?}") format!("{self:?}")
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_ops) dst.write_usize(self.num_ops)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let num_ops = src.read_usize()?; let num_ops = src.read_usize()?;
Ok(Self { num_ops }) Ok(Self { num_ops })
} }
@ -119,7 +119,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for MulExtensionGa
constraints constraints
} }
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
(0..self.num_ops) (0..self.num_ops)
.map(|i| { .map(|i| {
WitnessGeneratorRef::new( WitnessGeneratorRef::new(
@ -158,7 +158,7 @@ pub struct MulExtensionGenerator<F: RichField + Extendable<D>, const D: usize> {
i: usize, i: usize,
} }
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D>
for MulExtensionGenerator<F, D> for MulExtensionGenerator<F, D>
{ {
fn id(&self) -> String { fn id(&self) -> String {
@ -191,13 +191,13 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
out_buffer.set_extension_target(output_target, computed_output) out_buffer.set_extension_target(output_target, computed_output)
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
dst.write_field(self.const_0)?; dst.write_field(self.const_0)?;
dst.write_usize(self.i) dst.write_usize(self.i)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let const_0 = src.read_field()?; let const_0 = src.read_field()?;
let i = src.read_usize()?; let i = src.read_usize()?;

View File

@ -7,6 +7,7 @@ use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget; use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::WitnessGeneratorRef; use crate::iop::generator::WitnessGeneratorRef;
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBaseBatch}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBaseBatch};
use crate::util::serialization::{Buffer, IoResult}; use crate::util::serialization::{Buffer, IoResult};
@ -18,11 +19,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for NoopGate {
"NoopGate".into() "NoopGate".into()
} }
fn serialize(&self, _dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(
&self,
_dst: &mut Vec<u8>,
_common_data: &CommonCircuitData<F, D>,
) -> IoResult<()> {
Ok(()) Ok(())
} }
fn deserialize(_src: &mut Buffer) -> IoResult<Self> { fn deserialize(_src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
Ok(Self) Ok(Self)
} }
@ -42,7 +47,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for NoopGate {
Vec::new() Vec::new()
} }
fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
Vec::new() Vec::new()
} }

View File

@ -17,6 +17,7 @@ use crate::iop::target::Target;
use crate::iop::wire::Wire; use crate::iop::wire::Wire;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
@ -99,11 +100,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for PoseidonGate<F
format!("{self:?}<WIDTH={SPONGE_WIDTH}>") format!("{self:?}<WIDTH={SPONGE_WIDTH}>")
} }
fn serialize(&self, _dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(
&self,
_dst: &mut Vec<u8>,
_common_data: &CommonCircuitData<F, D>,
) -> IoResult<()> {
Ok(()) Ok(())
} }
fn deserialize(_src: &mut Buffer) -> IoResult<Self> { fn deserialize(_src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
Ok(PoseidonGate::new()) Ok(PoseidonGate::new())
} }
@ -380,7 +385,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for PoseidonGate<F
constraints constraints
} }
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
let gen = PoseidonGenerator::<F, D> { let gen = PoseidonGenerator::<F, D> {
row, row,
_phantom: PhantomData, _phantom: PhantomData,
@ -415,7 +420,7 @@ pub struct PoseidonGenerator<F: RichField + Extendable<D> + Poseidon, const D: u
_phantom: PhantomData<F>, _phantom: PhantomData<F>,
} }
impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F> impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F, D>
for PoseidonGenerator<F, D> for PoseidonGenerator<F, D>
{ {
fn id(&self) -> String { fn id(&self) -> String {
@ -512,11 +517,11 @@ impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F>
} }
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row) dst.write_usize(self.row)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
Ok(Self { Ok(Self {
row, row,

View File

@ -16,6 +16,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRe
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
@ -118,11 +119,15 @@ impl<F: RichField + Extendable<D> + Poseidon, const D: usize> Gate<F, D> for Pos
format!("{self:?}<WIDTH={SPONGE_WIDTH}>") format!("{self:?}<WIDTH={SPONGE_WIDTH}>")
} }
fn serialize(&self, _dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(
&self,
_dst: &mut Vec<u8>,
_common_data: &CommonCircuitData<F, D>,
) -> IoResult<()> {
Ok(()) Ok(())
} }
fn deserialize(_src: &mut Buffer) -> IoResult<Self> { fn deserialize(_src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
Ok(PoseidonMdsGate::new()) Ok(PoseidonMdsGate::new())
} }
@ -187,7 +192,7 @@ impl<F: RichField + Extendable<D> + Poseidon, const D: usize> Gate<F, D> for Pos
.collect() .collect()
} }
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
let gen = PoseidonMdsGenerator::<D> { row }; let gen = PoseidonMdsGenerator::<D> { row };
vec![WitnessGeneratorRef::new(gen.adapter())] vec![WitnessGeneratorRef::new(gen.adapter())]
} }
@ -214,7 +219,7 @@ pub struct PoseidonMdsGenerator<const D: usize> {
row: usize, row: usize,
} }
impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F> impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F, D>
for PoseidonMdsGenerator<D> for PoseidonMdsGenerator<D>
{ {
fn id(&self) -> String { fn id(&self) -> String {
@ -250,11 +255,11 @@ impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F>
} }
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row) dst.write_usize(self.row)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
Ok(Self { row }) Ok(Self { row })
} }

View File

@ -11,6 +11,7 @@ use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget; use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::WitnessGeneratorRef; use crate::iop::generator::WitnessGeneratorRef;
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::vars::{ use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked, EvaluationVarsBasePacked,
@ -31,11 +32,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for PublicInputGat
"PublicInputGate".into() "PublicInputGate".into()
} }
fn serialize(&self, _dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(
&self,
_dst: &mut Vec<u8>,
_common_data: &CommonCircuitData<F, D>,
) -> IoResult<()> {
Ok(()) Ok(())
} }
fn deserialize(_src: &mut Buffer) -> IoResult<Self> { fn deserialize(_src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
Ok(Self) Ok(Self)
} }
@ -72,7 +77,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for PublicInputGat
.collect() .collect()
} }
fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
Vec::new() Vec::new()
} }

View File

@ -18,7 +18,7 @@ use crate::iop::target::Target;
use crate::iop::wire::Wire; use crate::iop::wire::Wire;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
use crate::plonk::vars::{ use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked, EvaluationVarsBasePacked,
@ -122,14 +122,14 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for RandomAccessGa
format!("{self:?}<D={D}>") format!("{self:?}<D={D}>")
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.bits)?; dst.write_usize(self.bits)?;
dst.write_usize(self.num_copies)?; dst.write_usize(self.num_copies)?;
dst.write_usize(self.num_extra_constants)?; dst.write_usize(self.num_extra_constants)?;
Ok(()) Ok(())
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let bits = src.read_usize()?; let bits = src.read_usize()?;
let num_copies = src.read_usize()?; let num_copies = src.read_usize()?;
let num_extra_constants = src.read_usize()?; let num_extra_constants = src.read_usize()?;
@ -252,7 +252,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for RandomAccessGa
constraints constraints
} }
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
(0..self.num_copies) (0..self.num_copies)
.map(|copy| { .map(|copy| {
WitnessGeneratorRef::new( WitnessGeneratorRef::new(
@ -345,7 +345,7 @@ pub struct RandomAccessGenerator<F: RichField + Extendable<D>, const D: usize> {
copy: usize, copy: usize,
} }
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D>
for RandomAccessGenerator<F, D> for RandomAccessGenerator<F, D>
{ {
fn id(&self) -> String { fn id(&self) -> String {
@ -394,16 +394,16 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
} }
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
dst.write_usize(self.copy)?; dst.write_usize(self.copy)?;
self.gate.serialize(dst) self.gate.serialize(dst, _common_data)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let copy = src.read_usize()?; let copy = src.read_usize()?;
let gate = RandomAccessGate::<F, D>::deserialize(src)?; let gate = RandomAccessGate::<F, D>::deserialize(src, _common_data)?;
Ok(Self { row, gate, copy }) Ok(Self { row, gate, copy })
} }
} }

View File

@ -12,6 +12,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRe
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
@ -60,12 +61,12 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ReducingGate<D
format!("{self:?}") format!("{self:?}")
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_coeffs)?; dst.write_usize(self.num_coeffs)?;
Ok(()) Ok(())
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -150,7 +151,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ReducingGate<D
.collect() .collect()
} }
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
vec![WitnessGeneratorRef::new( vec![WitnessGeneratorRef::new(
ReducingGenerator { ReducingGenerator {
row, row,
@ -183,7 +184,7 @@ pub struct ReducingGenerator<const D: usize> {
gate: ReducingGate<D>, gate: ReducingGate<D>,
} }
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> for ReducingGenerator<D> { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for ReducingGenerator<D> {
fn id(&self) -> String { fn id(&self) -> String {
"ReducingGenerator".to_string() "ReducingGenerator".to_string()
} }
@ -225,14 +226,14 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> for Reduci
out_buffer.set_extension_target(output, acc); out_buffer.set_extension_target(output, acc);
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
<ReducingGate<D> as Gate<F, D>>::serialize(&self.gate, dst) <ReducingGate<D> as Gate<F, D>>::serialize(&self.gate, dst, _common_data)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let gate = <ReducingGate<D> as Gate<F, D>>::deserialize(src)?; let gate = <ReducingGate<D> as Gate<F, D>>::deserialize(src, _common_data)?;
Ok(Self { row, gate }) Ok(Self { row, gate })
} }
} }

View File

@ -12,6 +12,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRe
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
use crate::util::serialization::{Buffer, IoResult, Read, Write}; use crate::util::serialization::{Buffer, IoResult, Read, Write};
@ -63,12 +64,12 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ReducingExtens
format!("{self:?}") format!("{self:?}")
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_coeffs)?; dst.write_usize(self.num_coeffs)?;
Ok(()) Ok(())
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self>
where where
Self: Sized, Self: Sized,
{ {
@ -150,7 +151,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ReducingExtens
.collect() .collect()
} }
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> { fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F, D>> {
vec![WitnessGeneratorRef::new( vec![WitnessGeneratorRef::new(
ReducingGenerator { ReducingGenerator {
row, row,
@ -183,7 +184,7 @@ pub struct ReducingGenerator<const D: usize> {
gate: ReducingExtensionGate<D>, gate: ReducingExtensionGate<D>,
} }
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> for ReducingGenerator<D> { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for ReducingGenerator<D> {
fn id(&self) -> String { fn id(&self) -> String {
"ReducingExtensionGenerator".to_string() "ReducingExtensionGenerator".to_string()
} }
@ -219,14 +220,14 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> for Reduci
} }
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
<ReducingExtensionGate<D> as Gate<F, D>>::serialize(&self.gate, dst) <ReducingExtensionGate<D> as Gate<F, D>>::serialize(&self.gate, dst, _common_data)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let gate = <ReducingExtensionGate<D> as Gate<F, D>>::deserialize(src)?; let gate = <ReducingExtensionGate<D> as Gate<F, D>>::deserialize(src, _common_data)?;
Ok(Self { row, gate }) Ok(Self { row, gate })
} }
} }

View File

@ -98,7 +98,9 @@ pub(crate) fn generate_partial_witness<
} }
/// A generator participates in the generation of the witness. /// A generator participates in the generation of the witness.
pub trait WitnessGenerator<F: Field>: 'static + Send + Sync + Debug { pub trait WitnessGenerator<F: RichField + Extendable<D>, const D: usize>:
'static + Send + Sync + Debug
{
fn id(&self) -> String; fn id(&self) -> String;
/// Targets to be "watched" by this generator. Whenever a target in the watch list is populated, /// Targets to be "watched" by this generator. Whenever a target in the watch list is populated,
@ -110,32 +112,34 @@ pub trait WitnessGenerator<F: Field>: 'static + Send + Sync + Debug {
/// run next time a target in its watch list is populated. /// run next time a target in its watch list is populated.
fn run(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) -> bool; fn run(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) -> bool;
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()>; fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()>;
fn deserialize(src: &mut Buffer) -> IoResult<Self> fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self>
where where
Self: Sized; Self: Sized;
} }
/// A wrapper around an `Box<WitnessGenerator>` which implements `PartialEq` /// A wrapper around an `Box<WitnessGenerator>` which implements `PartialEq`
/// and `Eq` based on generator IDs. /// and `Eq` based on generator IDs.
pub struct WitnessGeneratorRef<F: Field>(pub Box<dyn WitnessGenerator<F>>); pub struct WitnessGeneratorRef<F: RichField + Extendable<D>, const D: usize>(
pub Box<dyn WitnessGenerator<F, D>>,
);
impl<F: Field> WitnessGeneratorRef<F> { impl<F: RichField + Extendable<D>, const D: usize> WitnessGeneratorRef<F, D> {
pub fn new<G: WitnessGenerator<F>>(generator: G) -> WitnessGeneratorRef<F> { pub fn new<G: WitnessGenerator<F, D>>(generator: G) -> WitnessGeneratorRef<F, D> {
WitnessGeneratorRef(Box::new(generator)) WitnessGeneratorRef(Box::new(generator))
} }
} }
impl<F: Field> PartialEq for WitnessGeneratorRef<F> { impl<F: RichField + Extendable<D>, const D: usize> PartialEq for WitnessGeneratorRef<F, D> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.0.id() == other.0.id() self.0.id() == other.0.id()
} }
} }
impl<F: Field> Eq for WitnessGeneratorRef<F> {} impl<F: RichField + Extendable<D>, const D: usize> Eq for WitnessGeneratorRef<F, D> {}
impl<F: Field> Debug for WitnessGeneratorRef<F> { impl<F: RichField + Extendable<D>, const D: usize> Debug for WitnessGeneratorRef<F, D> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0.id()) write!(f, "{}", self.0.id())
} }
@ -190,14 +194,16 @@ impl<F: Field> GeneratedValues<F> {
} }
/// A generator which runs once after a list of dependencies is present in the witness. /// A generator which runs once after a list of dependencies is present in the witness.
pub trait SimpleGenerator<F: Field>: 'static + Send + Sync + Debug { pub trait SimpleGenerator<F: RichField + Extendable<D>, const D: usize>:
'static + Send + Sync + Debug
{
fn id(&self) -> String; fn id(&self) -> String;
fn dependencies(&self) -> Vec<Target>; fn dependencies(&self) -> Vec<Target>;
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>); fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>);
fn adapter(self) -> SimpleGeneratorAdapter<F, Self> fn adapter(self) -> SimpleGeneratorAdapter<F, Self, D>
where where
Self: Sized, Self: Sized,
{ {
@ -207,20 +213,26 @@ pub trait SimpleGenerator<F: Field>: 'static + Send + Sync + Debug {
} }
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()>; fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()>;
fn deserialize(src: &mut Buffer) -> IoResult<Self> fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self>
where where
Self: Sized; Self: Sized;
} }
#[derive(Debug)] #[derive(Debug)]
pub struct SimpleGeneratorAdapter<F: Field, SG: SimpleGenerator<F> + ?Sized> { pub struct SimpleGeneratorAdapter<
F: RichField + Extendable<D>,
SG: SimpleGenerator<F, D> + ?Sized,
const D: usize,
> {
_phantom: PhantomData<F>, _phantom: PhantomData<F>,
inner: SG, inner: SG,
} }
impl<F: Field, SG: SimpleGenerator<F>> WitnessGenerator<F> for SimpleGeneratorAdapter<F, SG> { impl<F: RichField + Extendable<D>, SG: SimpleGenerator<F, D>, const D: usize> WitnessGenerator<F, D>
for SimpleGeneratorAdapter<F, SG, D>
{
fn id(&self) -> String { fn id(&self) -> String {
self.inner.id() self.inner.id()
} }
@ -238,13 +250,13 @@ impl<F: Field, SG: SimpleGenerator<F>> WitnessGenerator<F> for SimpleGeneratorAd
} }
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
self.inner.serialize(dst) self.inner.serialize(dst, common_data)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
Ok(Self { Ok(Self {
inner: SG::deserialize(src)?, inner: SG::deserialize(src, common_data)?,
_phantom: PhantomData, _phantom: PhantomData,
}) })
} }
@ -257,7 +269,7 @@ pub struct CopyGenerator {
pub(crate) dst: Target, pub(crate) dst: Target,
} }
impl<F: Field> SimpleGenerator<F> for CopyGenerator { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for CopyGenerator {
fn id(&self) -> String { fn id(&self) -> String {
"CopyGenerator".to_string() "CopyGenerator".to_string()
} }
@ -271,12 +283,12 @@ impl<F: Field> SimpleGenerator<F> for CopyGenerator {
out_buffer.set_target(self.dst, value); out_buffer.set_target(self.dst, value);
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target(self.src)?; dst.write_target(self.src)?;
dst.write_target(self.dst) dst.write_target(self.dst)
} }
fn deserialize(source: &mut Buffer) -> IoResult<Self> { fn deserialize(source: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let src = source.read_target()?; let src = source.read_target()?;
let dst = source.read_target()?; let dst = source.read_target()?;
Ok(Self { src, dst }) Ok(Self { src, dst })
@ -289,7 +301,7 @@ pub struct RandomValueGenerator {
pub(crate) target: Target, pub(crate) target: Target,
} }
impl<F: Field> SimpleGenerator<F> for RandomValueGenerator { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for RandomValueGenerator {
fn id(&self) -> String { fn id(&self) -> String {
"RandomValueGenerator".to_string() "RandomValueGenerator".to_string()
} }
@ -303,11 +315,11 @@ impl<F: Field> SimpleGenerator<F> for RandomValueGenerator {
out_buffer.set_target(self.target, random_value); out_buffer.set_target(self.target, random_value);
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target(self.target) dst.write_target(self.target)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let target = src.read_target()?; let target = src.read_target()?;
Ok(Self { target }) Ok(Self { target })
} }
@ -320,7 +332,7 @@ pub struct NonzeroTestGenerator {
pub(crate) dummy: Target, pub(crate) dummy: Target,
} }
impl<F: Field> SimpleGenerator<F> for NonzeroTestGenerator { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for NonzeroTestGenerator {
fn id(&self) -> String { fn id(&self) -> String {
"NonzeroTestGenerator".to_string() "NonzeroTestGenerator".to_string()
} }
@ -341,12 +353,12 @@ impl<F: Field> SimpleGenerator<F> for NonzeroTestGenerator {
out_buffer.set_target(self.dummy, dummy_value); out_buffer.set_target(self.dummy, dummy_value);
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target(self.to_test)?; dst.write_target(self.to_test)?;
dst.write_target(self.dummy) dst.write_target(self.dummy)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let to_test = src.read_target()?; let to_test = src.read_target()?;
let dummy = src.read_target()?; let dummy = src.read_target()?;
Ok(Self { to_test, dummy }) Ok(Self { to_test, dummy })
@ -368,7 +380,7 @@ impl<F: Field> ConstantGenerator<F> {
} }
} }
impl<F: RichField> SimpleGenerator<F> for ConstantGenerator<F> { impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for ConstantGenerator<F> {
fn id(&self) -> String { fn id(&self) -> String {
"ConstantGenerator".to_string() "ConstantGenerator".to_string()
} }
@ -381,14 +393,14 @@ impl<F: RichField> SimpleGenerator<F> for ConstantGenerator<F> {
out_buffer.set_target(Target::wire(self.row, self.wire_index), self.constant); out_buffer.set_target(Target::wire(self.row, self.wire_index), self.constant);
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?; dst.write_usize(self.row)?;
dst.write_usize(self.constant_index)?; dst.write_usize(self.constant_index)?;
dst.write_usize(self.wire_index)?; dst.write_usize(self.wire_index)?;
dst.write_field(self.constant) dst.write_field(self.constant)
} }
fn deserialize(src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?; let row = src.read_usize()?;
let constant_index = src.read_usize()?; let constant_index = src.read_usize()?;
let wire_index = src.read_usize()?; let wire_index = src.read_usize()?;

View File

@ -109,7 +109,7 @@ pub struct CircuitBuilder<F: RichField + Extendable<D>, const D: usize> {
context_log: ContextTree, context_log: ContextTree,
/// Generators used to generate the witness. /// Generators used to generate the witness.
generators: Vec<WitnessGeneratorRef<F>>, generators: Vec<WitnessGeneratorRef<F, D>>,
constants_to_targets: HashMap<F, Target>, constants_to_targets: HashMap<F, Target>,
targets_to_constants: HashMap<Target, F>, targets_to_constants: HashMap<Target, F>,
@ -444,11 +444,11 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.connect(x, one); self.connect(x, one);
} }
pub fn add_generators(&mut self, generators: Vec<WitnessGeneratorRef<F>>) { pub fn add_generators(&mut self, generators: Vec<WitnessGeneratorRef<F, D>>) {
self.generators.extend(generators); self.generators.extend(generators);
} }
pub fn add_simple_generator<G: SimpleGenerator<F>>(&mut self, generator: G) { pub fn add_simple_generator<G: SimpleGenerator<F, D>>(&mut self, generator: G) {
self.generators self.generators
.push(WitnessGeneratorRef::new(generator.adapter())); .push(WitnessGeneratorRef::new(generator.adapter()));
} }

View File

@ -295,7 +295,7 @@ pub struct ProverOnlyCircuitData<
C: GenericConfig<D, F = F>, C: GenericConfig<D, F = F>,
const D: usize, const D: usize,
> { > {
pub generators: Vec<WitnessGeneratorRef<F>>, pub generators: Vec<WitnessGeneratorRef<F, D>>,
/// Generator indices (within the `Vec` above), indexed by the representative of each target /// Generator indices (within the `Vec` above), indexed by the representative of each target
/// they watch. /// they watch.
pub generator_indices_by_watches: BTreeMap<usize, Vec<usize>>, pub generator_indices_by_watches: BTreeMap<usize, Vec<usize>>,
@ -321,6 +321,29 @@ pub struct ProverOnlyCircuitData<
pub lut_to_lookups: Vec<Lookup>, pub lut_to_lookups: Vec<Lookup>,
} }
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
ProverOnlyCircuitData<F, C, D>
{
pub fn to_bytes(
&self,
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<Vec<u8>> {
let mut buffer = Vec::new();
buffer.write_prover_only_circuit_data(self, generator_serializer, common_data)?;
Ok(buffer)
}
pub fn from_bytes(
bytes: &[u8],
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<Self> {
let mut buffer = Buffer::new(bytes);
buffer.read_prover_only_circuit_data(generator_serializer, common_data)
}
}
/// Circuit data required by the verifier, but not the prover. /// Circuit data required by the verifier, but not the prover.
#[derive(Debug, Clone, Eq, PartialEq, Serialize)] #[derive(Debug, Clone, Eq, PartialEq, Serialize)]
pub struct VerifierOnlyCircuitData<C: GenericConfig<D>, const D: usize> { pub struct VerifierOnlyCircuitData<C: GenericConfig<D>, const D: usize> {

View File

@ -80,15 +80,14 @@ pub fn set_lookup_wires<
let remaining_slots = (num_entries let remaining_slots = (num_entries
- (prover_data.lut_to_lookups[lut_index].len() % num_entries)) - (prover_data.lut_to_lookups[lut_index].len() % num_entries))
% num_entries; % num_entries;
let first_inp_value = F::from_canonical_u16(common_data.luts[lut_index][0].0); let (first_inp_value, first_out_value) = common_data.luts[lut_index][0];
let first_out_value = F::from_canonical_u16(common_data.luts[lut_index][0].1);
for slot in (num_entries - remaining_slots)..num_entries { for slot in (num_entries - remaining_slots)..num_entries {
let inp_target = let inp_target =
Target::wire(last_lut_gate - 1, LookupGate::wire_ith_looking_inp(slot)); Target::wire(last_lut_gate - 1, LookupGate::wire_ith_looking_inp(slot));
let out_target = let out_target =
Target::wire(last_lut_gate - 1, LookupGate::wire_ith_looking_out(slot)); Target::wire(last_lut_gate - 1, LookupGate::wire_ith_looking_out(slot));
pw.set_target(inp_target, first_inp_value); pw.set_target(inp_target, F::from_canonical_u16(first_inp_value));
pw.set_target(out_target, first_out_value); pw.set_target(out_target, F::from_canonical_u16(first_out_value));
multiplicities[0] += 1; multiplicities[0] += 1;
} }

View File

@ -37,11 +37,8 @@ pub(crate) fn get_lut_poly<F: RichField + Extendable<D>, const D: usize>(
let b = deltas[LookupChallenges::ChallengeB as usize]; let b = deltas[LookupChallenges::ChallengeB as usize];
let mut coeffs = Vec::new(); let mut coeffs = Vec::new();
let n = common_data.luts[lut_index].len(); let n = common_data.luts[lut_index].len();
for i in 0..n { for (input, output) in common_data.luts[lut_index].iter() {
coeffs.push( coeffs.push(F::from_canonical_u16(*input) + b * F::from_canonical_u16(*output));
F::from_canonical_u16(common_data.luts[lut_index][i].0)
+ b * F::from_canonical_u16(common_data.luts[lut_index][i].1),
);
} }
coeffs.append(&mut vec![F::ZERO; degree - n]); coeffs.append(&mut vec![F::ZERO; degree - n]);
coeffs.reverse(); coeffs.reverse();
@ -760,14 +757,11 @@ pub(crate) fn get_lut_poly_circuit<F: RichField + Extendable<D>, const D: usize>
let b = deltas[LookupChallenges::ChallengeB as usize]; let b = deltas[LookupChallenges::ChallengeB as usize];
let delta = deltas[LookupChallenges::ChallengeDelta as usize]; let delta = deltas[LookupChallenges::ChallengeDelta as usize];
let n = common_data.luts[lut_index].len(); let n = common_data.luts[lut_index].len();
let mut coeffs: Vec<Target> = (0..n) let mut coeffs: Vec<Target> = common_data.luts[lut_index]
.map(|i| { .iter()
let temp = .map(|(input, output)| {
builder.mul_const(F::from_canonical_u16(common_data.luts[lut_index][i].1), b); let temp = builder.mul_const(F::from_canonical_u16(*output), b);
builder.add_const( builder.add_const(temp, F::from_canonical_u16(*input))
temp,
F::from_canonical_u16(common_data.luts[lut_index][i].0),
)
}) })
.collect(); .collect();
for _ in n..degree { for _ in n..degree {

View File

@ -215,30 +215,7 @@ where
} }
} }
impl<F, C, const D: usize> DummyProofGenerator<F, C, D> impl<F, C, const D: usize> SimpleGenerator<F, D> for DummyProofGenerator<F, C, D>
where
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F> + 'static,
C::Hasher: AlgebraicHasher<F>,
{
pub fn deserialize_with_circuit_data(
src: &mut Buffer,
cd: &CommonCircuitData<F, D>,
) -> IoResult<Self> {
let proof_with_pis_target = src.read_target_proof_with_public_inputs()?;
let proof_with_pis = src.read_proof_with_public_inputs(cd)?;
let verifier_data_target = src.read_target_verifier_circuit()?;
let verifier_data = src.read_verifier_only_circuit_data()?;
Ok(Self {
proof_with_pis_target,
proof_with_pis,
verifier_data_target,
verifier_data,
})
}
}
impl<F, C, const D: usize> SimpleGenerator<F> for DummyProofGenerator<F, C, D>
where where
F: RichField + Extendable<D>, F: RichField + Extendable<D>,
C: GenericConfig<D, F = F> + 'static, C: GenericConfig<D, F = F> + 'static,
@ -257,14 +234,23 @@ where
out_buffer.set_verifier_data_target(&self.verifier_data_target, &self.verifier_data); out_buffer.set_verifier_data_target(&self.verifier_data_target, &self.verifier_data);
} }
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> { fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target_proof_with_public_inputs(&self.proof_with_pis_target)?; dst.write_target_proof_with_public_inputs(&self.proof_with_pis_target)?;
dst.write_proof_with_public_inputs(&self.proof_with_pis)?; dst.write_proof_with_public_inputs(&self.proof_with_pis)?;
dst.write_target_verifier_circuit(&self.verifier_data_target)?; dst.write_target_verifier_circuit(&self.verifier_data_target)?;
dst.write_verifier_only_circuit_data(&self.verifier_data) dst.write_verifier_only_circuit_data(&self.verifier_data)
} }
fn deserialize(_src: &mut Buffer) -> IoResult<Self> { fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
panic!() let proof_with_pis_target = src.read_target_proof_with_public_inputs()?;
let proof_with_pis = src.read_proof_with_public_inputs(common_data)?;
let verifier_data_target = src.read_target_verifier_circuit()?;
let verifier_data = src.read_verifier_only_circuit_data()?;
Ok(Self {
proof_with_pis_target,
proof_with_pis,
verifier_data_target,
verifier_data,
})
} }
} }

View File

@ -218,10 +218,10 @@ mod tests {
type F = <C as GenericConfig<D>>::F; type F = <C as GenericConfig<D>>::F;
let config = CircuitConfig::standard_recursion_zk_config(); let config = CircuitConfig::standard_recursion_zk_config();
let (proof, vd, cd) = dummy_proof::<F, C, D>(&config, 4_000)?; let (proof, vd, common_data) = dummy_proof::<F, C, D>(&config, 4_000)?;
let (proof, vd, cd) = let (proof, vd, common_data) =
recursive_proof::<F, C, C, D>(proof, vd, cd, &config, None, true, true)?; recursive_proof::<F, C, C, D>(proof, vd, common_data, &config, None, true, true)?;
test_serialization(&proof, &vd, &cd)?; test_serialization(&proof, &vd, &common_data)?;
Ok(()) Ok(())
} }
@ -234,10 +234,10 @@ mod tests {
type F = <C as GenericConfig<D>>::F; type F = <C as GenericConfig<D>>::F;
let config = CircuitConfig::standard_recursion_zk_config(); let config = CircuitConfig::standard_recursion_zk_config();
let (proof, vd, cd) = dummy_lookup_proof::<F, C, D>(&config, 10)?; let (proof, vd, common_data) = dummy_lookup_proof::<F, C, D>(&config, 10)?;
let (proof, vd, cd) = let (proof, vd, common_data) =
recursive_proof::<F, C, C, D>(proof, vd, cd, &config, None, true, true)?; recursive_proof::<F, C, C, D>(proof, vd, common_data, &config, None, true, true)?;
test_serialization(&proof, &vd, &cd)?; test_serialization(&proof, &vd, &common_data)?;
Ok(()) Ok(())
} }
@ -250,10 +250,10 @@ mod tests {
type F = <C as GenericConfig<D>>::F; type F = <C as GenericConfig<D>>::F;
let config = CircuitConfig::standard_recursion_config(); let config = CircuitConfig::standard_recursion_config();
let (proof, vd, cd) = dummy_two_luts_proof::<F, C, D>(&config)?; let (proof, vd, common_data) = dummy_two_luts_proof::<F, C, D>(&config)?;
let (proof, vd, cd) = let (proof, vd, common_data) =
recursive_proof::<F, C, C, D>(proof, vd, cd, &config, None, true, true)?; recursive_proof::<F, C, C, D>(proof, vd, common_data, &config, None, true, true)?;
test_serialization(&proof, &vd, &cd)?; test_serialization(&proof, &vd, &common_data)?;
Ok(()) Ok(())
} }
@ -266,10 +266,10 @@ mod tests {
type F = <C as GenericConfig<D>>::F; type F = <C as GenericConfig<D>>::F;
let config = CircuitConfig::standard_recursion_config(); let config = CircuitConfig::standard_recursion_config();
let (proof, vd, cd) = dummy_too_many_rows_proof::<F, C, D>(&config)?; let (proof, vd, common_data) = dummy_too_many_rows_proof::<F, C, D>(&config)?;
let (proof, vd, cd) = let (proof, vd, common_data) =
recursive_proof::<F, C, C, D>(proof, vd, cd, &config, None, true, true)?; recursive_proof::<F, C, C, D>(proof, vd, common_data, &config, None, true, true)?;
test_serialization(&proof, &vd, &cd)?; test_serialization(&proof, &vd, &common_data)?;
Ok(()) Ok(())
} }
@ -284,20 +284,20 @@ mod tests {
let config = CircuitConfig::standard_recursion_config(); let config = CircuitConfig::standard_recursion_config();
// Start with a degree 2^14 proof // Start with a degree 2^14 proof
let (proof, vd, cd) = dummy_proof::<F, C, D>(&config, 16_000)?; let (proof, vd, common_data) = dummy_proof::<F, C, D>(&config, 16_000)?;
assert_eq!(cd.degree_bits(), 14); assert_eq!(common_data.degree_bits(), 14);
// Shrink it to 2^13. // Shrink it to 2^13.
let (proof, vd, cd) = let (proof, vd, common_data) =
recursive_proof::<F, C, C, D>(proof, vd, cd, &config, Some(13), false, false)?; recursive_proof::<F, C, C, D>(proof, vd, common_data, &config, Some(13), false, false)?;
assert_eq!(cd.degree_bits(), 13); assert_eq!(common_data.degree_bits(), 13);
// Shrink it to 2^12. // Shrink it to 2^12.
let (proof, vd, cd) = let (proof, vd, common_data) =
recursive_proof::<F, C, C, D>(proof, vd, cd, &config, None, true, true)?; recursive_proof::<F, C, C, D>(proof, vd, common_data, &config, None, true, true)?;
assert_eq!(cd.degree_bits(), 12); assert_eq!(common_data.degree_bits(), 12);
test_serialization(&proof, &vd, &cd)?; test_serialization(&proof, &vd, &common_data)?;
Ok(()) Ok(())
} }
@ -316,13 +316,20 @@ mod tests {
let standard_config = CircuitConfig::standard_recursion_config(); let standard_config = CircuitConfig::standard_recursion_config();
// An initial dummy proof. // An initial dummy proof.
let (proof, vd, cd) = dummy_proof::<F, C, D>(&standard_config, 4_000)?; let (proof, vd, common_data) = dummy_proof::<F, C, D>(&standard_config, 4_000)?;
assert_eq!(cd.degree_bits(), 12); assert_eq!(common_data.degree_bits(), 12);
// A standard recursive proof. // A standard recursive proof.
let (proof, vd, cd) = let (proof, vd, common_data) = recursive_proof::<F, C, C, D>(
recursive_proof::<F, C, C, D>(proof, vd, cd, &standard_config, None, false, false)?; proof,
assert_eq!(cd.degree_bits(), 12); vd,
common_data,
&standard_config,
None,
false,
false,
)?;
assert_eq!(common_data.degree_bits(), 12);
// A high-rate recursive proof, designed to be verifiable with fewer routed wires. // A high-rate recursive proof, designed to be verifiable with fewer routed wires.
let high_rate_config = CircuitConfig { let high_rate_config = CircuitConfig {
@ -334,9 +341,16 @@ mod tests {
}, },
..standard_config ..standard_config
}; };
let (proof, vd, cd) = let (proof, vd, common_data) = recursive_proof::<F, C, C, D>(
recursive_proof::<F, C, C, D>(proof, vd, cd, &high_rate_config, None, true, true)?; proof,
assert_eq!(cd.degree_bits(), 12); vd,
common_data,
&high_rate_config,
None,
true,
true,
)?;
assert_eq!(common_data.degree_bits(), 12);
// A final proof, optimized for size. // A final proof, optimized for size.
let final_config = CircuitConfig { let final_config = CircuitConfig {
@ -350,11 +364,18 @@ mod tests {
}, },
..high_rate_config ..high_rate_config
}; };
let (proof, vd, cd) = let (proof, vd, common_data) = recursive_proof::<F, KC, C, D>(
recursive_proof::<F, KC, C, D>(proof, vd, cd, &final_config, None, true, true)?; proof,
assert_eq!(cd.degree_bits(), 12, "final proof too large"); vd,
common_data,
&final_config,
None,
true,
true,
)?;
assert_eq!(common_data.degree_bits(), 12, "final proof too large");
test_serialization(&proof, &vd, &cd)?; test_serialization(&proof, &vd, &common_data)?;
Ok(()) Ok(())
} }
@ -368,15 +389,15 @@ mod tests {
type F = <PC as GenericConfig<D>>::F; type F = <PC as GenericConfig<D>>::F;
let config = CircuitConfig::standard_recursion_config(); let config = CircuitConfig::standard_recursion_config();
let (proof, vd, cd) = dummy_proof::<F, PC, D>(&config, 4_000)?; let (proof, vd, common_data) = dummy_proof::<F, PC, D>(&config, 4_000)?;
let (proof, vd, cd) = let (proof, vd, common_data) =
recursive_proof::<F, PC, PC, D>(proof, vd, cd, &config, None, false, false)?; recursive_proof::<F, PC, PC, D>(proof, vd, common_data, &config, None, false, false)?;
test_serialization(&proof, &vd, &cd)?; test_serialization(&proof, &vd, &common_data)?;
let (proof, vd, cd) = let (proof, vd, common_data) =
recursive_proof::<F, KC, PC, D>(proof, vd, cd, &config, None, false, false)?; recursive_proof::<F, KC, PC, D>(proof, vd, common_data, &config, None, false, false)?;
test_serialization(&proof, &vd, &cd)?; test_serialization(&proof, &vd, &common_data)?;
Ok(()) Ok(())
} }
@ -662,18 +683,18 @@ mod tests {
>( >(
proof: &ProofWithPublicInputs<F, C, D>, proof: &ProofWithPublicInputs<F, C, D>,
vd: &VerifierOnlyCircuitData<C, D>, vd: &VerifierOnlyCircuitData<C, D>,
cd: &CommonCircuitData<F, D>, common_data: &CommonCircuitData<F, D>,
) -> Result<()> { ) -> Result<()> {
let proof_bytes = proof.to_bytes(); let proof_bytes = proof.to_bytes();
info!("Proof length: {} bytes", proof_bytes.len()); info!("Proof length: {} bytes", proof_bytes.len());
let proof_from_bytes = ProofWithPublicInputs::from_bytes(proof_bytes, cd)?; let proof_from_bytes = ProofWithPublicInputs::from_bytes(proof_bytes, common_data)?;
assert_eq!(proof, &proof_from_bytes); assert_eq!(proof, &proof_from_bytes);
let now = std::time::Instant::now(); let now = std::time::Instant::now();
let compressed_proof = proof.clone().compress(&vd.circuit_digest, cd)?; let compressed_proof = proof.clone().compress(&vd.circuit_digest, common_data)?;
let decompressed_compressed_proof = compressed_proof let decompressed_compressed_proof = compressed_proof
.clone() .clone()
.decompress(&vd.circuit_digest, cd)?; .decompress(&vd.circuit_digest, common_data)?;
info!("{:.4}s to compress proof", now.elapsed().as_secs_f64()); info!("{:.4}s to compress proof", now.elapsed().as_secs_f64());
assert_eq!(proof, &decompressed_compressed_proof); assert_eq!(proof, &decompressed_compressed_proof);
@ -683,7 +704,7 @@ mod tests {
compressed_proof_bytes.len() compressed_proof_bytes.len()
); );
let compressed_proof_from_bytes = let compressed_proof_from_bytes =
CompressedProofWithPublicInputs::from_bytes(compressed_proof_bytes, cd)?; CompressedProofWithPublicInputs::from_bytes(compressed_proof_bytes, common_data)?;
assert_eq!(compressed_proof, compressed_proof_from_bytes); assert_eq!(compressed_proof, compressed_proof_from_bytes);
Ok(()) Ok(())

View File

@ -2,21 +2,31 @@ use plonky2_field::extension::Extendable;
use crate::gates::gate::GateRef; use crate::gates::gate::GateRef;
use crate::hash::hash_types::RichField; use crate::hash::hash_types::RichField;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::util::serialization::{Buffer, IoResult}; use crate::util::serialization::{Buffer, IoResult};
pub trait GateSerializer<F: RichField + Extendable<D>, const D: usize> { pub trait GateSerializer<F: RichField + Extendable<D>, const D: usize> {
fn read_gate(&self, buf: &mut Buffer) -> IoResult<GateRef<F, D>>; fn read_gate(
fn write_gate(&self, buf: &mut Vec<u8>, gate: &GateRef<F, D>) -> IoResult<()>; &self,
buf: &mut Buffer,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<GateRef<F, D>>;
fn write_gate(
&self,
buf: &mut Vec<u8>,
gate: &GateRef<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<()>;
} }
#[macro_export] #[macro_export]
macro_rules! read_gate_impl { macro_rules! read_gate_impl {
($buf:expr, $tag:expr, $($gate_types:ty),+) => {{ ($buf:expr, $tag:expr, $common:expr, $($gate_types:ty),+) => {{
let tag = $tag; let tag = $tag;
let buf = $buf; let buf = $buf;
let mut i = 0..; let mut i = 0..;
$(if tag == i.next().unwrap() { $(if tag == i.next().unwrap() {
let gate = <$gate_types as $crate::gates::gate::Gate<F, D>>::deserialize(buf)?; let gate = <$gate_types as $crate::gates::gate::Gate<F, D>>::deserialize(buf, $common)?;
Ok($crate::gates::gate::GateRef::<F, D>::new(gate)) Ok($crate::gates::gate::GateRef::<F, D>::new(gate))
} else)* } else)*
{ {
@ -47,16 +57,25 @@ macro_rules! get_gate_tag_impl {
/// this as first argument, followed by all the targeted gates. /// this as first argument, followed by all the targeted gates.
macro_rules! impl_gate_serializer { macro_rules! impl_gate_serializer {
($target:ty, $($gate_types:ty),+) => { ($target:ty, $($gate_types:ty),+) => {
fn read_gate(&self, buf: &mut $crate::util::serialization::Buffer) -> $crate::util::serialization::IoResult<$crate::gates::gate::GateRef<F, D>> { fn read_gate(
&self,
buf: &mut $crate::util::serialization::Buffer,
common: &$crate::plonk::circuit_data::CommonCircuitData<F, D>,
) -> $crate::util::serialization::IoResult<$crate::gates::gate::GateRef<F, D>> {
let tag = $crate::util::serialization::Read::read_u32(buf)?; let tag = $crate::util::serialization::Read::read_u32(buf)?;
read_gate_impl!(buf, tag, $($gate_types),+) read_gate_impl!(buf, tag, common, $($gate_types),+)
} }
fn write_gate(&self, buf: &mut Vec<u8>, gate: &$crate::gates::gate::GateRef<F, D>) -> $crate::util::serialization::IoResult<()> { fn write_gate(
&self,
buf: &mut Vec<u8>,
gate: &$crate::gates::gate::GateRef<F, D>,
common: &$crate::plonk::circuit_data::CommonCircuitData<F, D>,
) -> $crate::util::serialization::IoResult<()> {
let tag = get_gate_tag_impl!(gate, $($gate_types),+)?; let tag = get_gate_tag_impl!(gate, $($gate_types),+)?;
$crate::util::serialization::Write::write_u32(buf, tag)?; $crate::util::serialization::Write::write_u32(buf, tag)?;
gate.0.serialize(buf)?; gate.0.serialize(buf, common)?;
Ok(()) Ok(())
} }
}; };

View File

@ -11,12 +11,14 @@ pub trait WitnessGeneratorSerializer<F: RichField + Extendable<D>, const D: usiz
fn read_generator( fn read_generator(
&self, &self,
buf: &mut Buffer, buf: &mut Buffer,
common: &CommonCircuitData<F, D>, common_data: &CommonCircuitData<F, D>,
) -> IoResult<WitnessGeneratorRef<F>>; ) -> IoResult<WitnessGeneratorRef<F, D>>;
fn write_generator( fn write_generator(
&self, &self,
buf: &mut Vec<u8>, buf: &mut Vec<u8>,
generator: &WitnessGeneratorRef<F>, generator: &WitnessGeneratorRef<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<()>; ) -> IoResult<()>;
} }
@ -27,19 +29,11 @@ macro_rules! read_generator_impl {
let buf = $buf; let buf = $buf;
let mut i = 0..; let mut i = 0..;
if tag == 0 {
let generator: $crate::recursion::dummy_circuit::DummyProofGenerator<F, C, D> =
$crate::recursion::dummy_circuit::DummyProofGenerator::deserialize_with_circuit_data(buf, $common)?;
return Ok($crate::iop::generator::WitnessGeneratorRef::<F>::new(
$crate::iop::generator::SimpleGenerator::<F>::adapter(generator),
));
}
$(if tag == i.next().unwrap() { $(if tag == i.next().unwrap() {
let generator = let generator =
<$generator_types as $crate::iop::generator::SimpleGenerator<F>>::deserialize(buf)?; <$generator_types as $crate::iop::generator::SimpleGenerator<F, D>>::deserialize(buf, $common)?;
Ok($crate::iop::generator::WitnessGeneratorRef::<F>::new( Ok($crate::iop::generator::WitnessGeneratorRef::<F, D>::new(
$crate::iop::generator::SimpleGenerator::<F>::adapter(generator), $crate::iop::generator::SimpleGenerator::<F, D>::adapter(generator),
)) ))
} else)* } else)*
{ {
@ -52,7 +46,7 @@ macro_rules! read_generator_impl {
macro_rules! get_generator_tag_impl { macro_rules! get_generator_tag_impl {
($generator:expr, $($generator_types:ty),+) => {{ ($generator:expr, $($generator_types:ty),+) => {{
let mut i = 0..; let mut i = 0..;
$(if let (tag, true) = (i.next().unwrap(), $generator.0.id() == $crate::iop::generator::SimpleGenerator::<F>::id(&<$generator_types>::default())) { $(if let (tag, true) = (i.next().unwrap(), $generator.0.id() == $crate::iop::generator::SimpleGenerator::<F, D>::id(&<$generator_types>::default())) {
Ok(tag) Ok(tag)
} else)* } else)*
{ {
@ -67,17 +61,13 @@ macro_rules! get_generator_tag_impl {
/// To serialize a list of generators used for a circuit, /// To serialize a list of generators used for a circuit,
/// this macro should be called with a struct on which to implement /// this macro should be called with a struct on which to implement
/// this as first argument, followed by all the targeted generators. /// this as first argument, followed by all the targeted generators.
///
/// ***NOTE:*** If you need to include `DummyProofGenerator`, you **MUST**
/// place it at the *beginning* of the generators list, right after
/// the serializer struct.
macro_rules! impl_generator_serializer { macro_rules! impl_generator_serializer {
($target:ty, $($generator_types:ty),+) => { ($target:ty, $($generator_types:ty),+) => {
fn read_generator( fn read_generator(
&self, &self,
buf: &mut $crate::util::serialization::Buffer, buf: &mut $crate::util::serialization::Buffer,
common: &$crate::plonk::circuit_data::CommonCircuitData<F, D>, common: &$crate::plonk::circuit_data::CommonCircuitData<F, D>,
) -> $crate::util::serialization::IoResult<$crate::iop::generator::WitnessGeneratorRef<F>> { ) -> $crate::util::serialization::IoResult<$crate::iop::generator::WitnessGeneratorRef<F, D>> {
let tag = $crate::util::serialization::Read::read_u32(buf)?; let tag = $crate::util::serialization::Read::read_u32(buf)?;
read_generator_impl!(buf, tag, common, $($generator_types),+) read_generator_impl!(buf, tag, common, $($generator_types),+)
} }
@ -85,12 +75,13 @@ macro_rules! impl_generator_serializer {
fn write_generator( fn write_generator(
&self, &self,
buf: &mut Vec<u8>, buf: &mut Vec<u8>,
generator: &$crate::iop::generator::WitnessGeneratorRef<F>, generator: &$crate::iop::generator::WitnessGeneratorRef<F, D>,
common: &$crate::plonk::circuit_data::CommonCircuitData<F, D>,
) -> $crate::util::serialization::IoResult<()> { ) -> $crate::util::serialization::IoResult<()> {
let tag = get_generator_tag_impl!(generator, $($generator_types),+)?; let tag = get_generator_tag_impl!(generator, $($generator_types),+)?;
$crate::util::serialization::Write::write_u32(buf, tag)?; $crate::util::serialization::Write::write_u32(buf, tag)?;
generator.0.serialize(buf)?; generator.0.serialize(buf, common)?;
Ok(()) Ok(())
} }
}; };
@ -139,13 +130,13 @@ pub mod default {
{ {
impl_generator_serializer! { impl_generator_serializer! {
DefaultGeneratorSerializer, DefaultGeneratorSerializer,
DummyProofGenerator<F, C, D>,
ArithmeticBaseGenerator<F, D>, ArithmeticBaseGenerator<F, D>,
ArithmeticExtensionGenerator<F, D>, ArithmeticExtensionGenerator<F, D>,
BaseSplitGenerator<2>, BaseSplitGenerator<2>,
BaseSumGenerator<2>, BaseSumGenerator<2>,
ConstantGenerator<F>, ConstantGenerator<F>,
CopyGenerator, CopyGenerator,
DummyProofGenerator<F, C, D>,
EqualityGenerator, EqualityGenerator,
ExponentiationGenerator<F, D>, ExponentiationGenerator<F, D>,
InterpolationGenerator<F, D>, InterpolationGenerator<F, D>,

View File

@ -684,13 +684,14 @@ pub trait Read {
fn read_gate<F: RichField + Extendable<D>, const D: usize>( fn read_gate<F: RichField + Extendable<D>, const D: usize>(
&mut self, &mut self,
gate_serializer: &dyn GateSerializer<F, D>, gate_serializer: &dyn GateSerializer<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<GateRef<F, D>>; ) -> IoResult<GateRef<F, D>>;
fn read_generator<F: RichField + Extendable<D>, const D: usize>( fn read_generator<F: RichField + Extendable<D>, const D: usize>(
&mut self, &mut self,
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>, generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
common_data: &CommonCircuitData<F, D>, common_data: &CommonCircuitData<F, D>,
) -> IoResult<WitnessGeneratorRef<F>>; ) -> IoResult<WitnessGeneratorRef<F, D>>;
fn read_selectors_info(&mut self) -> IoResult<SelectorsInfo> { fn read_selectors_info(&mut self) -> IoResult<SelectorsInfo> {
let selector_indices = self.read_usize_vec()?; let selector_indices = self.read_usize_vec()?;
@ -743,13 +744,6 @@ pub trait Read {
let config = self.read_circuit_config()?; let config = self.read_circuit_config()?;
let fri_params = self.read_fri_params()?; let fri_params = self.read_fri_params()?;
let gates_len = self.read_usize()?;
let mut gates = Vec::with_capacity(gates_len);
for _ in 0..gates_len {
let gate = self.read_gate::<F, D>(gate_serializer)?;
gates.push(gate);
}
let selectors_info = self.read_selectors_info()?; let selectors_info = self.read_selectors_info()?;
let quotient_degree_factor = self.read_usize()?; let quotient_degree_factor = self.read_usize()?;
let num_gate_constraints = self.read_usize()?; let num_gate_constraints = self.read_usize()?;
@ -770,10 +764,15 @@ pub trait Read {
luts.push(Arc::new(self.read_lut()?)); luts.push(Arc::new(self.read_lut()?));
} }
Ok(CommonCircuitData { let gates_len = self.read_usize()?;
let mut gates = Vec::with_capacity(gates_len);
// We construct the common data without gates first,
// to pass it as argument when reading the gates.
let mut common_data = CommonCircuitData {
config, config,
fri_params, fri_params,
gates, gates: vec![],
selectors_info, selectors_info,
quotient_degree_factor, quotient_degree_factor,
num_gate_constraints, num_gate_constraints,
@ -784,7 +783,16 @@ pub trait Read {
num_lookup_polys, num_lookup_polys,
num_lookup_selectors, num_lookup_selectors,
luts, luts,
}) };
for _ in 0..gates_len {
let gate = self.read_gate::<F, D>(gate_serializer, &common_data)?;
gates.push(gate);
}
common_data.gates = gates;
Ok(common_data)
} }
fn read_circuit_data< fn read_circuit_data<
@ -813,12 +821,12 @@ pub trait Read {
>( >(
&mut self, &mut self,
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>, generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
cd: &CommonCircuitData<F, D>, common_data: &CommonCircuitData<F, D>,
) -> IoResult<ProverOnlyCircuitData<F, C, D>> { ) -> IoResult<ProverOnlyCircuitData<F, C, D>> {
let gen_len = self.read_usize()?; let gen_len = self.read_usize()?;
let mut generators = Vec::with_capacity(gen_len); let mut generators = Vec::with_capacity(gen_len);
for _ in 0..gen_len { for _ in 0..gen_len {
generators.push(self.read_generator(generator_serializer, cd)?); generators.push(self.read_generator(generator_serializer, common_data)?);
} }
let map_len = self.read_usize()?; let map_len = self.read_usize()?;
let mut generator_indices_by_watches = BTreeMap::new(); let mut generator_indices_by_watches = BTreeMap::new();
@ -1689,12 +1697,14 @@ pub trait Write {
&mut self, &mut self,
gate: &GateRef<F, D>, gate: &GateRef<F, D>,
gate_serializer: &dyn GateSerializer<F, D>, gate_serializer: &dyn GateSerializer<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<()>; ) -> IoResult<()>;
fn write_generator<F: RichField + Extendable<D>, const D: usize>( fn write_generator<F: RichField + Extendable<D>, const D: usize>(
&mut self, &mut self,
generator: &WitnessGeneratorRef<F>, generator: &WitnessGeneratorRef<F, D>,
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>, generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<()>; ) -> IoResult<()>;
fn write_selectors_info(&mut self, selectors_info: &SelectorsInfo) -> IoResult<()> { fn write_selectors_info(&mut self, selectors_info: &SelectorsInfo) -> IoResult<()> {
@ -1757,11 +1767,6 @@ pub trait Write {
self.write_circuit_config(config)?; self.write_circuit_config(config)?;
self.write_fri_params(fri_params)?; self.write_fri_params(fri_params)?;
self.write_usize(gates.len())?;
for gate in gates.iter() {
self.write_gate::<F, D>(gate, gate_serializer)?;
}
self.write_selectors_info(selectors_info)?; self.write_selectors_info(selectors_info)?;
self.write_usize(*quotient_degree_factor)?; self.write_usize(*quotient_degree_factor)?;
self.write_usize(*num_gate_constraints)?; self.write_usize(*num_gate_constraints)?;
@ -1780,6 +1785,11 @@ pub trait Write {
self.write_lut(lut)?; self.write_lut(lut)?;
} }
self.write_usize(gates.len())?;
for gate in gates.iter() {
self.write_gate::<F, D>(gate, gate_serializer, common_data)?;
}
Ok(()) Ok(())
} }
@ -1794,7 +1804,11 @@ pub trait Write {
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>, generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
) -> IoResult<()> { ) -> IoResult<()> {
self.write_common_circuit_data(&circuit_data.common, gate_serializer)?; self.write_common_circuit_data(&circuit_data.common, gate_serializer)?;
self.write_prover_only_circuit_data(&circuit_data.prover_only, generator_serializer)?; self.write_prover_only_circuit_data(
&circuit_data.prover_only,
generator_serializer,
&circuit_data.common,
)?;
self.write_verifier_only_circuit_data(&circuit_data.verifier_only) self.write_verifier_only_circuit_data(&circuit_data.verifier_only)
} }
@ -1806,6 +1820,7 @@ pub trait Write {
&mut self, &mut self,
prover_only_circuit_data: &ProverOnlyCircuitData<F, C, D>, prover_only_circuit_data: &ProverOnlyCircuitData<F, C, D>,
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>, generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<()> { ) -> IoResult<()> {
let ProverOnlyCircuitData { let ProverOnlyCircuitData {
generators, generators,
@ -1823,7 +1838,7 @@ pub trait Write {
self.write_usize(generators.len())?; self.write_usize(generators.len())?;
for generator in generators.iter() { for generator in generators.iter() {
self.write_generator::<F, D>(generator, generator_serializer)?; self.write_generator::<F, D>(generator, generator_serializer, common_data)?;
} }
self.write_usize(generator_indices_by_watches.len())?; self.write_usize(generator_indices_by_watches.len())?;
@ -1883,7 +1898,11 @@ pub trait Write {
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>, generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
) -> IoResult<()> { ) -> IoResult<()> {
self.write_common_circuit_data(&prover_circuit_data.common, gate_serializer)?; self.write_common_circuit_data(&prover_circuit_data.common, gate_serializer)?;
self.write_prover_only_circuit_data(&prover_circuit_data.prover_only, generator_serializer) self.write_prover_only_circuit_data(
&prover_circuit_data.prover_only,
generator_serializer,
&prover_circuit_data.common,
)
} }
fn write_verifier_only_circuit_data< fn write_verifier_only_circuit_data<
@ -2110,16 +2129,18 @@ impl Write for Vec<u8> {
&mut self, &mut self,
gate: &GateRef<F, D>, gate: &GateRef<F, D>,
gate_serializer: &dyn GateSerializer<F, D>, gate_serializer: &dyn GateSerializer<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<()> { ) -> IoResult<()> {
gate_serializer.write_gate(self, gate) gate_serializer.write_gate(self, gate, common_data)
} }
fn write_generator<F: RichField + Extendable<D>, const D: usize>( fn write_generator<F: RichField + Extendable<D>, const D: usize>(
&mut self, &mut self,
generator: &WitnessGeneratorRef<F>, generator: &WitnessGeneratorRef<F, D>,
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>, generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<()> { ) -> IoResult<()> {
generator_serializer.write_generator(self, generator) generator_serializer.write_generator(self, generator, common_data)
} }
} }
@ -2178,15 +2199,16 @@ impl<'a> Read for Buffer<'a> {
fn read_gate<F: RichField + Extendable<D>, const D: usize>( fn read_gate<F: RichField + Extendable<D>, const D: usize>(
&mut self, &mut self,
gate_serializer: &dyn GateSerializer<F, D>, gate_serializer: &dyn GateSerializer<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> IoResult<GateRef<F, D>> { ) -> IoResult<GateRef<F, D>> {
gate_serializer.read_gate(self) gate_serializer.read_gate(self, common_data)
} }
fn read_generator<F: RichField + Extendable<D>, const D: usize>( fn read_generator<F: RichField + Extendable<D>, const D: usize>(
&mut self, &mut self,
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>, generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
common_data: &CommonCircuitData<F, D>, common_data: &CommonCircuitData<F, D>,
) -> IoResult<WitnessGeneratorRef<F>> { ) -> IoResult<WitnessGeneratorRef<F, D>> {
generator_serializer.read_generator(self, common_data) generator_serializer.read_generator(self, common_data)
} }
} }