diff --git a/plonky2/src/fri/oracle.rs b/plonky2/src/fri/oracle.rs index dca3202a..8642a6c5 100644 --- a/plonky2/src/fri/oracle.rs +++ b/plonky2/src/fri/oracle.rs @@ -36,6 +36,20 @@ pub struct PolynomialBatch, C: GenericConfig, C: GenericConfig, const D: usize> Default + for PolynomialBatch +{ + fn default() -> Self { + PolynomialBatch { + polynomials: Vec::new(), + merkle_tree: MerkleTree::default(), + degree_log: 0, + rate_bits: 0, + blinding: false, + } + } +} + impl, C: GenericConfig, const D: usize> PolynomialBatch { diff --git a/plonky2/src/hash/merkle_tree.rs b/plonky2/src/hash/merkle_tree.rs index b3b0e0cb..ab7e3958 100644 --- a/plonky2/src/hash/merkle_tree.rs +++ b/plonky2/src/hash/merkle_tree.rs @@ -17,6 +17,12 @@ use crate::util::log2_strict; // TODO: Change H to GenericHashOut, since this only cares about the hash, not the hasher. pub struct MerkleCap>(pub Vec); +impl> Default for MerkleCap { + fn default() -> Self { + Self(Vec::new()) + } +} + impl> MerkleCap { pub fn len(&self) -> usize { self.0.len() @@ -54,6 +60,16 @@ pub struct MerkleTree> { pub cap: MerkleCap, } +impl> Default for MerkleTree { + fn default() -> Self { + Self { + leaves: Vec::new(), + digests: Vec::new(), + cap: MerkleCap::default(), + } + } +} + fn capacity_up_to_mut(v: &mut Vec, len: usize) -> &mut [MaybeUninit] { assert!(v.capacity() >= len); let v_ptr = v.as_mut_ptr().cast::>(); diff --git a/plonky2/src/lookup_test.rs b/plonky2/src/lookup_test.rs index c575417e..165d5dfe 100644 --- a/plonky2/src/lookup_test.rs +++ b/plonky2/src/lookup_test.rs @@ -469,6 +469,49 @@ mod tests { Ok(()) } + #[test] + fn test_circuit_build_mock() { + // This code is taken from examples/fibonacci.rs + use crate::field::types::Field; + use crate::iop::witness::{PartialWitness, Witness, WitnessWrite}; + use crate::plonk::circuit_builder::CircuitBuilder; + use crate::plonk::circuit_data::CircuitConfig; + use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + + // The arithmetic circuit. + let initial_a = builder.add_virtual_target(); + let initial_b = builder.add_virtual_target(); + let mut prev_target = initial_a; + let mut cur_target = initial_b; + for _ in 0..99 { + let temp = builder.add(prev_target, cur_target); + prev_target = cur_target; + cur_target = temp; + } + + // Public inputs are the two initial values (provided below) and the result (which is generated). + builder.register_public_input(initial_a); + builder.register_public_input(initial_b); + builder.register_public_input(cur_target); + + // Provide initial values. + let mut pw = PartialWitness::new(); + pw.set_target(initial_a, F::ZERO); + pw.set_target(initial_b, F::ONE); + + let data = builder.mock_build::(); + let partition_witness = data.generate_witness(pw); + let result = partition_witness.try_get_target(cur_target).unwrap(); + assert_eq!(result, F::from_canonical_u64(3736710860384812976)); + } + fn init_logger() -> anyhow::Result<()> { let mut builder = env_logger::Builder::from_default_env(); builder.format_timestamp(None); diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 82d4ee89..bd436f2c 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -40,8 +40,8 @@ use crate::iop::generator::{ use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; use crate::plonk::circuit_data::{ - CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData, - VerifierCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData, + CircuitConfig, CircuitData, CommonCircuitData, MockCircuitData, ProverCircuitData, + ProverOnlyCircuitData, VerifierCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData, }; use crate::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut, Hasher}; use crate::plonk::copy_constraint::CopyConstraint; @@ -916,7 +916,10 @@ impl, const D: usize> CircuitBuilder { } /// Builds a "full circuit", with both prover and verifier data. - pub fn build>(mut self) -> CircuitData { + pub fn build_with_options>( + mut self, + commit_to_sigma: bool, + ) -> CircuitData { let mut timing = TimingTree::new("preprocess", Level::Trace); #[cfg(feature = "std")] @@ -1023,15 +1026,19 @@ impl, const D: usize> CircuitBuilder { let max_fft_points = 1 << (degree_bits + max(rate_bits, log2_ceil(quotient_degree_factor))); let fft_root_table = fft_root_table(max_fft_points); - let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat(); - let constants_sigmas_commitment = PolynomialBatch::::from_values( - constants_sigmas_vecs, - rate_bits, - PlonkOracle::CONSTANTS_SIGMAS.blinding, - cap_height, - &mut timing, - Some(&fft_root_table), - ); + let constants_sigmas_commitment = if commit_to_sigma { + let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat(); + PolynomialBatch::::from_values( + constants_sigmas_vecs, + rate_bits, + PlonkOracle::CONSTANTS_SIGMAS.blinding, + cap_height, + &mut timing, + Some(&fft_root_table), + ) + } else { + PolynomialBatch::::default() + }; // Map between gates where not all generators are used and the gate's number of used generators. let incomplete_gates = self @@ -1151,6 +1158,17 @@ impl, const D: usize> CircuitBuilder { } } + pub fn build>(self) -> CircuitData { + self.build_with_options(true) + } + + pub fn mock_build>(self) -> MockCircuitData { + let circuit_data = self.build_with_options(false); + MockCircuitData { + prover_only: circuit_data.prover_only, + common: circuit_data.common, + } + } /// Builds a "prover circuit", with data needed to generate proofs but not verify them. pub fn build_prover>(self) -> ProverCircuitData { // TODO: Can skip parts of this. diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index 6e4e0638..c93de8cb 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -24,9 +24,9 @@ use crate::gates::selectors::SelectorsInfo; use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::WitnessGeneratorRef; +use crate::iop::generator::{generate_partial_witness, WitnessGeneratorRef}; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::plonk_common::PlonkOracle; @@ -111,6 +111,22 @@ impl CircuitConfig { } } +/// Mock circuit data to only do witness generation without generating a proof. +#[derive(Eq, PartialEq, Debug)] +pub struct MockCircuitData, C: GenericConfig, const D: usize> +{ + pub prover_only: ProverOnlyCircuitData, + pub common: CommonCircuitData, +} + +impl, C: GenericConfig, const D: usize> + MockCircuitData +{ + pub fn generate_witness(&self, inputs: PartialWitness) -> PartitionWitness { + generate_partial_witness::(inputs, &self.prover_only, &self.common) + } +} + /// Circuit data required by the prover or the verifier. #[derive(Eq, PartialEq, Debug)] pub struct CircuitData, C: GenericConfig, const D: usize> {