mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 14:53:08 +00:00
Add serialisation support for gates, generators, and various structs
Co-authored-by: Sebastien La Duca <sladuca777@gmail.com>
This commit is contained in:
parent
f7f5fb4e93
commit
f71139d934
@ -1,3 +1,4 @@
|
||||
use core::mem::{self, MaybeUninit};
|
||||
use std::collections::BTreeMap;
|
||||
use std::ops::Range;
|
||||
|
||||
@ -19,6 +20,9 @@ use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, Hasher};
|
||||
use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
|
||||
use plonky2::recursion::cyclic_recursion::check_cyclic_proof_verifier_data;
|
||||
use plonky2::recursion::dummy_circuit::cyclic_base_proof;
|
||||
use plonky2::util::gate_serialization::GateSerializer;
|
||||
use plonky2::util::generator_serialization::WitnessGeneratorSerializer;
|
||||
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
use plonky2::util::timing::TimingTree;
|
||||
use plonky2_util::log2_ceil;
|
||||
|
||||
@ -47,6 +51,7 @@ const THRESHOLD_DEGREE_BITS: usize = 13;
|
||||
/// `degree_bits`, this contains a chain of recursive circuits for shrinking that STARK from
|
||||
/// `degree_bits` to a constant `THRESHOLD_DEGREE_BITS`. It also contains a special root circuit
|
||||
/// for combining each STARK's shrunk wrapper proof into a single proof.
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct AllRecursiveCircuits<F, C, const D: usize>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
@ -64,12 +69,13 @@ where
|
||||
|
||||
/// Data for the EVM root circuit, which is used to combine each STARK's shrunk wrapper proof
|
||||
/// into a single proof.
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct RootCircuitData<F, C, const D: usize>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
{
|
||||
circuit: CircuitData<F, C, D>,
|
||||
pub circuit: CircuitData<F, C, D>,
|
||||
proof_with_pis: [ProofWithPublicInputsTarget<D>; NUM_TABLES],
|
||||
/// For each table, various inner circuits may be used depending on the initial table size.
|
||||
/// This target holds the index of the circuit (within `final_circuits()`) that was used.
|
||||
@ -79,37 +85,182 @@ where
|
||||
cyclic_vk: VerifierCircuitTarget,
|
||||
}
|
||||
|
||||
impl<F, C, const D: usize> RootCircuitData<F, C, D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
{
|
||||
pub fn to_buffer(
|
||||
&self,
|
||||
buffer: &mut Vec<u8>,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<()> {
|
||||
buffer.write_circuit_data(&self.circuit, gate_serializer, generator_serializer)?;
|
||||
for proof in &self.proof_with_pis {
|
||||
buffer.write_target_proof_with_public_inputs(proof)?;
|
||||
}
|
||||
for index in self.index_verifier_data {
|
||||
buffer.write_target(index)?;
|
||||
}
|
||||
buffer.write_target_verifier_circuit(&self.cyclic_vk)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn from_buffer(
|
||||
buffer: &mut Buffer,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Self> {
|
||||
let circuit = buffer.read_circuit_data(gate_serializer, generator_serializer)?;
|
||||
let mut proof_with_pis = Vec::with_capacity(NUM_TABLES);
|
||||
for _ in 0..NUM_TABLES {
|
||||
proof_with_pis.push(buffer.read_target_proof_with_public_inputs()?);
|
||||
}
|
||||
let mut index_verifier_data = Vec::with_capacity(NUM_TABLES);
|
||||
for _ in 0..NUM_TABLES {
|
||||
index_verifier_data.push(buffer.read_target()?);
|
||||
}
|
||||
let cyclic_vk = buffer.read_target_verifier_circuit()?;
|
||||
|
||||
Ok(Self {
|
||||
circuit,
|
||||
proof_with_pis: proof_with_pis.try_into().unwrap(),
|
||||
index_verifier_data: index_verifier_data.try_into().unwrap(),
|
||||
cyclic_vk,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Data for the aggregation circuit, which is used to compress two proofs into one. Each inner
|
||||
/// proof can be either an EVM root proof or another aggregation proof.
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct AggregationCircuitData<F, C, const D: usize>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
{
|
||||
circuit: CircuitData<F, C, D>,
|
||||
pub circuit: CircuitData<F, C, D>,
|
||||
lhs: AggregationChildTarget<D>,
|
||||
rhs: AggregationChildTarget<D>,
|
||||
cyclic_vk: VerifierCircuitTarget,
|
||||
}
|
||||
|
||||
impl<F, C, const D: usize> AggregationCircuitData<F, C, D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
{
|
||||
pub fn to_buffer(
|
||||
&self,
|
||||
buffer: &mut Vec<u8>,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<()> {
|
||||
buffer.write_circuit_data(&self.circuit, gate_serializer, generator_serializer)?;
|
||||
buffer.write_target_verifier_circuit(&self.cyclic_vk)?;
|
||||
self.lhs.to_buffer(buffer)?;
|
||||
self.rhs.to_buffer(buffer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn from_buffer(
|
||||
buffer: &mut Buffer,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Self> {
|
||||
let circuit = buffer.read_circuit_data(gate_serializer, generator_serializer)?;
|
||||
let cyclic_vk = buffer.read_target_verifier_circuit()?;
|
||||
let lhs = AggregationChildTarget::from_buffer(buffer)?;
|
||||
let rhs = AggregationChildTarget::from_buffer(buffer)?;
|
||||
Ok(Self {
|
||||
circuit,
|
||||
lhs,
|
||||
rhs,
|
||||
cyclic_vk,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct AggregationChildTarget<const D: usize> {
|
||||
is_agg: BoolTarget,
|
||||
agg_proof: ProofWithPublicInputsTarget<D>,
|
||||
evm_proof: ProofWithPublicInputsTarget<D>,
|
||||
}
|
||||
|
||||
impl<const D: usize> AggregationChildTarget<D> {
|
||||
pub fn to_buffer(&self, buffer: &mut Vec<u8>) -> IoResult<()> {
|
||||
buffer.write_target_bool(self.is_agg)?;
|
||||
buffer.write_target_proof_with_public_inputs(&self.agg_proof)?;
|
||||
buffer.write_target_proof_with_public_inputs(&self.evm_proof)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn from_buffer(buffer: &mut Buffer) -> IoResult<Self> {
|
||||
let is_agg = buffer.read_target_bool()?;
|
||||
let agg_proof = buffer.read_target_proof_with_public_inputs()?;
|
||||
let evm_proof = buffer.read_target_proof_with_public_inputs()?;
|
||||
Ok(Self {
|
||||
is_agg,
|
||||
agg_proof,
|
||||
evm_proof,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct BlockCircuitData<F, C, const D: usize>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
{
|
||||
circuit: CircuitData<F, C, D>,
|
||||
pub circuit: CircuitData<F, C, D>,
|
||||
has_parent_block: BoolTarget,
|
||||
parent_block_proof: ProofWithPublicInputsTarget<D>,
|
||||
agg_root_proof: ProofWithPublicInputsTarget<D>,
|
||||
cyclic_vk: VerifierCircuitTarget,
|
||||
}
|
||||
|
||||
impl<F, C, const D: usize> BlockCircuitData<F, C, D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
{
|
||||
pub fn to_buffer(
|
||||
&self,
|
||||
buffer: &mut Vec<u8>,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<()> {
|
||||
buffer.write_circuit_data(&self.circuit, gate_serializer, generator_serializer)?;
|
||||
buffer.write_target_bool(self.has_parent_block)?;
|
||||
buffer.write_target_proof_with_public_inputs(&self.parent_block_proof)?;
|
||||
buffer.write_target_proof_with_public_inputs(&self.agg_root_proof)?;
|
||||
buffer.write_target_verifier_circuit(&self.cyclic_vk)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn from_buffer(
|
||||
buffer: &mut Buffer,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Self> {
|
||||
let circuit = buffer.read_circuit_data(gate_serializer, generator_serializer)?;
|
||||
let has_parent_block = buffer.read_target_bool()?;
|
||||
let parent_block_proof = buffer.read_target_proof_with_public_inputs()?;
|
||||
let agg_root_proof = buffer.read_target_proof_with_public_inputs()?;
|
||||
let cyclic_vk = buffer.read_target_verifier_circuit()?;
|
||||
Ok(Self {
|
||||
circuit,
|
||||
has_parent_block,
|
||||
parent_block_proof,
|
||||
agg_root_proof,
|
||||
cyclic_vk,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, C, const D: usize> AllRecursiveCircuits<F, C, D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
@ -124,6 +275,67 @@ where
|
||||
[(); C::HCO::WIDTH]:,
|
||||
[(); C::HCI::WIDTH]:,
|
||||
{
|
||||
pub fn to_bytes(
|
||||
&self,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Vec<u8>> {
|
||||
// TODO: would be better to initialize it dynamically based on the supported max degree.
|
||||
let mut buffer = Vec::with_capacity(1 << 34);
|
||||
self.root
|
||||
.to_buffer(&mut buffer, gate_serializer, generator_serializer)?;
|
||||
self.aggregation
|
||||
.to_buffer(&mut buffer, gate_serializer, generator_serializer)?;
|
||||
self.block
|
||||
.to_buffer(&mut buffer, gate_serializer, generator_serializer)?;
|
||||
for table in &self.by_table {
|
||||
table.to_buffer(&mut buffer, gate_serializer, generator_serializer)?;
|
||||
}
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
pub fn from_bytes(
|
||||
bytes: &[u8],
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Self> {
|
||||
let mut buffer = Buffer::new(bytes.to_vec());
|
||||
let root =
|
||||
RootCircuitData::from_buffer(&mut buffer, gate_serializer, generator_serializer)?;
|
||||
let aggregation = AggregationCircuitData::from_buffer(
|
||||
&mut buffer,
|
||||
gate_serializer,
|
||||
generator_serializer,
|
||||
)?;
|
||||
let block =
|
||||
BlockCircuitData::from_buffer(&mut buffer, gate_serializer, generator_serializer)?;
|
||||
|
||||
// Tricky use of MaybeUninit to remove the need for implementing Debug
|
||||
// for all underlying types, necessary to convert a by_table Vec to an array.
|
||||
let by_table = {
|
||||
let mut by_table: [MaybeUninit<RecursiveCircuitsForTable<F, C, D>>; NUM_TABLES] =
|
||||
unsafe { MaybeUninit::uninit().assume_init() };
|
||||
for table in &mut by_table[..] {
|
||||
let value = RecursiveCircuitsForTable::from_buffer(
|
||||
&mut buffer,
|
||||
gate_serializer,
|
||||
generator_serializer,
|
||||
)?;
|
||||
*table = MaybeUninit::new(value);
|
||||
}
|
||||
unsafe {
|
||||
mem::transmute::<_, [RecursiveCircuitsForTable<F, C, D>; NUM_TABLES]>(by_table)
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
root,
|
||||
aggregation,
|
||||
block,
|
||||
by_table,
|
||||
})
|
||||
}
|
||||
|
||||
/// Preprocess all recursive circuits used by the system.
|
||||
pub fn new(
|
||||
all_stark: &AllStark<F, D>,
|
||||
@ -484,7 +696,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
struct RecursiveCircuitsForTable<F, C, const D: usize>
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct RecursiveCircuitsForTable<F, C, const D: usize>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
@ -504,6 +717,39 @@ where
|
||||
[(); C::HCO::WIDTH]:,
|
||||
[(); C::HCI::WIDTH]:,
|
||||
{
|
||||
pub fn to_buffer(
|
||||
&self,
|
||||
buffer: &mut Vec<u8>,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<()> {
|
||||
buffer.write_usize(self.by_stark_size.len())?;
|
||||
for (&size, table) in &self.by_stark_size {
|
||||
buffer.write_usize(size)?;
|
||||
table.to_buffer(buffer, gate_serializer, generator_serializer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn from_buffer(
|
||||
buffer: &mut Buffer,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Self> {
|
||||
let length = buffer.read_usize()?;
|
||||
let mut by_stark_size = BTreeMap::new();
|
||||
for _ in 0..length {
|
||||
let key = buffer.read_usize()?;
|
||||
let table = RecursiveCircuitsForTableSize::from_buffer(
|
||||
buffer,
|
||||
gate_serializer,
|
||||
generator_serializer,
|
||||
)?;
|
||||
by_stark_size.insert(key, table);
|
||||
}
|
||||
Ok(Self { by_stark_size })
|
||||
}
|
||||
|
||||
fn new<S: Stark<F, D>>(
|
||||
table: Table,
|
||||
stark: &S,
|
||||
@ -549,6 +795,7 @@ where
|
||||
|
||||
/// A chain of shrinking wrapper circuits, ending with a final circuit with `degree_bits`
|
||||
/// `THRESHOLD_DEGREE_BITS`.
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
struct RecursiveCircuitsForTableSize<F, C, const D: usize>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
@ -568,6 +815,67 @@ where
|
||||
[(); C::HCO::WIDTH]:,
|
||||
[(); C::HCI::WIDTH]:,
|
||||
{
|
||||
pub fn to_buffer(
|
||||
&self,
|
||||
buffer: &mut Vec<u8>,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<()> {
|
||||
buffer.write_usize(self.shrinking_wrappers.len())?;
|
||||
if !self.shrinking_wrappers.is_empty() {
|
||||
buffer.write_common_circuit_data(
|
||||
&self.shrinking_wrappers[0].circuit.common,
|
||||
gate_serializer,
|
||||
)?;
|
||||
}
|
||||
for wrapper in &self.shrinking_wrappers {
|
||||
buffer.write_prover_only_circuit_data(
|
||||
&wrapper.circuit.prover_only,
|
||||
generator_serializer,
|
||||
)?;
|
||||
buffer.write_verifier_only_circuit_data(&wrapper.circuit.verifier_only)?;
|
||||
buffer.write_target_proof_with_public_inputs(&wrapper.proof_with_pis_target)?;
|
||||
}
|
||||
self.initial_wrapper
|
||||
.to_buffer(buffer, gate_serializer, generator_serializer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn from_buffer(
|
||||
buffer: &mut Buffer,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Self> {
|
||||
let length = buffer.read_usize()?;
|
||||
let mut shrinking_wrappers = Vec::with_capacity(length);
|
||||
if length != 0 {
|
||||
let common = buffer.read_common_circuit_data(gate_serializer)?;
|
||||
|
||||
for _ in 0..length {
|
||||
let prover_only =
|
||||
buffer.read_prover_only_circuit_data(generator_serializer, &common)?;
|
||||
let verifier_only = buffer.read_verifier_only_circuit_data()?;
|
||||
let proof_with_pis_target = buffer.read_target_proof_with_public_inputs()?;
|
||||
shrinking_wrappers.push(PlonkWrapperCircuit {
|
||||
circuit: CircuitData {
|
||||
common: common.clone(),
|
||||
prover_only,
|
||||
verifier_only,
|
||||
},
|
||||
proof_with_pis_target,
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let initial_wrapper =
|
||||
StarkWrapperCircuit::from_buffer(buffer, gate_serializer, generator_serializer)?;
|
||||
|
||||
Ok(Self {
|
||||
initial_wrapper,
|
||||
shrinking_wrappers,
|
||||
})
|
||||
}
|
||||
|
||||
fn new<S: Stark<F, D>>(
|
||||
table: Table,
|
||||
stark: &S,
|
||||
|
||||
@ -17,6 +17,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::config::{AlgebraicHasher, Hasher};
|
||||
use plonky2::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_circuit};
|
||||
use plonky2::util::reducing::{ReducingFactor, ReducingFactorTarget};
|
||||
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
use plonky2_maybe_rayon::*;
|
||||
|
||||
use crate::config::StarkConfig;
|
||||
@ -89,6 +90,30 @@ pub(crate) struct GrandProductChallengeSet<T: Copy + Eq + PartialEq + Debug> {
|
||||
pub(crate) challenges: Vec<GrandProductChallenge<T>>,
|
||||
}
|
||||
|
||||
impl GrandProductChallengeSet<Target> {
|
||||
pub fn to_buffer(&self, buffer: &mut Vec<u8>) -> IoResult<()> {
|
||||
buffer.write_usize(self.challenges.len())?;
|
||||
for challenge in &self.challenges {
|
||||
buffer.write_target(challenge.beta)?;
|
||||
buffer.write_target(challenge.gamma)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn from_buffer(buffer: &mut Buffer) -> IoResult<Self> {
|
||||
let length = buffer.read_usize()?;
|
||||
let mut challenges = Vec::with_capacity(length);
|
||||
for _ in 0..length {
|
||||
challenges.push(GrandProductChallenge {
|
||||
beta: buffer.read_target()?,
|
||||
gamma: buffer.read_target()?,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(GrandProductChallengeSet { challenges })
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute all Z polynomials (for permutation arguments).
|
||||
pub(crate) fn compute_permutation_z_polys<F, S, const D: usize>(
|
||||
stark: &S,
|
||||
|
||||
@ -12,6 +12,7 @@ use plonky2::hash::merkle_tree::MerkleCap;
|
||||
use plonky2::iop::ext_target::ExtensionTarget;
|
||||
use plonky2::iop::target::Target;
|
||||
use plonky2::plonk::config::GenericConfig;
|
||||
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
use plonky2_maybe_rayon::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -148,6 +149,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> S
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct StarkProofTarget<const D: usize> {
|
||||
pub trace_cap: MerkleCapTarget,
|
||||
pub permutation_ctl_zs_cap: MerkleCapTarget,
|
||||
@ -157,6 +159,31 @@ pub struct StarkProofTarget<const D: usize> {
|
||||
}
|
||||
|
||||
impl<const D: usize> StarkProofTarget<D> {
|
||||
pub fn to_buffer(&self, buffer: &mut Vec<u8>) -> IoResult<()> {
|
||||
buffer.write_target_merkle_cap(&self.trace_cap)?;
|
||||
buffer.write_target_merkle_cap(&self.permutation_ctl_zs_cap)?;
|
||||
buffer.write_target_merkle_cap(&self.quotient_polys_cap)?;
|
||||
buffer.write_target_fri_proof(&self.opening_proof)?;
|
||||
self.openings.to_buffer(buffer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn from_buffer(buffer: &mut Buffer) -> IoResult<Self> {
|
||||
let trace_cap = buffer.read_target_merkle_cap()?;
|
||||
let permutation_ctl_zs_cap = buffer.read_target_merkle_cap()?;
|
||||
let quotient_polys_cap = buffer.read_target_merkle_cap()?;
|
||||
let opening_proof = buffer.read_target_fri_proof()?;
|
||||
let openings = StarkOpeningSetTarget::from_buffer(buffer)?;
|
||||
|
||||
Ok(Self {
|
||||
trace_cap,
|
||||
permutation_ctl_zs_cap,
|
||||
quotient_polys_cap,
|
||||
openings,
|
||||
opening_proof,
|
||||
})
|
||||
}
|
||||
|
||||
/// Recover the length of the trace from a STARK proof and a STARK config.
|
||||
pub fn recover_degree_bits(&self, config: &StarkConfig) -> usize {
|
||||
let initial_merkle_proof = &self.opening_proof.query_round_proofs[0]
|
||||
@ -276,6 +303,7 @@ impl<F: RichField + Extendable<D>, const D: usize> StarkOpeningSet<F, D> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct StarkOpeningSetTarget<const D: usize> {
|
||||
pub local_values: Vec<ExtensionTarget<D>>,
|
||||
pub next_values: Vec<ExtensionTarget<D>>,
|
||||
@ -286,6 +314,34 @@ pub struct StarkOpeningSetTarget<const D: usize> {
|
||||
}
|
||||
|
||||
impl<const D: usize> StarkOpeningSetTarget<D> {
|
||||
pub fn to_buffer(&self, buffer: &mut Vec<u8>) -> IoResult<()> {
|
||||
buffer.write_target_ext_vec(&self.local_values)?;
|
||||
buffer.write_target_ext_vec(&self.next_values)?;
|
||||
buffer.write_target_ext_vec(&self.permutation_ctl_zs)?;
|
||||
buffer.write_target_ext_vec(&self.permutation_ctl_zs_next)?;
|
||||
buffer.write_target_vec(&self.ctl_zs_last)?;
|
||||
buffer.write_target_ext_vec(&self.quotient_polys)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn from_buffer(buffer: &mut Buffer) -> IoResult<Self> {
|
||||
let local_values = buffer.read_target_ext_vec::<D>()?;
|
||||
let next_values = buffer.read_target_ext_vec::<D>()?;
|
||||
let permutation_ctl_zs = buffer.read_target_ext_vec::<D>()?;
|
||||
let permutation_ctl_zs_next = buffer.read_target_ext_vec::<D>()?;
|
||||
let ctl_zs_last = buffer.read_target_vec()?;
|
||||
let quotient_polys = buffer.read_target_ext_vec::<D>()?;
|
||||
|
||||
Ok(Self {
|
||||
local_values,
|
||||
next_values,
|
||||
permutation_ctl_zs,
|
||||
permutation_ctl_zs_next,
|
||||
ctl_zs_last,
|
||||
quotient_polys,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn to_fri_openings(&self, zero: Target) -> FriOpeningsTarget<D> {
|
||||
let zeta_batch = FriOpeningBatchTarget {
|
||||
values: self
|
||||
|
||||
@ -18,7 +18,10 @@ use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, VerifierCircuitData};
|
||||
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||
use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
|
||||
use plonky2::util::gate_serialization::GateSerializer;
|
||||
use plonky2::util::generator_serialization::WitnessGeneratorSerializer;
|
||||
use plonky2::util::reducing::ReducingFactorTarget;
|
||||
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
use plonky2::with_context;
|
||||
use plonky2_util::log2_ceil;
|
||||
|
||||
@ -157,6 +160,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
}
|
||||
|
||||
/// Represents a circuit which recursively verifies a STARK proof.
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub(crate) struct StarkWrapperCircuit<F, C, const D: usize>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
@ -178,6 +182,39 @@ where
|
||||
[(); C::HCO::WIDTH]:,
|
||||
[(); C::HCI::WIDTH]:,
|
||||
{
|
||||
pub fn to_buffer(
|
||||
&self,
|
||||
buffer: &mut Vec<u8>,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<()> {
|
||||
buffer.write_circuit_data(&self.circuit, gate_serializer, generator_serializer)?;
|
||||
buffer.write_target_vec(&self.init_challenger_state_target)?;
|
||||
buffer.write_target(self.zero_target)?;
|
||||
self.stark_proof_target.to_buffer(buffer)?;
|
||||
self.ctl_challenges_target.to_buffer(buffer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn from_buffer(
|
||||
buffer: &mut Buffer,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Self> {
|
||||
let circuit = buffer.read_circuit_data(gate_serializer, generator_serializer)?;
|
||||
let init_challenger_state_target = buffer.read_target_vec()?;
|
||||
let zero_target = buffer.read_target()?;
|
||||
let stark_proof_target = StarkProofTarget::from_buffer(buffer)?;
|
||||
let ctl_challenges_target = GrandProductChallengeSet::from_buffer(buffer)?;
|
||||
Ok(Self {
|
||||
circuit,
|
||||
stark_proof_target,
|
||||
ctl_challenges_target,
|
||||
init_challenger_state_target: init_challenger_state_target.try_into().unwrap(),
|
||||
zero_target,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn prove(
|
||||
&self,
|
||||
proof_with_metadata: &StarkProofWithMetadata<F, C, D>,
|
||||
@ -212,6 +249,7 @@ where
|
||||
}
|
||||
|
||||
/// Represents a circuit which recursively verifies a PLONK proof.
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub(crate) struct PlonkWrapperCircuit<F, C, const D: usize>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::time::Duration;
|
||||
|
||||
use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV};
|
||||
use eth_trie_utils::partial_trie::{HashedPartialTrie, PartialTrie};
|
||||
use keccak_hash::keccak;
|
||||
use log::info;
|
||||
use plonky2::field::goldilocks_field::GoldilocksField;
|
||||
use plonky2::plonk::config::PoseidonGoldilocksConfig;
|
||||
use plonky2::util::gate_serialization::default::DefaultGateSerializer;
|
||||
use plonky2::util::generator_serialization::default::DefaultGeneratorSerializer;
|
||||
use plonky2::util::timing::TimingTree;
|
||||
use plonky2_evm::all_stark::AllStark;
|
||||
use plonky2_evm::config::StarkConfig;
|
||||
@ -92,8 +96,39 @@ fn test_empty_txn_list() -> anyhow::Result<()> {
|
||||
|
||||
verify_proof(&all_stark, proof, &config)?;
|
||||
|
||||
let all_circuits = AllRecursiveCircuits::<F, C, D>::new(&all_stark, 9..19, &config);
|
||||
let all_circuits = AllRecursiveCircuits::<F, C, D>::new(&all_stark, 9..18, &config);
|
||||
|
||||
{
|
||||
let gate_serializer = DefaultGateSerializer;
|
||||
let generator_serializer = DefaultGeneratorSerializer {
|
||||
_phantom: PhantomData::<C>,
|
||||
};
|
||||
|
||||
let timing = TimingTree::new("serialize AllRecursiveCircuits", log::Level::Info);
|
||||
let all_circuits_bytes = all_circuits
|
||||
.to_bytes(&gate_serializer, &generator_serializer)
|
||||
.map_err(|_| anyhow::Error::msg("AllRecursiveCircuits serialization failed."))?;
|
||||
timing.filter(Duration::from_millis(100)).print();
|
||||
info!(
|
||||
"AllRecursiveCircuits length: {} bytes",
|
||||
all_circuits_bytes.len()
|
||||
);
|
||||
|
||||
let timing = TimingTree::new("deserialize AllRecursiveCircuits", log::Level::Info);
|
||||
let all_circuits_from_bytes = AllRecursiveCircuits::<F, C, D>::from_bytes(
|
||||
&all_circuits_bytes,
|
||||
&gate_serializer,
|
||||
&generator_serializer,
|
||||
)
|
||||
.map_err(|_| anyhow::Error::msg("AllRecursiveCircuits deserialization failed."))?;
|
||||
timing.filter(Duration::from_millis(100)).print();
|
||||
|
||||
assert_eq!(all_circuits, all_circuits_from_bytes);
|
||||
}
|
||||
|
||||
let mut timing = TimingTree::new("prove", log::Level::Info);
|
||||
let root_proof = all_circuits.prove_root(&all_stark, &config, inputs, &mut timing)?;
|
||||
timing.filter(Duration::from_millis(100)).print();
|
||||
all_circuits.verify_root(root_proof.clone())?;
|
||||
|
||||
let agg_proof = all_circuits.prove_aggregation(false, &root_proof, false, &root_proof)?;
|
||||
|
||||
@ -22,6 +22,7 @@ use plonky2::plonk::circuit_data::{CircuitConfig, CommonCircuitData, VerifierOnl
|
||||
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, PoseidonGoldilocksConfig};
|
||||
use plonky2::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs};
|
||||
use plonky2::plonk::prover::prove;
|
||||
use plonky2::util::gate_serialization::default::DefaultGateSerializer;
|
||||
use plonky2::util::timing::TimingTree;
|
||||
use plonky2_field::extension::Extendable;
|
||||
use plonky2_maybe_rayon::rayon;
|
||||
@ -181,6 +182,19 @@ where
|
||||
CompressedProofWithPublicInputs::from_bytes(compressed_proof_bytes, cd)?;
|
||||
assert_eq!(compressed_proof, compressed_proof_from_bytes);
|
||||
|
||||
let gate_serializer = DefaultGateSerializer;
|
||||
let common_data_bytes = cd
|
||||
.to_bytes(&gate_serializer)
|
||||
.map_err(|_| anyhow::Error::msg("CommonCircuitData serialization failed."))?;
|
||||
info!(
|
||||
"Common circuit data length: {} bytes",
|
||||
common_data_bytes.len()
|
||||
);
|
||||
let common_data_from_bytes =
|
||||
CommonCircuitData::<F, D>::from_bytes(common_data_bytes, &gate_serializer)
|
||||
.map_err(|_| anyhow::Error::msg("CommonCircuitData deserialization failed."))?;
|
||||
assert_eq!(cd, &common_data_from_bytes);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@ -11,11 +11,12 @@ use plonky2::iop::witness::{PartialWitness, PartitionWitness, Witness, WitnessWr
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::circuit_data::CircuitConfig;
|
||||
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
use plonky2_field::extension::Extendable;
|
||||
|
||||
/// A generator used by the prover to calculate the square root (`x`) of a given value
|
||||
/// (`x_squared`), outside of the circuit, in order to supply it as an additional public input.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
struct SquareRootGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
x: Target,
|
||||
x_squared: Target,
|
||||
@ -25,6 +26,10 @@ struct SquareRootGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
for SquareRootGenerator<F, D>
|
||||
{
|
||||
fn id(&self) -> String {
|
||||
"SquareRootGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![self.x_squared]
|
||||
}
|
||||
@ -37,6 +42,21 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
|
||||
out_buffer.set_target(self.x, x);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_target(self.x)?;
|
||||
dst.write_target(self.x_squared)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let x = src.read_target()?;
|
||||
let x_squared = src.read_target()?;
|
||||
Ok(Self {
|
||||
x,
|
||||
x_squared,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// An example of using Plonky2 to prove a statement of the form
|
||||
|
||||
@ -27,6 +27,7 @@ use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place, transp
|
||||
pub const SALT_SIZE: usize = 4;
|
||||
|
||||
/// Represents a FRI oracle, i.e. a batch of polynomials which have been Merklized.
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct PolynomialBatch<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
{
|
||||
pub polynomials: Vec<PolynomialCoeffs<F>>,
|
||||
|
||||
@ -33,7 +33,7 @@ pub struct FriQueryStep<
|
||||
pub merkle_proof: MerkleProof<F, HC, H>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct FriQueryStepTarget<const D: usize> {
|
||||
pub evals: Vec<ExtensionTarget<D>>,
|
||||
pub merkle_proof: MerkleProofTarget,
|
||||
@ -58,7 +58,7 @@ impl<F: RichField, HC: HashConfig, H: Hasher<F, HC>> FriInitialTreeProof<F, HC,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct FriInitialTreeProofTarget {
|
||||
pub evals_proofs: Vec<(Vec<Target>, MerkleProofTarget)>,
|
||||
}
|
||||
@ -92,7 +92,7 @@ pub struct FriQueryRound<
|
||||
pub steps: Vec<FriQueryStep<F, HC, H, D>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct FriQueryRoundTarget<const D: usize> {
|
||||
pub initial_trees_proof: FriInitialTreeProofTarget,
|
||||
pub steps: Vec<FriQueryStepTarget<D>>,
|
||||
@ -129,7 +129,7 @@ pub struct FriProof<F: RichField + Extendable<D>, HC: HashConfig, H: Hasher<F, H
|
||||
pub pow_witness: F,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct FriProofTarget<const D: usize> {
|
||||
pub commit_phase_merkle_caps: Vec<MerkleCapTarget>,
|
||||
pub query_round_proofs: Vec<FriQueryRoundTarget<D>>,
|
||||
|
||||
@ -11,6 +11,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||
use crate::iop::target::{BoolTarget, Target};
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// Computes `-x`.
|
||||
@ -370,8 +371,8 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct EqualityGenerator {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct EqualityGenerator {
|
||||
x: Target,
|
||||
y: Target,
|
||||
equal: BoolTarget,
|
||||
@ -379,6 +380,10 @@ struct EqualityGenerator {
|
||||
}
|
||||
|
||||
impl<F: RichField> SimpleGenerator<F> for EqualityGenerator {
|
||||
fn id(&self) -> String {
|
||||
"EqualityGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![self.x, self.y]
|
||||
}
|
||||
@ -392,6 +397,21 @@ impl<F: RichField> SimpleGenerator<F> for EqualityGenerator {
|
||||
out_buffer.set_bool_target(self.equal, x == y);
|
||||
out_buffer.set_target(self.inv, inv);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_target(self.x)?;
|
||||
dst.write_target(self.y)?;
|
||||
dst.write_target_bool(self.equal)?;
|
||||
dst.write_target(self.inv)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let x = src.read_target()?;
|
||||
let y = src.read_target()?;
|
||||
let equal = src.read_target_bool()?;
|
||||
let inv = src.read_target()?;
|
||||
Ok(Self { x, y, equal, inv })
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a base arithmetic operation in the circuit. Used to memoize results.
|
||||
|
||||
@ -13,6 +13,7 @@ use crate::iop::target::Target;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::util::bits_u64;
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
pub fn arithmetic_extension(
|
||||
@ -493,8 +494,8 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct QuotientGeneratorExtension<const D: usize> {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct QuotientGeneratorExtension<const D: usize> {
|
||||
numerator: ExtensionTarget<D>,
|
||||
denominator: ExtensionTarget<D>,
|
||||
quotient: ExtensionTarget<D>,
|
||||
@ -503,6 +504,10 @@ struct QuotientGeneratorExtension<const D: usize> {
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
for QuotientGeneratorExtension<D>
|
||||
{
|
||||
fn id(&self) -> String {
|
||||
"QuotientGeneratorExtension".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
let mut deps = self.numerator.to_target_array().to_vec();
|
||||
deps.extend(self.denominator.to_target_array());
|
||||
@ -515,6 +520,23 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
let quotient = num / dem;
|
||||
out_buffer.set_extension_target(self.quotient, quotient)
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_target_ext(self.numerator)?;
|
||||
dst.write_target_ext(self.denominator)?;
|
||||
dst.write_target_ext(self.quotient)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let numerator = src.read_target_ext()?;
|
||||
let denominator = src.read_target_ext()?;
|
||||
let quotient = src.read_target_ext()?;
|
||||
Ok(Self {
|
||||
numerator,
|
||||
denominator,
|
||||
quotient,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the powers of a certain base element `b`: `b^0, b^1, b^2, ...`.
|
||||
|
||||
@ -7,7 +7,7 @@ use crate::iop::target::Target;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::util::reducing::ReducingFactorTarget;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct PolynomialCoeffsExtTarget<const D: usize>(pub Vec<ExtensionTarget<D>>);
|
||||
|
||||
impl<const D: usize> PolynomialCoeffsExtTarget<D> {
|
||||
|
||||
@ -7,6 +7,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||
use crate::iop::target::{BoolTarget, Target};
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// Checks that `x < 2^n_log` using a `BaseSumGate`.
|
||||
@ -51,8 +52,8 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct LowHighGenerator {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct LowHighGenerator {
|
||||
integer: Target,
|
||||
n_log: usize,
|
||||
low: Target,
|
||||
@ -60,6 +61,10 @@ struct LowHighGenerator {
|
||||
}
|
||||
|
||||
impl<F: RichField> SimpleGenerator<F> for LowHighGenerator {
|
||||
fn id(&self) -> String {
|
||||
"LowHighGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![self.integer]
|
||||
}
|
||||
@ -72,4 +77,24 @@ impl<F: RichField> SimpleGenerator<F> for LowHighGenerator {
|
||||
out_buffer.set_target(self.low, F::from_canonical_u64(low));
|
||||
out_buffer.set_target(self.high, F::from_canonical_u64(high));
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_target(self.integer)?;
|
||||
dst.write_usize(self.n_log)?;
|
||||
dst.write_target(self.low)?;
|
||||
dst.write_target(self.high)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let integer = src.read_target()?;
|
||||
let n_log = src.read_usize()?;
|
||||
let low = src.read_target()?;
|
||||
let high = src.read_target()?;
|
||||
Ok(Self {
|
||||
integer,
|
||||
n_log,
|
||||
low,
|
||||
high,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ use crate::iop::target::{BoolTarget, Target};
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::util::log_floor;
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// Split the given element into a list of targets, where each one represents a
|
||||
@ -79,13 +80,17 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BaseSumGenerator<const B: usize> {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct BaseSumGenerator<const B: usize> {
|
||||
row: usize,
|
||||
limbs: Vec<BoolTarget>,
|
||||
}
|
||||
|
||||
impl<F: Field, const B: usize> SimpleGenerator<F> for BaseSumGenerator<B> {
|
||||
fn id(&self) -> String {
|
||||
"BaseSumGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
self.limbs.iter().map(|b| b.target).collect()
|
||||
}
|
||||
@ -102,6 +107,17 @@ impl<F: Field, const B: usize> SimpleGenerator<F> for BaseSumGenerator<B> {
|
||||
|
||||
out_buffer.set_target(Target::wire(self.row, BaseSumGate::<B>::WIRE_SUM), sum);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)?;
|
||||
dst.write_target_bool_vec(&self.limbs)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
let limbs = src.read_target_bool_vec()?;
|
||||
Ok(Self { row, limbs })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -9,6 +9,7 @@ use crate::iop::target::{BoolTarget, Target};
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::util::ceil_div_usize;
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// Split the given integer into a list of wires, where each one represents a
|
||||
@ -55,13 +56,17 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SplitGenerator {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct SplitGenerator {
|
||||
integer: Target,
|
||||
bits: Vec<Target>,
|
||||
}
|
||||
|
||||
impl<F: RichField> SimpleGenerator<F> for SplitGenerator {
|
||||
fn id(&self) -> String {
|
||||
"SplitGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![self.integer]
|
||||
}
|
||||
@ -80,16 +85,31 @@ impl<F: RichField> SimpleGenerator<F> for SplitGenerator {
|
||||
"Integer too large to fit in given number of bits"
|
||||
);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_target(self.integer)?;
|
||||
dst.write_target_vec(&self.bits)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let integer = src.read_target()?;
|
||||
let bits = src.read_target_vec()?;
|
||||
Ok(Self { integer, bits })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct WireSplitGenerator {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct WireSplitGenerator {
|
||||
integer: Target,
|
||||
gates: Vec<usize>,
|
||||
num_limbs: usize,
|
||||
}
|
||||
|
||||
impl<F: RichField> SimpleGenerator<F> for WireSplitGenerator {
|
||||
fn id(&self) -> String {
|
||||
"WireSplitGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![self.integer]
|
||||
}
|
||||
@ -120,4 +140,21 @@ impl<F: RichField> SimpleGenerator<F> for WireSplitGenerator {
|
||||
self.gates.len()
|
||||
);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_target(self.integer)?;
|
||||
dst.write_usize_vec(&self.gates)?;
|
||||
dst.write_usize(self.num_limbs)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let integer = src.read_target()?;
|
||||
let gates = src.read_usize_vec()?;
|
||||
let num_limbs = src.read_usize()?;
|
||||
Ok(Self {
|
||||
integer,
|
||||
gates,
|
||||
num_limbs,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::format;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
@ -10,7 +9,7 @@ use crate::gates::packed_util::PackedEvaluableBase;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
@ -19,6 +18,7 @@ use crate::plonk::vars::{
|
||||
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
|
||||
EvaluationVarsBasePacked,
|
||||
};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// A gate which can perform a weighted multiply-add, i.e. `result = c0 x y + c1 z`. If the config
|
||||
/// supports enough routed wires, it can support several such operations in one gate.
|
||||
@ -60,6 +60,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticGate
|
||||
format!("{self:?}")
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.num_ops)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let num_ops = src.read_usize()?;
|
||||
Ok(Self { num_ops })
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let const_0 = vars.local_constants[0];
|
||||
let const_1 = vars.local_constants[1];
|
||||
@ -117,10 +126,10 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticGate
|
||||
constraints
|
||||
}
|
||||
|
||||
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
(0..self.num_ops)
|
||||
.map(|i| {
|
||||
let g: Box<dyn WitnessGenerator<F>> = Box::new(
|
||||
WitnessGeneratorRef::new(
|
||||
ArithmeticBaseGenerator {
|
||||
row,
|
||||
const_0: local_constants[0],
|
||||
@ -128,8 +137,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticGate
|
||||
i,
|
||||
}
|
||||
.adapter(),
|
||||
);
|
||||
g
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@ -172,8 +180,8 @@ impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D> for
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct ArithmeticBaseGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub(crate) struct ArithmeticBaseGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
row: usize,
|
||||
const_0: F,
|
||||
const_1: F,
|
||||
@ -183,6 +191,10 @@ struct ArithmeticBaseGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
for ArithmeticBaseGenerator<F, D>
|
||||
{
|
||||
fn id(&self) -> String {
|
||||
"ArithmeticBaseGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
[
|
||||
ArithmeticGate::wire_ith_multiplicand_0(self.i),
|
||||
@ -208,6 +220,26 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
|
||||
out_buffer.set_target(output_target, computed_output)
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)?;
|
||||
dst.write_field(self.const_0)?;
|
||||
dst.write_field(self.const_1)?;
|
||||
dst.write_usize(self.i)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
let const_0 = src.read_field()?;
|
||||
let const_1 = src.read_field()?;
|
||||
let i = src.read_usize()?;
|
||||
Ok(Self {
|
||||
row,
|
||||
const_0,
|
||||
const_1,
|
||||
i,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::format;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
@ -9,12 +8,13 @@ use crate::gates::gate::Gate;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// A gate which can perform a weighted multiply-add, i.e. `result = c0 x y + c1 z`. If the config
|
||||
/// supports enough routed wires, it can support several such operations in one gate.
|
||||
@ -56,6 +56,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExte
|
||||
format!("{self:?}")
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.num_ops)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let num_ops = src.read_usize()?;
|
||||
Ok(Self { num_ops })
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let const_0 = vars.local_constants[0];
|
||||
let const_1 = vars.local_constants[1];
|
||||
@ -122,10 +131,10 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExte
|
||||
constraints
|
||||
}
|
||||
|
||||
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
(0..self.num_ops)
|
||||
.map(|i| {
|
||||
let g: Box<dyn WitnessGenerator<F>> = Box::new(
|
||||
WitnessGeneratorRef::new(
|
||||
ArithmeticExtensionGenerator {
|
||||
row,
|
||||
const_0: local_constants[0],
|
||||
@ -133,8 +142,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExte
|
||||
i,
|
||||
}
|
||||
.adapter(),
|
||||
);
|
||||
g
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@ -156,8 +164,8 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExte
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct ArithmeticExtensionGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub(crate) struct ArithmeticExtensionGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
row: usize,
|
||||
const_0: F,
|
||||
const_1: F,
|
||||
@ -167,6 +175,10 @@ struct ArithmeticExtensionGenerator<F: RichField + Extendable<D>, const D: usize
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
for ArithmeticExtensionGenerator<F, D>
|
||||
{
|
||||
fn id(&self) -> String {
|
||||
"ArithmeticExtensionGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
ArithmeticExtensionGate::<D>::wires_ith_multiplicand_0(self.i)
|
||||
.chain(ArithmeticExtensionGate::<D>::wires_ith_multiplicand_1(
|
||||
@ -201,6 +213,26 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
|
||||
out_buffer.set_extension_target(output_target, computed_output)
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)?;
|
||||
dst.write_field(self.const_0)?;
|
||||
dst.write_field(self.const_1)?;
|
||||
dst.write_usize(self.i)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
let const_0 = src.read_field()?;
|
||||
let const_1 = src.read_field()?;
|
||||
let i = src.read_usize()?;
|
||||
Ok(Self {
|
||||
row,
|
||||
const_0,
|
||||
const_1,
|
||||
i,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{format, vec};
|
||||
@ -12,7 +11,7 @@ use crate::gates::packed_util::PackedEvaluableBase;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
@ -23,6 +22,7 @@ use crate::plonk::vars::{
|
||||
EvaluationVarsBasePacked,
|
||||
};
|
||||
use crate::util::log_floor;
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// A gate which can decompose a number into base B little-endian limbs.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -55,6 +55,15 @@ impl<F: RichField + Extendable<D>, const D: usize, const B: usize> Gate<F, D> fo
|
||||
format!("{self:?} + Base: {B}")
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.num_limbs)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let num_limbs = src.read_usize()?;
|
||||
Ok(Self { num_limbs })
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let sum = vars.local_wires[Self::WIRE_SUM];
|
||||
let limbs = vars.local_wires[self.limbs()].to_vec();
|
||||
@ -109,12 +118,12 @@ impl<F: RichField + Extendable<D>, const D: usize, const B: usize> Gate<F, D> fo
|
||||
constraints
|
||||
}
|
||||
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
let gen = BaseSplitGenerator::<B> {
|
||||
row,
|
||||
num_limbs: self.num_limbs,
|
||||
};
|
||||
vec![Box::new(gen.adapter())]
|
||||
vec![WitnessGeneratorRef::new(gen.adapter())]
|
||||
}
|
||||
|
||||
// 1 for the sum then `num_limbs` for the limbs.
|
||||
@ -160,13 +169,17 @@ impl<F: RichField + Extendable<D>, const D: usize, const B: usize> PackedEvaluab
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct BaseSplitGenerator<const B: usize> {
|
||||
row: usize,
|
||||
num_limbs: usize,
|
||||
}
|
||||
|
||||
impl<F: RichField, const B: usize> SimpleGenerator<F> for BaseSplitGenerator<B> {
|
||||
fn id(&self) -> String {
|
||||
"BaseSplitGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![Target::wire(self.row, BaseSumGate::<B>::WIRE_SUM)]
|
||||
}
|
||||
@ -195,6 +208,17 @@ impl<F: RichField, const B: usize> SimpleGenerator<F> for BaseSplitGenerator<B>
|
||||
out_buffer.set_target(b, b_value);
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)?;
|
||||
dst.write_usize(self.num_limbs)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
let num_limbs = src.read_usize()?;
|
||||
Ok(Self { row, num_limbs })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{format, vec};
|
||||
@ -10,12 +9,13 @@ use crate::gates::packed_util::PackedEvaluableBase;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::WitnessGenerator;
|
||||
use crate::iop::generator::WitnessGeneratorRef;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::vars::{
|
||||
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
|
||||
EvaluationVarsBasePacked,
|
||||
};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// A gate which takes a single constant parameter and outputs that value.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -40,6 +40,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ConstantGate {
|
||||
format!("{self:?}")
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.num_consts)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let num_consts = src.read_usize()?;
|
||||
Ok(Self { num_consts })
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
(0..self.num_consts)
|
||||
.map(|i| {
|
||||
@ -75,7 +84,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ConstantGate {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{format, vec};
|
||||
@ -13,12 +12,13 @@ use crate::gates::gate::Gate;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::wire::Wire;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// One of the instantiations of `InterpolationGate`: allows constraints of variable
|
||||
/// degree, up to `1<<subgroup_bits`.
|
||||
@ -45,7 +45,7 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
///
|
||||
/// Then e[N] is the final interpolated value. The non-routed wires hold every (d - 1)'th
|
||||
/// intermediate value of p and e, starting at p[d] and e[d], where d is the gate degree.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct CosetInterpolationGate<F: RichField + Extendable<D>, const D: usize> {
|
||||
pub subgroup_bits: usize,
|
||||
pub degree: usize,
|
||||
@ -168,6 +168,26 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for CosetInterpola
|
||||
format!("{self:?}<D={D}>")
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.subgroup_bits)?;
|
||||
dst.write_usize(self.degree)?;
|
||||
dst.write_usize(self.barycentric_weights.len())?;
|
||||
dst.write_field_vec(&self.barycentric_weights)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let subgroup_bits = src.read_usize()?;
|
||||
let degree = src.read_usize()?;
|
||||
let length = src.read_usize()?;
|
||||
let barycentric_weights: Vec<F> = src.read_field_vec(length)?;
|
||||
Ok(Self {
|
||||
subgroup_bits,
|
||||
degree,
|
||||
barycentric_weights,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let mut constraints = Vec::with_capacity(self.num_constraints());
|
||||
|
||||
@ -342,9 +362,9 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for CosetInterpola
|
||||
constraints
|
||||
}
|
||||
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
let gen = InterpolationGenerator::<F, D>::new(row, self.clone());
|
||||
vec![Box::new(gen.adapter())]
|
||||
vec![WitnessGeneratorRef::new(gen.adapter())]
|
||||
}
|
||||
|
||||
fn num_wires(&self) -> usize {
|
||||
@ -366,8 +386,8 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for CosetInterpola
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InterpolationGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct InterpolationGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
row: usize,
|
||||
gate: CosetInterpolationGate<F, D>,
|
||||
interpolation_domain: Vec<F>,
|
||||
@ -389,6 +409,10 @@ impl<F: RichField + Extendable<D>, const D: usize> InterpolationGenerator<F, D>
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
for InterpolationGenerator<F, D>
|
||||
{
|
||||
fn id(&self) -> String {
|
||||
"InterpolationGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
let local_target = |column| {
|
||||
Target::Wire(Wire {
|
||||
@ -471,6 +495,17 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
let evaluation_value_wires = self.gate.wires_evaluation_value().map(local_wire);
|
||||
out_buffer.set_ext_wires(evaluation_value_wires, computed_eval);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)?;
|
||||
self.gate.serialize(dst)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
let gate = CosetInterpolationGate::deserialize(src)?;
|
||||
Ok(Self::new(row, gate))
|
||||
}
|
||||
}
|
||||
|
||||
/// Interpolate the polynomial defined by its values on an arbitrary domain at the given point `x`.
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{format, vec};
|
||||
@ -13,7 +12,7 @@ use crate::gates::packed_util::PackedEvaluableBase;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::wire::Wire;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
@ -23,9 +22,10 @@ use crate::plonk::vars::{
|
||||
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
|
||||
EvaluationVarsBasePacked,
|
||||
};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// A gate for raising a value to a power.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ExponentiationGate<F: RichField + Extendable<D>, const D: usize> {
|
||||
pub num_power_bits: usize,
|
||||
pub _phantom: PhantomData<F>,
|
||||
@ -76,6 +76,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for Exponentiation
|
||||
format!("{self:?}<D={D}>")
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.num_power_bits)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let num_power_bits = src.read_usize()?;
|
||||
Ok(Self::new(num_power_bits))
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let base = vars.local_wires[self.wire_base()];
|
||||
|
||||
@ -164,12 +173,12 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for Exponentiation
|
||||
constraints
|
||||
}
|
||||
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
let gen = ExponentiationGenerator::<F, D> {
|
||||
row,
|
||||
gate: self.clone(),
|
||||
};
|
||||
vec![Box::new(gen.adapter())]
|
||||
vec![WitnessGeneratorRef::new(gen.adapter())]
|
||||
}
|
||||
|
||||
fn num_wires(&self) -> usize {
|
||||
@ -228,8 +237,8 @@ impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D>
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ExponentiationGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct ExponentiationGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
row: usize,
|
||||
gate: ExponentiationGate<F, D>,
|
||||
}
|
||||
@ -237,6 +246,10 @@ struct ExponentiationGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
for ExponentiationGenerator<F, D>
|
||||
{
|
||||
fn id(&self) -> String {
|
||||
"ExponentiationGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
let local_target = |column| Target::wire(self.row, column);
|
||||
|
||||
@ -281,6 +294,17 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
let output_wire = local_wire(self.gate.wire_output());
|
||||
out_buffer.set_wire(output_wire, intermediate_values[num_power_bits - 1]);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)?;
|
||||
self.gate.serialize(dst)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
let gate = ExponentiationGate::deserialize(src)?;
|
||||
Ok(Self { row, gate })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
use core::any::Any;
|
||||
use core::fmt::{Debug, Error, Formatter};
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::ops::Range;
|
||||
@ -16,16 +16,23 @@ use crate::gates::selectors::UNUSED_SELECTOR;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::WitnessGenerator;
|
||||
use crate::iop::generator::WitnessGeneratorRef;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::vars::{
|
||||
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
|
||||
};
|
||||
use crate::util::serialization::{Buffer, IoResult};
|
||||
|
||||
/// A custom gate.
|
||||
pub trait Gate<F: RichField + Extendable<D>, const D: usize>: 'static + Send + Sync {
|
||||
fn id(&self) -> String;
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()>;
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension>;
|
||||
|
||||
/// Like `eval_unfiltered`, but specialized for points in the base field.
|
||||
@ -162,7 +169,7 @@ pub trait Gate<F: RichField + Extendable<D>, const D: usize>: 'static + Send + S
|
||||
|
||||
/// The generators used to populate the witness.
|
||||
/// Note: This should return exactly 1 generator per operation in the gate.
|
||||
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>>;
|
||||
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>>;
|
||||
|
||||
/// The number of wires used by this gate.
|
||||
fn num_wires(&self) -> usize;
|
||||
@ -191,9 +198,19 @@ pub trait Gate<F: RichField + Extendable<D>, const D: usize>: 'static + Send + S
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AnyGate<F: RichField + Extendable<D>, const D: usize>: Gate<F, D> {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
}
|
||||
|
||||
impl<T: Gate<F, D>, F: RichField + Extendable<D>, const D: usize> AnyGate<F, D> for T {
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper around an `Rc<Gate>` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs.
|
||||
#[derive(Clone)]
|
||||
pub struct GateRef<F: RichField + Extendable<D>, const D: usize>(pub(crate) Arc<dyn Gate<F, D>>);
|
||||
pub struct GateRef<F: RichField + Extendable<D>, const D: usize>(pub(crate) Arc<dyn AnyGate<F, D>>);
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> GateRef<F, D> {
|
||||
pub fn new<G: Gate<F, D>>(gate: G) -> GateRef<F, D> {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::format;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
@ -9,12 +8,13 @@ use crate::gates::gate::Gate;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// A gate which can perform a weighted multiplication, i.e. `result = c0 x y`. If the config
|
||||
/// supports enough routed wires, it can support several such operations in one gate.
|
||||
@ -53,6 +53,15 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for MulExtensionGa
|
||||
format!("{self:?}")
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.num_ops)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let num_ops = src.read_usize()?;
|
||||
Ok(Self { num_ops })
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let const_0 = vars.local_constants[0];
|
||||
|
||||
@ -110,18 +119,17 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for MulExtensionGa
|
||||
constraints
|
||||
}
|
||||
|
||||
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, row: usize, local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
(0..self.num_ops)
|
||||
.map(|i| {
|
||||
let g: Box<dyn WitnessGenerator<F>> = Box::new(
|
||||
WitnessGeneratorRef::new(
|
||||
MulExtensionGenerator {
|
||||
row,
|
||||
const_0: local_constants[0],
|
||||
i,
|
||||
}
|
||||
.adapter(),
|
||||
);
|
||||
g
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@ -143,8 +151,8 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for MulExtensionGa
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct MulExtensionGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub(crate) struct MulExtensionGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
row: usize,
|
||||
const_0: F,
|
||||
i: usize,
|
||||
@ -153,6 +161,10 @@ struct MulExtensionGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
for MulExtensionGenerator<F, D>
|
||||
{
|
||||
fn id(&self) -> String {
|
||||
"MulExtensionGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
MulExtensionGate::<D>::wires_ith_multiplicand_0(self.i)
|
||||
.chain(MulExtensionGate::<D>::wires_ith_multiplicand_1(self.i))
|
||||
@ -178,6 +190,19 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
|
||||
out_buffer.set_extension_target(output_target, computed_output)
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)?;
|
||||
dst.write_field(self.const_0)?;
|
||||
dst.write_usize(self.i)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
let const_0 = src.read_field()?;
|
||||
let i = src.read_usize()?;
|
||||
Ok(Self { row, const_0, i })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
@ -6,9 +5,10 @@ use crate::field::extension::Extendable;
|
||||
use crate::gates::gate::Gate;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::WitnessGenerator;
|
||||
use crate::iop::generator::WitnessGeneratorRef;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBaseBatch};
|
||||
use crate::util::serialization::{Buffer, IoResult};
|
||||
|
||||
/// A gate which does nothing.
|
||||
pub struct NoopGate;
|
||||
@ -18,6 +18,14 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for NoopGate {
|
||||
"NoopGate".into()
|
||||
}
|
||||
|
||||
fn serialize(&self, _dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(_src: &mut Buffer) -> IoResult<Self> {
|
||||
Ok(Self)
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, _vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
Vec::new()
|
||||
}
|
||||
@ -34,7 +42,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for NoopGate {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{format, vec};
|
||||
@ -13,12 +12,13 @@ use crate::hash::hash_types::RichField;
|
||||
use crate::hash::poseidon;
|
||||
use crate::hash::poseidon::{Poseidon, SPONGE_WIDTH};
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::wire::Wire;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// Evaluates a full Poseidon permutation with 12 state elements.
|
||||
///
|
||||
@ -99,6 +99,14 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for PoseidonGate<F
|
||||
format!("{self:?}<WIDTH={SPONGE_WIDTH}>")
|
||||
}
|
||||
|
||||
fn serialize(&self, _dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(_src: &mut Buffer) -> IoResult<Self> {
|
||||
Ok(PoseidonGate::new())
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let mut constraints = Vec::with_capacity(self.num_constraints());
|
||||
|
||||
@ -372,12 +380,12 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for PoseidonGate<F
|
||||
constraints
|
||||
}
|
||||
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
let gen = PoseidonGenerator::<F, D> {
|
||||
row,
|
||||
_phantom: PhantomData,
|
||||
};
|
||||
vec![Box::new(gen.adapter())]
|
||||
vec![WitnessGeneratorRef::new(gen.adapter())]
|
||||
}
|
||||
|
||||
fn num_wires(&self) -> usize {
|
||||
@ -401,8 +409,8 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for PoseidonGate<F
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PoseidonGenerator<F: RichField + Extendable<D> + Poseidon, const D: usize> {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct PoseidonGenerator<F: RichField + Extendable<D> + Poseidon, const D: usize> {
|
||||
row: usize,
|
||||
_phantom: PhantomData<F>,
|
||||
}
|
||||
@ -410,6 +418,10 @@ struct PoseidonGenerator<F: RichField + Extendable<D> + Poseidon, const D: usize
|
||||
impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F>
|
||||
for PoseidonGenerator<F, D>
|
||||
{
|
||||
fn id(&self) -> String {
|
||||
"PoseidonGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
(0..SPONGE_WIDTH)
|
||||
.map(|i| PoseidonGate::<F, D>::wire_input(i))
|
||||
@ -499,6 +511,18 @@ impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F>
|
||||
out_buffer.set_wire(local_wire(PoseidonGate::<F, D>::wire_output(i)), state[i]);
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
Ok(Self {
|
||||
row,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{format, vec};
|
||||
@ -13,11 +12,12 @@ use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::hash::poseidon::{Poseidon, SPONGE_WIDTH};
|
||||
use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// Poseidon MDS Gate
|
||||
#[derive(Debug, Default)]
|
||||
@ -118,6 +118,14 @@ impl<F: RichField + Extendable<D> + Poseidon, const D: usize> Gate<F, D> for Pos
|
||||
format!("{self:?}<WIDTH={SPONGE_WIDTH}>")
|
||||
}
|
||||
|
||||
fn serialize(&self, _dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(_src: &mut Buffer) -> IoResult<Self> {
|
||||
Ok(PoseidonMdsGate::new())
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let inputs: [_; SPONGE_WIDTH] = (0..SPONGE_WIDTH)
|
||||
.map(|i| vars.get_local_ext_algebra(Self::wires_input(i)))
|
||||
@ -179,9 +187,9 @@ impl<F: RichField + Extendable<D> + Poseidon, const D: usize> Gate<F, D> for Pos
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
let gen = PoseidonMdsGenerator::<D> { row };
|
||||
vec![Box::new(gen.adapter())]
|
||||
vec![WitnessGeneratorRef::new(gen.adapter())]
|
||||
}
|
||||
|
||||
fn num_wires(&self) -> usize {
|
||||
@ -201,14 +209,18 @@ impl<F: RichField + Extendable<D> + Poseidon, const D: usize> Gate<F, D> for Pos
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct PoseidonMdsGenerator<const D: usize> {
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub(crate) struct PoseidonMdsGenerator<const D: usize> {
|
||||
row: usize,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F>
|
||||
for PoseidonMdsGenerator<D>
|
||||
{
|
||||
fn id(&self) -> String {
|
||||
"PoseidonMdsGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
(0..SPONGE_WIDTH)
|
||||
.flat_map(|i| {
|
||||
@ -237,6 +249,15 @@ impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
Ok(Self { row })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use core::ops::Range;
|
||||
@ -10,12 +9,13 @@ use crate::gates::packed_util::PackedEvaluableBase;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::WitnessGenerator;
|
||||
use crate::iop::generator::WitnessGeneratorRef;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::vars::{
|
||||
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
|
||||
EvaluationVarsBasePacked,
|
||||
};
|
||||
use crate::util::serialization::{Buffer, IoResult};
|
||||
|
||||
/// A gate whose first four wires will be equal to a hash of public inputs.
|
||||
pub struct PublicInputGate;
|
||||
@ -31,6 +31,14 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for PublicInputGat
|
||||
"PublicInputGate".into()
|
||||
}
|
||||
|
||||
fn serialize(&self, _dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(_src: &mut Buffer) -> IoResult<Self> {
|
||||
Ok(Self)
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
Self::wires_public_inputs_hash()
|
||||
.zip(vars.public_inputs_hash.elements)
|
||||
@ -64,7 +72,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for PublicInputGat
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{format, vec};
|
||||
@ -14,7 +13,7 @@ use crate::gates::packed_util::PackedEvaluableBase;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::wire::Wire;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
@ -24,9 +23,10 @@ use crate::plonk::vars::{
|
||||
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
|
||||
EvaluationVarsBasePacked,
|
||||
};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// A gate for checking that a particular element of a list matches a given value.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct RandomAccessGate<F: RichField + Extendable<D>, const D: usize> {
|
||||
/// Number of bits in the index (log2 of the list size).
|
||||
pub bits: usize,
|
||||
@ -122,6 +122,20 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for RandomAccessGa
|
||||
format!("{self:?}<D={D}>")
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.bits)?;
|
||||
dst.write_usize(self.num_copies)?;
|
||||
dst.write_usize(self.num_extra_constants)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let bits = src.read_usize()?;
|
||||
let num_copies = src.read_usize()?;
|
||||
let num_extra_constants = src.read_usize()?;
|
||||
Ok(Self::new(num_copies, bits, num_extra_constants))
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let mut constraints = Vec::with_capacity(self.num_constraints());
|
||||
|
||||
@ -238,18 +252,17 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for RandomAccessGa
|
||||
constraints
|
||||
}
|
||||
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
(0..self.num_copies)
|
||||
.map(|copy| {
|
||||
let g: Box<dyn WitnessGenerator<F>> = Box::new(
|
||||
WitnessGeneratorRef::new(
|
||||
RandomAccessGenerator {
|
||||
row,
|
||||
gate: *self,
|
||||
copy,
|
||||
}
|
||||
.adapter(),
|
||||
);
|
||||
g
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@ -325,8 +338,8 @@ impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D>
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RandomAccessGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct RandomAccessGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
row: usize,
|
||||
gate: RandomAccessGate<F, D>,
|
||||
copy: usize,
|
||||
@ -335,6 +348,10 @@ struct RandomAccessGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
for RandomAccessGenerator<F, D>
|
||||
{
|
||||
fn id(&self) -> String {
|
||||
"RandomAccessGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
let local_target = |column| Target::wire(self.row, column);
|
||||
|
||||
@ -376,6 +393,19 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
set_local_wire(self.gate.wire_bit(i, copy), bit);
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)?;
|
||||
dst.write_usize(self.copy)?;
|
||||
self.gate.serialize(dst)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
let copy = src.read_usize()?;
|
||||
let gate = RandomAccessGate::<F, D>::deserialize(src)?;
|
||||
Ok(Self { row, gate, copy })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{format, vec};
|
||||
@ -9,14 +8,15 @@ use crate::gates::gate::Gate;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// Computes `sum alpha^i c_i` for a vector `c_i` of `num_coeffs` elements of the base field.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ReducingGate<const D: usize> {
|
||||
pub num_coeffs: usize,
|
||||
}
|
||||
@ -60,6 +60,19 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ReducingGate<D
|
||||
format!("{self:?}")
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.num_coeffs)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let num_coeffs = src.read_usize()?;
|
||||
Ok(Self::new(num_coeffs))
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let alpha = vars.get_local_ext_algebra(Self::wires_alpha());
|
||||
let old_acc = vars.get_local_ext_algebra(Self::wires_old_acc());
|
||||
@ -137,8 +150,8 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ReducingGate<D
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
vec![Box::new(
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
vec![WitnessGeneratorRef::new(
|
||||
ReducingGenerator {
|
||||
row,
|
||||
gate: self.clone(),
|
||||
@ -164,13 +177,17 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ReducingGate<D
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ReducingGenerator<const D: usize> {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct ReducingGenerator<const D: usize> {
|
||||
row: usize,
|
||||
gate: ReducingGate<D>,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> for ReducingGenerator<D> {
|
||||
fn id(&self) -> String {
|
||||
"ReducingGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
ReducingGate::<D>::wires_alpha()
|
||||
.chain(ReducingGate::<D>::wires_old_acc())
|
||||
@ -207,6 +224,17 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> for Reduci
|
||||
}
|
||||
out_buffer.set_extension_target(output, acc);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)?;
|
||||
<ReducingGate<D> as Gate<F, D>>::serialize(&self.gate, dst)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
let gate = <ReducingGate<D> as Gate<F, D>>::deserialize(src)?;
|
||||
Ok(Self { row, gate })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{format, vec};
|
||||
@ -9,14 +8,15 @@ use crate::gates::gate::Gate;
|
||||
use crate::gates::util::StridedConstraintConsumer;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// Computes `sum alpha^i c_i` for a vector `c_i` of `num_coeffs` elements of the extension field.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ReducingExtensionGate<const D: usize> {
|
||||
pub num_coeffs: usize,
|
||||
}
|
||||
@ -63,6 +63,19 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ReducingExtens
|
||||
format!("{self:?}")
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.num_coeffs)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let num_coeffs = src.read_usize()?;
|
||||
Ok(Self::new(num_coeffs))
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let alpha = vars.get_local_ext_algebra(Self::wires_alpha());
|
||||
let old_acc = vars.get_local_ext_algebra(Self::wires_old_acc());
|
||||
@ -137,8 +150,8 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ReducingExtens
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
vec![Box::new(
|
||||
fn generators(&self, row: usize, _local_constants: &[F]) -> Vec<WitnessGeneratorRef<F>> {
|
||||
vec![WitnessGeneratorRef::new(
|
||||
ReducingGenerator {
|
||||
row,
|
||||
gate: self.clone(),
|
||||
@ -164,13 +177,17 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ReducingExtens
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ReducingGenerator<const D: usize> {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct ReducingGenerator<const D: usize> {
|
||||
row: usize,
|
||||
gate: ReducingExtensionGate<D>,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> for ReducingGenerator<D> {
|
||||
fn id(&self) -> String {
|
||||
"ReducingExtensionGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
ReducingExtensionGate::<D>::wires_alpha()
|
||||
.chain(ReducingExtensionGate::<D>::wires_old_acc())
|
||||
@ -201,6 +218,17 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> for Reduci
|
||||
acc = computed_acc;
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)?;
|
||||
<ReducingExtensionGate<D> as Gate<F, D>>::serialize(&self.gate, dst)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
let gate = <ReducingExtensionGate<D> as Gate<F, D>>::deserialize(src)?;
|
||||
Ok(Self { row, gate })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -110,7 +110,7 @@ impl<F: Field> Default for HashOut<F> {
|
||||
}
|
||||
|
||||
/// Represents a ~256 bit hash output.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct HashOutTarget {
|
||||
pub elements: [Target; 4],
|
||||
}
|
||||
@ -148,7 +148,7 @@ impl TryFrom<&[Target]> for HashOutTarget {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct MerkleCapTarget(pub Vec<HashOutTarget>);
|
||||
|
||||
/// Hash consisting of a byte array.
|
||||
|
||||
@ -31,7 +31,7 @@ impl<F: RichField, HC: HashConfig, H: Hasher<F, HC>> MerkleProof<F, HC, H> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct MerkleProofTarget {
|
||||
/// The Merkle digest of each sibling subtree, staying from the bottommost layer.
|
||||
pub siblings: Vec<HashOutTarget>,
|
||||
|
||||
@ -36,7 +36,7 @@ impl<F: RichField, HC: HashConfig, H: Hasher<F, HC>> MerkleCap<F, HC, H> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct MerkleTree<F: RichField, HC: HashConfig, H: Hasher<F, HC>> {
|
||||
/// The data in the leaves of the Merkle tree.
|
||||
pub leaves: Vec<Vec<F>>,
|
||||
|
||||
@ -12,6 +12,12 @@ use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct ExtensionTarget<const D: usize>(pub [Target; D]);
|
||||
|
||||
impl<const D: usize> Default for ExtensionTarget<D> {
|
||||
fn default() -> Self {
|
||||
Self([Target::default(); D])
|
||||
}
|
||||
}
|
||||
|
||||
impl<const D: usize> ExtensionTarget<D> {
|
||||
pub fn to_target_array(&self) -> [Target; D] {
|
||||
self.0
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
use core::any::Any;
|
||||
use core::fmt::Debug;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
@ -12,6 +13,7 @@ use crate::iop::wire::Wire;
|
||||
use crate::iop::witness::{PartialWitness, PartitionWitness, Witness, WitnessWrite};
|
||||
use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData};
|
||||
use crate::plonk::config::GenericConfig;
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// Given a `PartitionWitness` that has only inputs set, populates the rest of the witness using the
|
||||
/// given set of generators.
|
||||
@ -58,7 +60,7 @@ pub(crate) fn generate_partial_witness<
|
||||
continue;
|
||||
}
|
||||
|
||||
let finished = generators[generator_idx].run(&witness, &mut buffer);
|
||||
let finished = generators[generator_idx].0.run(&witness, &mut buffer);
|
||||
if finished {
|
||||
generator_is_expired[generator_idx] = true;
|
||||
remaining_generators -= 1;
|
||||
@ -98,6 +100,8 @@ pub(crate) fn generate_partial_witness<
|
||||
|
||||
/// A generator participates in the generation of the witness.
|
||||
pub trait WitnessGenerator<F: Field>: 'static + Send + Sync + Debug {
|
||||
fn id(&self) -> String;
|
||||
|
||||
/// Targets to be "watched" by this generator. Whenever a target in the watch list is populated,
|
||||
/// the generator will be queued to run.
|
||||
fn watch_list(&self) -> Vec<Target>;
|
||||
@ -106,6 +110,52 @@ pub trait WitnessGenerator<F: Field>: 'static + Send + Sync + Debug {
|
||||
/// flag is true, the generator will never be run again, otherwise it will be queued for another
|
||||
/// run next time a target in its watch list is populated.
|
||||
fn run(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) -> bool;
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()>;
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
pub trait AnyWitnessGenerator<F: Field>: WitnessGenerator<F> {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
}
|
||||
|
||||
impl<T: WitnessGenerator<F>, F: Field> AnyWitnessGenerator<F> for T {
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper around an `Box<AnyWitnessGenerator>`.
|
||||
pub struct WitnessGeneratorRef<F: Field>(pub(crate) Box<dyn AnyWitnessGenerator<F>>);
|
||||
|
||||
impl<F: Field> WitnessGeneratorRef<F> {
|
||||
pub fn new<G: AnyWitnessGenerator<F>>(generator: G) -> WitnessGeneratorRef<F> {
|
||||
WitnessGeneratorRef(Box::new(generator))
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field> PartialEq for WitnessGeneratorRef<F> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let mut buf1 = Vec::new();
|
||||
let mut buf2 = Vec::new();
|
||||
self.0.serialize(&mut buf1).unwrap();
|
||||
other.0.serialize(&mut buf2).unwrap();
|
||||
|
||||
buf1 == buf2
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field> Eq for WitnessGeneratorRef<F> {}
|
||||
|
||||
impl<F: Field> Debug for WitnessGeneratorRef<F> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let mut buf = Vec::new();
|
||||
self.0.serialize(&mut buf).unwrap();
|
||||
write!(f, "{:?}", buf)
|
||||
}
|
||||
}
|
||||
|
||||
/// Values generated by a generator invocation.
|
||||
@ -158,6 +208,8 @@ impl<F: Field> GeneratedValues<F> {
|
||||
|
||||
/// A generator which runs once after a list of dependencies is present in the witness.
|
||||
pub trait SimpleGenerator<F: Field>: 'static + Send + Sync + Debug {
|
||||
fn id(&self) -> String;
|
||||
|
||||
fn dependencies(&self) -> Vec<Target>;
|
||||
|
||||
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>);
|
||||
@ -171,6 +223,12 @@ pub trait SimpleGenerator<F: Field>: 'static + Send + Sync + Debug {
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()>;
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -180,6 +238,10 @@ pub struct SimpleGeneratorAdapter<F: Field, SG: SimpleGenerator<F> + ?Sized> {
|
||||
}
|
||||
|
||||
impl<F: Field, SG: SimpleGenerator<F>> WitnessGenerator<F> for SimpleGeneratorAdapter<F, SG> {
|
||||
fn id(&self) -> String {
|
||||
self.inner.id()
|
||||
}
|
||||
|
||||
fn watch_list(&self) -> Vec<Target> {
|
||||
self.inner.dependencies()
|
||||
}
|
||||
@ -192,16 +254,31 @@ impl<F: Field, SG: SimpleGenerator<F>> WitnessGenerator<F> for SimpleGeneratorAd
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
self.inner.serialize(dst)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
Ok(Self {
|
||||
inner: SG::deserialize(src)?,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A generator which copies one wire to another.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct CopyGenerator {
|
||||
pub(crate) src: Target,
|
||||
pub(crate) dst: Target,
|
||||
}
|
||||
|
||||
impl<F: Field> SimpleGenerator<F> for CopyGenerator {
|
||||
fn id(&self) -> String {
|
||||
"CopyGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![self.src]
|
||||
}
|
||||
@ -210,15 +287,30 @@ impl<F: Field> SimpleGenerator<F> for CopyGenerator {
|
||||
let value = witness.get_target(self.src);
|
||||
out_buffer.set_target(self.dst, value);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_target(self.src)?;
|
||||
dst.write_target(self.dst)
|
||||
}
|
||||
|
||||
fn deserialize(source: &mut Buffer) -> IoResult<Self> {
|
||||
let src = source.read_target()?;
|
||||
let dst = source.read_target()?;
|
||||
Ok(Self { src, dst })
|
||||
}
|
||||
}
|
||||
|
||||
/// A generator for including a random value
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct RandomValueGenerator {
|
||||
pub(crate) target: Target,
|
||||
}
|
||||
|
||||
impl<F: Field> SimpleGenerator<F> for RandomValueGenerator {
|
||||
fn id(&self) -> String {
|
||||
"RandomValueGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
Vec::new()
|
||||
}
|
||||
@ -227,16 +319,29 @@ impl<F: Field> SimpleGenerator<F> for RandomValueGenerator {
|
||||
let random_value = F::rand();
|
||||
out_buffer.set_target(self.target, random_value);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_target(self.target)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let target = src.read_target()?;
|
||||
Ok(Self { target })
|
||||
}
|
||||
}
|
||||
|
||||
/// A generator for testing if a value equals zero
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct NonzeroTestGenerator {
|
||||
pub(crate) to_test: Target,
|
||||
pub(crate) dummy: Target,
|
||||
}
|
||||
|
||||
impl<F: Field> SimpleGenerator<F> for NonzeroTestGenerator {
|
||||
fn id(&self) -> String {
|
||||
"NonzeroTestGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![self.to_test]
|
||||
}
|
||||
@ -252,10 +357,21 @@ impl<F: Field> SimpleGenerator<F> for NonzeroTestGenerator {
|
||||
|
||||
out_buffer.set_target(self.dummy, dummy_value);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_target(self.to_test)?;
|
||||
dst.write_target(self.dummy)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let to_test = src.read_target()?;
|
||||
let dummy = src.read_target()?;
|
||||
Ok(Self { to_test, dummy })
|
||||
}
|
||||
}
|
||||
|
||||
/// Generator used to fill an extra constant.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub(crate) struct ConstantGenerator<F: Field> {
|
||||
pub row: usize,
|
||||
pub constant_index: usize,
|
||||
@ -269,7 +385,11 @@ impl<F: Field> ConstantGenerator<F> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field> SimpleGenerator<F> for ConstantGenerator<F> {
|
||||
impl<F: RichField> SimpleGenerator<F> for ConstantGenerator<F> {
|
||||
fn id(&self) -> String {
|
||||
"ConstantGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![]
|
||||
}
|
||||
@ -277,4 +397,24 @@ impl<F: Field> SimpleGenerator<F> for ConstantGenerator<F> {
|
||||
fn run_once(&self, _witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
|
||||
out_buffer.set_target(Target::wire(self.row, self.wire_index), self.constant);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_usize(self.row)?;
|
||||
dst.write_usize(self.constant_index)?;
|
||||
dst.write_usize(self.wire_index)?;
|
||||
dst.write_field(self.constant)
|
||||
}
|
||||
|
||||
fn deserialize(src: &mut Buffer) -> IoResult<Self> {
|
||||
let row = src.read_usize()?;
|
||||
let constant_index = src.read_usize()?;
|
||||
let wire_index = src.read_usize()?;
|
||||
let constant = src.read_field()?;
|
||||
Ok(Self {
|
||||
row,
|
||||
constant_index,
|
||||
wire_index,
|
||||
constant,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,12 @@ pub enum Target {
|
||||
},
|
||||
}
|
||||
|
||||
impl Default for Target {
|
||||
fn default() -> Self {
|
||||
Self::VirtualTarget { index: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Target {
|
||||
pub fn wire(row: usize, column: usize) -> Self {
|
||||
Self::Wire(Wire { row, column })
|
||||
@ -49,7 +55,7 @@ impl Target {
|
||||
}
|
||||
|
||||
/// A `Target` which has already been constrained such that it can only be 0 or 1.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
#[allow(clippy::manual_non_exhaustive)]
|
||||
pub struct BoolTarget {
|
||||
pub target: Target,
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
@ -33,7 +32,7 @@ use crate::hash::merkle_proofs::MerkleProofTarget;
|
||||
use crate::hash::merkle_tree::MerkleCap;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::{
|
||||
ConstantGenerator, CopyGenerator, RandomValueGenerator, SimpleGenerator, WitnessGenerator,
|
||||
ConstantGenerator, CopyGenerator, RandomValueGenerator, SimpleGenerator, WitnessGeneratorRef,
|
||||
};
|
||||
use crate::iop::target::{BoolTarget, Target};
|
||||
use crate::iop::wire::Wire;
|
||||
@ -77,7 +76,7 @@ pub struct CircuitBuilder<F: RichField + Extendable<D>, const D: usize> {
|
||||
context_log: ContextTree,
|
||||
|
||||
/// Generators used to generate the witness.
|
||||
generators: Vec<Box<dyn WitnessGenerator<F>>>,
|
||||
generators: Vec<WitnessGeneratorRef<F>>,
|
||||
|
||||
constants_to_targets: HashMap<F, Target>,
|
||||
targets_to_constants: HashMap<Target, F>,
|
||||
@ -367,12 +366,13 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
self.connect(x, one);
|
||||
}
|
||||
|
||||
pub fn add_generators(&mut self, generators: Vec<Box<dyn WitnessGenerator<F>>>) {
|
||||
pub fn add_generators(&mut self, generators: Vec<WitnessGeneratorRef<F>>) {
|
||||
self.generators.extend(generators);
|
||||
}
|
||||
|
||||
pub fn add_simple_generator<G: SimpleGenerator<F>>(&mut self, generator: G) {
|
||||
self.generators.push(Box::new(generator.adapter()));
|
||||
self.generators
|
||||
.push(WitnessGeneratorRef::new(generator.adapter()));
|
||||
}
|
||||
|
||||
/// Returns a routable target with a value of 0.
|
||||
@ -865,7 +865,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
// Index generator indices by their watched targets.
|
||||
let mut generator_indices_by_watches = BTreeMap::new();
|
||||
for (i, generator) in self.generators.iter().enumerate() {
|
||||
for watch in generator.watch_list() {
|
||||
for watch in generator.0.watch_list() {
|
||||
let watch_index = forest.target_index(watch);
|
||||
let watch_rep_index = forest.parents[watch_index];
|
||||
generator_indices_by_watches
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
@ -22,7 +21,7 @@ use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField};
|
||||
use crate::hash::hashing::HashConfig;
|
||||
use crate::hash::merkle_tree::MerkleCap;
|
||||
use crate::iop::ext_target::ExtensionTarget;
|
||||
use crate::iop::generator::WitnessGenerator;
|
||||
use crate::iop::generator::WitnessGeneratorRef;
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::PartialWitness;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
@ -31,6 +30,9 @@ use crate::plonk::plonk_common::PlonkOracle;
|
||||
use crate::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs};
|
||||
use crate::plonk::prover::prove;
|
||||
use crate::plonk::verifier::verify;
|
||||
use crate::util::gate_serialization::GateSerializer;
|
||||
use crate::util::generator_serialization::WitnessGeneratorSerializer;
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
use crate::util::timing::TimingTree;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
@ -107,6 +109,7 @@ impl CircuitConfig {
|
||||
}
|
||||
|
||||
/// Circuit data required by the prover or the verifier.
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct CircuitData<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> {
|
||||
pub prover_only: ProverOnlyCircuitData<F, C, D>,
|
||||
pub verifier_only: VerifierOnlyCircuitData<C, D>,
|
||||
@ -116,6 +119,25 @@ pub struct CircuitData<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>,
|
||||
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
CircuitData<F, C, D>
|
||||
{
|
||||
pub fn to_bytes(
|
||||
&self,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Vec<u8>> {
|
||||
let mut buffer = Vec::new();
|
||||
buffer.write_circuit_data(self, gate_serializer, generator_serializer)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
pub fn from_bytes(
|
||||
bytes: &[u8],
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Self> {
|
||||
let mut buffer = Buffer::new(bytes.to_vec());
|
||||
buffer.read_circuit_data(gate_serializer, generator_serializer)
|
||||
}
|
||||
|
||||
pub fn prove(&self, inputs: PartialWitness<F>) -> Result<ProofWithPublicInputs<F, C, D>>
|
||||
where
|
||||
[(); C::HCO::WIDTH]:,
|
||||
@ -214,6 +236,25 @@ pub struct ProverCircuitData<
|
||||
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
ProverCircuitData<F, C, D>
|
||||
{
|
||||
pub fn to_bytes(
|
||||
&self,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Vec<u8>> {
|
||||
let mut buffer = Vec::new();
|
||||
buffer.write_prover_circuit_data(self, gate_serializer, generator_serializer)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
pub fn from_bytes(
|
||||
bytes: &[u8],
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
generator_serializer: &dyn WitnessGeneratorSerializer<F, D>,
|
||||
) -> IoResult<Self> {
|
||||
let mut buffer = Buffer::new(bytes.to_vec());
|
||||
buffer.read_prover_circuit_data(gate_serializer, generator_serializer)
|
||||
}
|
||||
|
||||
pub fn prove(&self, inputs: PartialWitness<F>) -> Result<ProofWithPublicInputs<F, C, D>>
|
||||
where
|
||||
[(); C::HCO::WIDTH]:,
|
||||
@ -242,6 +283,20 @@ pub struct VerifierCircuitData<
|
||||
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
VerifierCircuitData<F, C, D>
|
||||
{
|
||||
pub fn to_bytes(&self, gate_serializer: &dyn GateSerializer<F, D>) -> IoResult<Vec<u8>> {
|
||||
let mut buffer = Vec::new();
|
||||
buffer.write_verifier_circuit_data(self, gate_serializer)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
pub fn from_bytes(
|
||||
bytes: Vec<u8>,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
) -> IoResult<Self> {
|
||||
let mut buffer = Buffer::new(bytes);
|
||||
buffer.read_verifier_circuit_data(gate_serializer)
|
||||
}
|
||||
|
||||
pub fn verify(&self, proof_with_pis: ProofWithPublicInputs<F, C, D>) -> Result<()>
|
||||
where
|
||||
[(); C::HCO::WIDTH]:,
|
||||
@ -263,12 +318,13 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
}
|
||||
|
||||
/// Circuit data required by the prover, but not the verifier.
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct ProverOnlyCircuitData<
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
const D: usize,
|
||||
> {
|
||||
pub generators: Vec<Box<dyn WitnessGenerator<F>>>,
|
||||
pub generators: Vec<WitnessGeneratorRef<F>>,
|
||||
/// Generator indices (within the `Vec` above), indexed by the representative of each target
|
||||
/// they watch.
|
||||
pub generator_indices_by_watches: BTreeMap<usize, Vec<usize>>,
|
||||
@ -300,6 +356,19 @@ pub struct VerifierOnlyCircuitData<C: GenericConfig<D>, const D: usize> {
|
||||
pub circuit_digest: <<C as GenericConfig<D>>::Hasher as Hasher<C::F, C::HCO>>::Hash,
|
||||
}
|
||||
|
||||
impl<C: GenericConfig<D>, const D: usize> VerifierOnlyCircuitData<C, D> {
|
||||
pub fn to_bytes(&self) -> IoResult<Vec<u8>> {
|
||||
let mut buffer = Vec::new();
|
||||
buffer.write_verifier_only_circuit_data(self)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: Vec<u8>) -> IoResult<Self> {
|
||||
let mut buffer = Buffer::new(bytes);
|
||||
buffer.read_verifier_only_circuit_data()
|
||||
}
|
||||
}
|
||||
|
||||
/// Circuit data required by both the prover and the verifier.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct CommonCircuitData<F: RichField + Extendable<D>, const D: usize> {
|
||||
@ -332,6 +401,20 @@ pub struct CommonCircuitData<F: RichField + Extendable<D>, const D: usize> {
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CommonCircuitData<F, D> {
|
||||
pub fn to_bytes(&self, gate_serializer: &dyn GateSerializer<F, D>) -> IoResult<Vec<u8>> {
|
||||
let mut buffer = Vec::new();
|
||||
buffer.write_common_circuit_data(self, gate_serializer)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
pub fn from_bytes(
|
||||
bytes: Vec<u8>,
|
||||
gate_serializer: &dyn GateSerializer<F, D>,
|
||||
) -> IoResult<Self> {
|
||||
let mut buffer = Buffer::new(bytes);
|
||||
buffer.read_common_circuit_data(gate_serializer)
|
||||
}
|
||||
|
||||
pub const fn degree_bits(&self) -> usize {
|
||||
self.fri_params.degree_bits
|
||||
}
|
||||
@ -503,7 +586,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CommonCircuitData<F, D> {
|
||||
/// is intentionally missing certain fields, such as `CircuitConfig`, because we support only a
|
||||
/// limited form of dynamic inner circuits. We can't practically make things like the wire count
|
||||
/// dynamic, at least not without setting a maximum wire count and paying for the worst case.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct VerifierCircuitTarget {
|
||||
/// A commitment to each constant polynomial and each permutation polynomial.
|
||||
pub constants_sigmas_cap: MerkleCapTarget,
|
||||
|
||||
@ -41,7 +41,7 @@ pub struct Proof<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const
|
||||
pub opening_proof: FriProof<F, C::HCO, C::Hasher, D>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ProofTarget<const D: usize> {
|
||||
pub wires_cap: MerkleCapTarget,
|
||||
pub plonk_zs_partial_products_cap: MerkleCapTarget,
|
||||
@ -305,13 +305,13 @@ pub(crate) struct FriInferredElements<F: RichField + Extendable<D>, const D: usi
|
||||
pub Vec<F::Extension>,
|
||||
);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ProofWithPublicInputsTarget<const D: usize> {
|
||||
pub proof: ProofTarget<D>,
|
||||
pub public_inputs: Vec<Target>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)]
|
||||
/// The purported values of each polynomial at a single point.
|
||||
pub struct OpeningSet<F: RichField + Extendable<D>, const D: usize> {
|
||||
pub constants: Vec<F::Extension>,
|
||||
@ -377,7 +377,7 @@ impl<F: RichField + Extendable<D>, const D: usize> OpeningSet<F, D> {
|
||||
}
|
||||
|
||||
/// The purported values of each polynomial at a single point.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct OpeningSetTarget<const D: usize> {
|
||||
pub constants: Vec<ExtensionTarget<D>>,
|
||||
pub plonk_sigmas: Vec<ExtensionTarget<D>>,
|
||||
|
||||
@ -13,6 +13,7 @@ use crate::plonk::circuit_data::{
|
||||
};
|
||||
use crate::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||
use crate::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
impl<C: GenericConfig<D>, const D: usize> VerifierOnlyCircuitData<C, D> {
|
||||
fn from_slice(slice: &[C::F], common_data: &CommonCircuitData<C::F, D>) -> Result<Self>
|
||||
@ -41,6 +42,23 @@ impl<C: GenericConfig<D>, const D: usize> VerifierOnlyCircuitData<C, D> {
|
||||
}
|
||||
|
||||
impl VerifierCircuitTarget {
|
||||
pub fn to_bytes(&self) -> IoResult<Vec<u8>> {
|
||||
let mut buffer = Vec::new();
|
||||
buffer.write_target_merkle_cap(&self.constants_sigmas_cap)?;
|
||||
buffer.write_target_hash(&self.circuit_digest)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: Vec<u8>) -> IoResult<Self> {
|
||||
let mut buffer = Buffer::new(bytes);
|
||||
let constants_sigmas_cap = buffer.read_target_merkle_cap()?;
|
||||
let circuit_digest = buffer.read_target_hash()?;
|
||||
Ok(Self {
|
||||
constants_sigmas_cap,
|
||||
circuit_digest,
|
||||
})
|
||||
}
|
||||
|
||||
fn from_slice<F: RichField + Extendable<D>, const D: usize>(
|
||||
slice: &[Target],
|
||||
common_data: &CommonCircuitData<F, D>,
|
||||
|
||||
@ -3,11 +3,15 @@ use alloc::vec::Vec;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use plonky2_field::extension::Extendable;
|
||||
use plonky2_field::polynomial::PolynomialCoeffs;
|
||||
use plonky2_util::ceil_div_usize;
|
||||
|
||||
use crate::fri::proof::{FriProof, FriProofTarget};
|
||||
use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
|
||||
use crate::gates::noop::NoopGate;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField};
|
||||
use crate::hash::hashing::HashConfig;
|
||||
use crate::hash::merkle_tree::MerkleCap;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::{PartialWitness, PartitionWitness, WitnessWrite};
|
||||
@ -15,8 +19,12 @@ use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::{
|
||||
CircuitData, CommonCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData,
|
||||
};
|
||||
use crate::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||
use crate::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
|
||||
use crate::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut, Hasher};
|
||||
use crate::plonk::proof::{
|
||||
OpeningSet, OpeningSetTarget, Proof, ProofTarget, ProofWithPublicInputs,
|
||||
ProofWithPublicInputsTarget,
|
||||
};
|
||||
use crate::util::serialization::{Buffer, IoResult, Read, Write};
|
||||
|
||||
/// Creates a dummy proof which is suitable for use as a base proof in a cyclic recursion tree.
|
||||
/// Such a base proof will not actually be verified, so most of its data is arbitrary. However, its
|
||||
@ -157,12 +165,101 @@ where
|
||||
pub(crate) verifier_data: VerifierOnlyCircuitData<C, D>,
|
||||
}
|
||||
|
||||
impl<F, C, const D: usize> Default for DummyProofGenerator<F, C, D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
{
|
||||
fn default() -> Self {
|
||||
let proof_with_pis_target = ProofWithPublicInputsTarget {
|
||||
proof: ProofTarget {
|
||||
wires_cap: MerkleCapTarget(vec![]),
|
||||
plonk_zs_partial_products_cap: MerkleCapTarget(vec![]),
|
||||
quotient_polys_cap: MerkleCapTarget(vec![]),
|
||||
openings: OpeningSetTarget::default(),
|
||||
opening_proof: FriProofTarget {
|
||||
commit_phase_merkle_caps: vec![],
|
||||
query_round_proofs: vec![],
|
||||
final_poly: PolynomialCoeffsExtTarget(vec![]),
|
||||
pow_witness: Target::default(),
|
||||
},
|
||||
},
|
||||
public_inputs: vec![],
|
||||
};
|
||||
|
||||
let proof_with_pis = ProofWithPublicInputs {
|
||||
proof: Proof {
|
||||
wires_cap: MerkleCap(vec![]),
|
||||
plonk_zs_partial_products_cap: MerkleCap(vec![]),
|
||||
quotient_polys_cap: MerkleCap(vec![]),
|
||||
openings: OpeningSet::default(),
|
||||
opening_proof: FriProof {
|
||||
commit_phase_merkle_caps: vec![],
|
||||
query_round_proofs: vec![],
|
||||
final_poly: PolynomialCoeffs { coeffs: vec![] },
|
||||
pow_witness: F::ZERO,
|
||||
},
|
||||
},
|
||||
public_inputs: vec![],
|
||||
};
|
||||
|
||||
let verifier_data_target = VerifierCircuitTarget {
|
||||
constants_sigmas_cap: MerkleCapTarget(vec![]),
|
||||
circuit_digest: HashOutTarget {
|
||||
elements: [Target::default(); 4],
|
||||
},
|
||||
};
|
||||
|
||||
let verifier_data = VerifierOnlyCircuitData {
|
||||
constants_sigmas_cap: MerkleCap(vec![]),
|
||||
circuit_digest:
|
||||
<<C as GenericConfig<D>>::Hasher as Hasher<C::F, C::HCO>>::Hash::from_bytes(
|
||||
&vec![0; <<C as GenericConfig<D>>::Hasher as Hasher<C::F, C::HCO>>::HASH_SIZE],
|
||||
),
|
||||
};
|
||||
|
||||
Self {
|
||||
proof_with_pis_target,
|
||||
proof_with_pis,
|
||||
verifier_data_target,
|
||||
verifier_data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, C, const D: usize> DummyProofGenerator<F, C, D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F> + 'static,
|
||||
C::Hasher: AlgebraicHasher<F, C::HCO>,
|
||||
{
|
||||
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
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F> + 'static,
|
||||
C::Hasher: AlgebraicHasher<F, C::HCO>,
|
||||
{
|
||||
fn id(&self) -> String {
|
||||
"DummyProofGenerator".to_string()
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![]
|
||||
}
|
||||
@ -171,4 +268,15 @@ where
|
||||
out_buffer.set_proof_with_pis_target(&self.proof_with_pis_target, &self.proof_with_pis);
|
||||
out_buffer.set_verifier_data_target(&self.verifier_data_target, &self.verifier_data);
|
||||
}
|
||||
|
||||
fn serialize(&self, dst: &mut Vec<u8>) -> IoResult<()> {
|
||||
dst.write_target_proof_with_public_inputs(&self.proof_with_pis_target)?;
|
||||
dst.write_proof_with_public_inputs(&self.proof_with_pis)?;
|
||||
dst.write_target_verifier_circuit(&self.verifier_data_target)?;
|
||||
dst.write_verifier_only_circuit_data(&self.verifier_data)
|
||||
}
|
||||
|
||||
fn deserialize(_src: &mut Buffer) -> IoResult<Self> {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
101
plonky2/src/util/gate_serialization.rs
Normal file
101
plonky2/src/util/gate_serialization.rs
Normal file
@ -0,0 +1,101 @@
|
||||
use plonky2_field::extension::Extendable;
|
||||
|
||||
use crate::gates::gate::GateRef;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::util::serialization::{Buffer, IoResult};
|
||||
|
||||
pub trait GateSerializer<F: RichField + Extendable<D>, const D: usize> {
|
||||
fn read_gate(&self, buf: &mut Buffer) -> IoResult<GateRef<F, D>>;
|
||||
fn write_gate(&self, buf: &mut Vec<u8>, gate: &GateRef<F, D>) -> IoResult<()>;
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! read_gate_impl {
|
||||
($buf:expr, $tag:expr, $($gate_types:ty),+) => {{
|
||||
let tag = $tag;
|
||||
let buf = $buf;
|
||||
let mut i = 0..;
|
||||
$(if tag == i.next().unwrap() {
|
||||
let gate = <$gate_types as $crate::gates::gate::Gate<F, D>>::deserialize(buf)?;
|
||||
Ok($crate::gates::gate::GateRef::<F, D>::new(gate))
|
||||
} else)*
|
||||
{
|
||||
Err($crate::util::serialization::IoError)
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! get_gate_tag_impl {
|
||||
($gate:expr, $($gate_types:ty),+) => {{
|
||||
let gate_any = $gate.0.as_any();
|
||||
let mut i = 0..;
|
||||
$(if let (tag, true) = (i.next().unwrap(), gate_any.is::<$gate_types>()) {
|
||||
Ok(tag)
|
||||
} else)*
|
||||
{
|
||||
log::log!(log::Level::Error, "attempted to serialize gate with id `{}` which is unsupported by this gate serializer", $gate.0.id());
|
||||
Err($crate::util::serialization::IoError)
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_gate_serializer {
|
||||
($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>> {
|
||||
let tag = $crate::util::serialization::Read::read_u32(buf)?;
|
||||
read_gate_impl!(buf, tag, $($gate_types),+)
|
||||
}
|
||||
|
||||
fn write_gate(&self, buf: &mut Vec<u8>, gate: &$crate::gates::gate::GateRef<F, D>) -> $crate::util::serialization::IoResult<()> {
|
||||
let tag = get_gate_tag_impl!(gate, $($gate_types),+)?;
|
||||
|
||||
$crate::util::serialization::Write::write_u32(buf, tag)?;
|
||||
gate.0.serialize(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub mod default {
|
||||
use plonky2_field::extension::Extendable;
|
||||
|
||||
use crate::gates::arithmetic_base::ArithmeticGate;
|
||||
use crate::gates::arithmetic_extension::ArithmeticExtensionGate;
|
||||
use crate::gates::base_sum::BaseSumGate;
|
||||
use crate::gates::constant::ConstantGate;
|
||||
use crate::gates::coset_interpolation::CosetInterpolationGate;
|
||||
use crate::gates::exponentiation::ExponentiationGate;
|
||||
use crate::gates::multiplication_extension::MulExtensionGate;
|
||||
use crate::gates::noop::NoopGate;
|
||||
use crate::gates::poseidon::PoseidonGate;
|
||||
use crate::gates::poseidon_mds::PoseidonMdsGate;
|
||||
use crate::gates::public_input::PublicInputGate;
|
||||
use crate::gates::random_access::RandomAccessGate;
|
||||
use crate::gates::reducing::ReducingGate;
|
||||
use crate::gates::reducing_extension::ReducingExtensionGate;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::util::gate_serialization::GateSerializer;
|
||||
|
||||
pub struct DefaultGateSerializer;
|
||||
impl<F: RichField + Extendable<D>, const D: usize> GateSerializer<F, D> for DefaultGateSerializer {
|
||||
impl_gate_serializer! {
|
||||
DefaultGateSerializer,
|
||||
ArithmeticGate,
|
||||
ArithmeticExtensionGate<D>,
|
||||
BaseSumGate<2>,
|
||||
ConstantGate,
|
||||
CosetInterpolationGate<F, D>,
|
||||
ExponentiationGate<F, D>,
|
||||
MulExtensionGate<D>,
|
||||
NoopGate,
|
||||
PoseidonMdsGate<F, D>,
|
||||
PoseidonGate<F, D>,
|
||||
PublicInputGate,
|
||||
RandomAccessGate<F, D>,
|
||||
ReducingExtensionGate<D>,
|
||||
ReducingGate<D>
|
||||
}
|
||||
}
|
||||
}
|
||||
156
plonky2/src/util/generator_serialization.rs
Normal file
156
plonky2/src/util/generator_serialization.rs
Normal file
@ -0,0 +1,156 @@
|
||||
//! A module to help with WitnessGeneratorRef serialization
|
||||
|
||||
use plonky2_field::extension::Extendable;
|
||||
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::generator::WitnessGeneratorRef;
|
||||
use crate::plonk::circuit_data::CommonCircuitData;
|
||||
use crate::util::serialization::{Buffer, IoResult};
|
||||
|
||||
pub trait WitnessGeneratorSerializer<F: RichField + Extendable<D>, const D: usize> {
|
||||
fn read_generator(
|
||||
&self,
|
||||
buf: &mut Buffer,
|
||||
common: &CommonCircuitData<F, D>,
|
||||
) -> IoResult<WitnessGeneratorRef<F>>;
|
||||
fn write_generator(
|
||||
&self,
|
||||
buf: &mut Vec<u8>,
|
||||
generator: &WitnessGeneratorRef<F>,
|
||||
) -> IoResult<()>;
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! read_generator_impl {
|
||||
($buf:expr, $tag:expr, $common:expr, $($generator_types:ty),+) => {{
|
||||
let tag = $tag;
|
||||
let buf = $buf;
|
||||
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() {
|
||||
let generator =
|
||||
<$generator_types as $crate::iop::generator::SimpleGenerator<F>>::deserialize(buf)?;
|
||||
Ok($crate::iop::generator::WitnessGeneratorRef::<F>::new(
|
||||
$crate::iop::generator::SimpleGenerator::<F>::adapter(generator),
|
||||
))
|
||||
} else)*
|
||||
{
|
||||
Err($crate::util::serialization::IoError)
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! get_generator_tag_impl {
|
||||
($generator:expr, $($generator_types:ty),+) => {{
|
||||
let mut i = 0..;
|
||||
$(if let (tag, true) = (i.next().unwrap(), $generator.0.id() == $crate::iop::generator::SimpleGenerator::<F>::id(&<$generator_types>::default())) {
|
||||
Ok(tag)
|
||||
} else)*
|
||||
{
|
||||
log::log!(log::Level::Error, "attempted to serialize generator with id {} which is unsupported by this generator serializer", $generator.0.id());
|
||||
Err($crate::util::serialization::IoError)
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_generator_serializer {
|
||||
($target:ty, $($generator_types:ty),+) => {
|
||||
fn read_generator(
|
||||
&self,
|
||||
buf: &mut $crate::util::serialization::Buffer,
|
||||
common: &$crate::plonk::circuit_data::CommonCircuitData<F, D>,
|
||||
) -> $crate::util::serialization::IoResult<$crate::iop::generator::WitnessGeneratorRef<F>> {
|
||||
let tag = $crate::util::serialization::Read::read_u32(buf)?;
|
||||
read_generator_impl!(buf, tag, common, $($generator_types),+)
|
||||
}
|
||||
|
||||
fn write_generator(
|
||||
&self,
|
||||
buf: &mut Vec<u8>,
|
||||
generator: &$crate::iop::generator::WitnessGeneratorRef<F>,
|
||||
) -> $crate::util::serialization::IoResult<()> {
|
||||
let tag = get_generator_tag_impl!(generator, $($generator_types),+)?;
|
||||
|
||||
$crate::util::serialization::Write::write_u32(buf, tag)?;
|
||||
generator.0.serialize(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub mod default {
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use plonky2_field::extension::Extendable;
|
||||
|
||||
use crate::gadgets::arithmetic::EqualityGenerator;
|
||||
use crate::gadgets::arithmetic_extension::QuotientGeneratorExtension;
|
||||
use crate::gadgets::range_check::LowHighGenerator;
|
||||
use crate::gadgets::split_base::BaseSumGenerator;
|
||||
use crate::gadgets::split_join::{SplitGenerator, WireSplitGenerator};
|
||||
use crate::gates::arithmetic_base::ArithmeticBaseGenerator;
|
||||
use crate::gates::arithmetic_extension::ArithmeticExtensionGenerator;
|
||||
use crate::gates::base_sum::BaseSplitGenerator;
|
||||
use crate::gates::coset_interpolation::InterpolationGenerator;
|
||||
use crate::gates::exponentiation::ExponentiationGenerator;
|
||||
use crate::gates::multiplication_extension::MulExtensionGenerator;
|
||||
use crate::gates::poseidon::PoseidonGenerator;
|
||||
use crate::gates::poseidon_mds::PoseidonMdsGenerator;
|
||||
use crate::gates::random_access::RandomAccessGenerator;
|
||||
use crate::gates::reducing::ReducingGenerator;
|
||||
use crate::gates::reducing_extension::ReducingGenerator as ReducingExtensionGenerator;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::generator::{
|
||||
ConstantGenerator, CopyGenerator, NonzeroTestGenerator, RandomValueGenerator,
|
||||
};
|
||||
use crate::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||
use crate::recursion::dummy_circuit::DummyProofGenerator;
|
||||
use crate::util::generator_serialization::WitnessGeneratorSerializer;
|
||||
|
||||
pub struct DefaultGeneratorSerializer<C: GenericConfig<D>, const D: usize> {
|
||||
pub _phantom: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<F, C, const D: usize> WitnessGeneratorSerializer<F, D> for DefaultGeneratorSerializer<C, D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F> + 'static,
|
||||
C::Hasher: AlgebraicHasher<F, C::HCO>,
|
||||
{
|
||||
impl_generator_serializer! {
|
||||
DefaultGateSerializer,
|
||||
DummyProofGenerator<F, C, D>,
|
||||
ArithmeticBaseGenerator<F, D>,
|
||||
ArithmeticExtensionGenerator<F, D>,
|
||||
BaseSplitGenerator<2>,
|
||||
BaseSumGenerator<2>,
|
||||
ConstantGenerator<F>,
|
||||
CopyGenerator,
|
||||
EqualityGenerator,
|
||||
ExponentiationGenerator<F, D>,
|
||||
InterpolationGenerator<F, D>,
|
||||
LowHighGenerator,
|
||||
MulExtensionGenerator<F, D>,
|
||||
NonzeroTestGenerator,
|
||||
PoseidonGenerator<F, D>,
|
||||
PoseidonMdsGenerator<D>,
|
||||
QuotientGeneratorExtension<D>,
|
||||
RandomAccessGenerator<F, D>,
|
||||
RandomValueGenerator,
|
||||
ReducingGenerator<D>,
|
||||
ReducingExtensionGenerator<D>,
|
||||
SplitGenerator,
|
||||
WireSplitGenerator
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,10 @@ use crate::field::types::Field;
|
||||
pub(crate) mod context_tree;
|
||||
pub(crate) mod partial_products;
|
||||
|
||||
#[macro_use]
|
||||
pub mod gate_serialization;
|
||||
#[macro_use]
|
||||
pub mod generator_serialization;
|
||||
pub mod reducing;
|
||||
pub mod serialization;
|
||||
pub mod strided_view;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user