diff --git a/src/bin/bench_recursion.rs b/src/bin/bench_recursion.rs index 8867415d..8e798f72 100644 --- a/src/bin/bench_recursion.rs +++ b/src/bin/bench_recursion.rs @@ -50,8 +50,8 @@ fn bench_prove, const D: usize>() -> Result<()> { let circuit = builder.build(); let inputs = PartialWitness::new(); - let proof = circuit.prove(inputs)?; - let proof_bytes = serde_cbor::to_vec(&proof).unwrap(); + let proof_with_pis = circuit.prove(inputs)?; + let proof_bytes = serde_cbor::to_vec(&proof_with_pis).unwrap(); info!("Proof length: {} bytes", proof_bytes.len()); - circuit.verify(proof) + circuit.verify(proof_with_pis) } diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index 2cfeb720..2e12ce0f 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -17,6 +17,7 @@ use crate::gates::constant::ConstantGate; use crate::gates::gate::{GateInstance, GateRef, PrefixedGate}; use crate::gates::gate_tree::Tree; use crate::gates::noop::NoopGate; +use crate::gates::public_input::PublicInputGate; use crate::generator::{CopyGenerator, RandomValueGenerator, WitnessGenerator}; use crate::hash::hash_n_to_hash; use crate::permutation_argument::TargetPartition; @@ -39,8 +40,8 @@ pub struct CircuitBuilder, const D: usize> { /// The concrete placement of each gate. gate_instances: Vec>, - /// The next available index for a public input. - public_input_index: usize, + /// Targets to be made public. + public_inputs: Vec, /// The next available index for a `VirtualTarget`. virtual_target_index: usize, @@ -66,7 +67,7 @@ impl, const D: usize> CircuitBuilder { config, gates: HashSet::new(), gate_instances: Vec::new(), - public_input_index: 0, + public_inputs: Vec::new(), virtual_target_index: 0, copy_constraints: Vec::new(), context_log: ContextTree::new(), @@ -81,14 +82,14 @@ impl, const D: usize> CircuitBuilder { self.gate_instances.len() } - pub fn add_public_input(&mut self) -> Target { - let index = self.public_input_index; - self.public_input_index += 1; - Target::PublicInput { index } + /// Registers the given target as a public input. + pub fn register_public_input(&mut self, target: Target) { + self.public_inputs.push(target); } - pub fn add_public_inputs(&mut self, n: usize) -> Vec { - (0..n).map(|_i| self.add_public_input()).collect() + /// Registers the given targets as public inputs. + pub fn register_public_inputs(&mut self, targets: &[Target]) { + targets.iter().for_each(|&t| self.register_public_input(t)); } /// Adds a new "virtual" target. This is not an actual wire in the witness, but just a target @@ -462,10 +463,7 @@ impl, const D: usize> CircuitBuilder { let degree_log = log2_strict(degree); let mut target_partition = TargetPartition::new(|t| match t { Target::Wire(Wire { gate, input }) => gate * self.config.num_routed_wires + input, - Target::PublicInput { index } => degree * self.config.num_routed_wires + index, - Target::VirtualTarget { index } => { - degree * self.config.num_routed_wires + self.public_input_index + index - } + Target::VirtualTarget { index } => degree * self.config.num_routed_wires + index, }); for gate in 0..degree { @@ -474,10 +472,6 @@ impl, const D: usize> CircuitBuilder { } } - for index in 0..self.public_input_index { - target_partition.add(Target::PublicInput { index }); - } - for index in 0..self.virtual_target_index { target_partition.add(Target::VirtualTarget { index }); } @@ -500,6 +494,19 @@ impl, const D: usize> CircuitBuilder { pub fn build(mut self) -> CircuitData { let quotient_degree_factor = 7; // TODO: add this as a parameter. let start = Instant::now(); + + // Hash the public inputs, and route them to a `PublicInputGate` which will enforce that + // those hash wires match the claimed public inputs. + let public_inputs_hash = self.hash_n_to_hash(self.public_inputs.clone(), true); + let pi_gate = self.add_gate_no_constants(PublicInputGate::get()); + for (&hash_part, wire) in public_inputs_hash + .elements + .iter() + .zip(PublicInputGate::wires_public_inputs_hash()) + { + self.route(hash_part, Target::wire(pi_gate, wire)) + } + info!( "Degree before blinding & padding: {}", self.gate_instances.len() @@ -552,6 +559,7 @@ impl, const D: usize> CircuitBuilder { subgroup, copy_constraints: self.copy_constraints, gate_instances: self.gate_instances, + public_inputs: self.public_inputs, marked_targets: self.marked_targets, }; diff --git a/src/circuit_data.rs b/src/circuit_data.rs index 9c68ca46..912f05cc 100644 --- a/src/circuit_data.rs +++ b/src/circuit_data.rs @@ -9,8 +9,9 @@ use crate::fri::FriConfig; use crate::gates::gate::{GateInstance, PrefixedGate}; use crate::generator::WitnessGenerator; use crate::polynomial::commitment::ListPolynomialCommitment; -use crate::proof::{Hash, HashTarget, Proof}; +use crate::proof::{Hash, HashTarget, ProofWithPublicInputs}; use crate::prover::prove; +use crate::target::Target; use crate::util::marking::MarkedTargets; use crate::verifier::verify; use crate::witness::PartialWitness; @@ -78,12 +79,12 @@ pub struct CircuitData, const D: usize> { } impl, const D: usize> CircuitData { - pub fn prove(&self, inputs: PartialWitness) -> Result> { + pub fn prove(&self, inputs: PartialWitness) -> Result> { prove(&self.prover_only, &self.common, inputs) } - pub fn verify(&self, proof: Proof) -> Result<()> { - verify(proof, &self.verifier_only, &self.common) + pub fn verify(&self, proof_with_pis: ProofWithPublicInputs) -> Result<()> { + verify(proof_with_pis, &self.verifier_only, &self.common) } } @@ -100,7 +101,7 @@ pub struct ProverCircuitData, const D: usize> { } impl, const D: usize> ProverCircuitData { - pub fn prove(&self, inputs: PartialWitness) -> Result> { + pub fn prove(&self, inputs: PartialWitness) -> Result> { prove(&self.prover_only, &self.common, inputs) } } @@ -112,8 +113,8 @@ pub struct VerifierCircuitData, const D: usize> { } impl, const D: usize> VerifierCircuitData { - pub fn verify(&self, proof: Proof) -> Result<()> { - verify(proof, &self.verifier_only, &self.common) + pub fn verify(&self, proof_with_pis: ProofWithPublicInputs) -> Result<()> { + verify(proof_with_pis, &self.verifier_only, &self.common) } } @@ -130,6 +131,8 @@ pub(crate) struct ProverOnlyCircuitData, const D: usize> { pub copy_constraints: Vec, /// The concrete placement of each gate in the circuit. pub gate_instances: Vec>, + /// Targets to be made public. + pub public_inputs: Vec, /// A vector of marked targets. The values assigned to these targets will be displayed by the prover. pub marked_targets: Vec>, } diff --git a/src/gates/gate.rs b/src/gates/gate.rs index 9b45817e..17059332 100644 --- a/src/gates/gate.rs +++ b/src/gates/gate.rs @@ -31,9 +31,11 @@ pub trait Gate, const D: usize>: 'static + Send + Sync { .iter() .map(|w| F::Extension::from_basefield(*w)) .collect::>(); + let public_inputs_hash = &vars_base.public_inputs_hash; let vars = EvaluationVars { local_constants, local_wires, + public_inputs_hash, }; let values = self.eval_unfiltered(vars); diff --git a/src/gates/gate_testing.rs b/src/gates/gate_testing.rs index cb25acb8..2f7a3020 100644 --- a/src/gates/gate_testing.rs +++ b/src/gates/gate_testing.rs @@ -2,6 +2,7 @@ use crate::field::extension_field::Extendable; use crate::field::field::Field; use crate::gates::gate::GateRef; use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; +use crate::proof::Hash; use crate::util::{log2_ceil, transpose}; use crate::vars::EvaluationVars; @@ -17,6 +18,7 @@ pub(crate) fn test_low_degree, const D: usize>(gate: GateRef(gate.num_wires(), rate_bits); let constant_ldes = random_low_degree_matrix::(gate.num_constants(), rate_bits); assert_eq!(wire_ldes.len(), constant_ldes.len()); + let public_inputs_hash = &Hash::rand(); let constraint_evals = wire_ldes .iter() @@ -24,6 +26,7 @@ pub(crate) fn test_low_degree, const D: usize>(gate: GateRef>(); diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 768a5693..e61ed8d9 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -326,6 +326,7 @@ mod tests { use crate::gates::gmimc::{GMiMCGate, W}; use crate::generator::generate_partial_witness; use crate::gmimc::gmimc_permute_naive; + use crate::proof::Hash; use crate::vars::{EvaluationTargets, EvaluationVars}; use crate::verifier::verify; use crate::wire::Wire; @@ -416,9 +417,11 @@ mod tests { let gate = Gate::with_constants(constants); let wires = FF::rand_vec(Gate::end()); + let public_inputs_hash = &Hash::rand(); let vars = EvaluationVars { local_constants: &[], local_wires: &wires, + public_inputs_hash, }; let ev = gate.0.eval_unfiltered(vars); @@ -427,9 +430,14 @@ mod tests { for i in 0..Gate::end() { pw.set_extension_target(wires_t[i], wires[i]); } + + let public_inputs_hash_t = builder.add_virtual_hash(); + pw.set_hash_target(public_inputs_hash_t, *public_inputs_hash); + let vars_t = EvaluationTargets { local_constants: &[], local_wires: &wires_t, + public_inputs_hash: &public_inputs_hash_t, }; let ev_t = gate.0.eval_unfiltered_recursively(&mut builder, vars_t); diff --git a/src/gates/insertion.rs b/src/gates/insertion.rs index 64301347..2fbeda15 100644 --- a/src/gates/insertion.rs +++ b/src/gates/insertion.rs @@ -288,6 +288,7 @@ mod tests { use crate::gates::gate::Gate; use crate::gates::gate_testing::test_low_degree; use crate::gates::insertion::InsertionGate; + use crate::proof::Hash; use crate::vars::EvaluationVars; #[test] @@ -366,6 +367,7 @@ mod tests { let vars = EvaluationVars { local_constants: &[], local_wires: &get_wires(orig_vec, insertion_index, element_to_insert), + public_inputs_hash: &Hash::rand(), }; assert!( diff --git a/src/gates/interpolation.rs b/src/gates/interpolation.rs index ccf8d57d..2d6745b4 100644 --- a/src/gates/interpolation.rs +++ b/src/gates/interpolation.rs @@ -271,6 +271,7 @@ mod tests { use crate::gates::gate_testing::test_low_degree; use crate::gates::interpolation::InterpolationGate; use crate::polynomial::polynomial::PolynomialCoeffs; + use crate::proof::Hash; use crate::vars::EvaluationVars; #[test] @@ -352,6 +353,7 @@ mod tests { let vars = EvaluationVars { local_constants: &[], local_wires: &get_wires(2, coeffs, points, eval_point), + public_inputs_hash: &Hash::rand(), }; assert!( diff --git a/src/gates/mod.rs b/src/gates/mod.rs index 6b3f05fa..441383ec 100644 --- a/src/gates/mod.rs +++ b/src/gates/mod.rs @@ -10,6 +10,7 @@ pub mod gmimc; pub mod insertion; pub mod interpolation; pub(crate) mod noop; +pub(crate) mod public_input; #[cfg(test)] mod gate_testing; diff --git a/src/gates/public_input.rs b/src/gates/public_input.rs new file mode 100644 index 00000000..a86b78d5 --- /dev/null +++ b/src/gates/public_input.rs @@ -0,0 +1,84 @@ +use std::ops::Range; + +use crate::circuit_builder::CircuitBuilder; +use crate::field::extension_field::target::ExtensionTarget; +use crate::field::extension_field::Extendable; +use crate::gates::gate::{Gate, GateRef}; +use crate::generator::WitnessGenerator; +use crate::vars::{EvaluationTargets, EvaluationVars}; + +/// A gate whose first four wires will be equal to a hash of public inputs. +pub struct PublicInputGate; + +impl PublicInputGate { + pub fn get, const D: usize>() -> GateRef { + GateRef::new(PublicInputGate) + } + + pub fn wires_public_inputs_hash() -> Range { + 0..4 + } +} + +impl, const D: usize> Gate for PublicInputGate { + fn id(&self) -> String { + "PublicInputGate".into() + } + + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { + Self::wires_public_inputs_hash() + .zip(vars.public_inputs_hash.elements) + .map(|(wire, hash_part)| vars.local_wires[wire] - hash_part.into()) + .collect() + } + + fn eval_unfiltered_recursively( + &self, + builder: &mut CircuitBuilder, + vars: EvaluationTargets, + ) -> Vec> { + Self::wires_public_inputs_hash() + .zip(vars.public_inputs_hash.elements) + .map(|(wire, hash_part)| { + let hash_part_ext = builder.convert_to_ext(hash_part); + builder.sub_extension(vars.local_wires[wire], hash_part_ext) + }) + .collect() + } + + fn generators( + &self, + _gate_index: usize, + _local_constants: &[F], + ) -> Vec>> { + Vec::new() + } + + fn num_wires(&self) -> usize { + 4 + } + + fn num_constants(&self) -> usize { + 0 + } + + fn degree(&self) -> usize { + 1 + } + + fn num_constraints(&self) -> usize { + 4 + } +} + +#[cfg(test)] +mod tests { + use crate::field::crandall_field::CrandallField; + use crate::gates::gate_testing::test_low_degree; + use crate::gates::public_input::PublicInputGate; + + #[test] + fn low_degree() { + test_low_degree(PublicInputGate::get::()) + } +} diff --git a/src/proof.rs b/src/proof.rs index 71edba03..47be8569 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -37,6 +37,12 @@ impl Hash { elements: [elements[0], elements[1], elements[2], elements[3]], } } + + pub(crate) fn rand() -> Self { + Self { + elements: [F::rand(), F::rand(), F::rand(), F::rand()], + } + } } /// Represents a ~256 bit hash output. @@ -79,6 +85,13 @@ pub struct Proof, const D: usize> { pub opening_proof: OpeningProof, } +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(bound = "")] +pub struct ProofWithPublicInputs, const D: usize> { + pub proof: Proof, + pub public_inputs: Vec, +} + pub struct ProofTarget { pub wires_root: HashTarget, pub plonk_zs_partial_products_root: HashTarget, @@ -87,6 +100,11 @@ pub struct ProofTarget { pub opening_proof: OpeningProofTarget, } +pub struct ProofWithPublicInputsTarget { + pub proof: ProofTarget, + pub public_inputs: Vec, +} + /// Evaluations and Merkle proof produced by the prover in a FRI query step. #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(bound = "")] diff --git a/src/prover.rs b/src/prover.rs index e7c85130..4c2e86bc 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -7,11 +7,12 @@ use rayon::prelude::*; use crate::circuit_data::{CommonCircuitData, ProverOnlyCircuitData}; use crate::field::extension_field::Extendable; use crate::generator::generate_partial_witness; +use crate::hash::hash_n_to_hash; use crate::plonk_challenger::Challenger; use crate::plonk_common::{PlonkPolynomials, ZeroPolyOnCoset}; use crate::polynomial::commitment::ListPolynomialCommitment; use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; -use crate::proof::Proof; +use crate::proof::{Hash, Proof, ProofWithPublicInputs}; use crate::timed; use crate::util::partial_products::partial_products; use crate::util::{log2_ceil, transpose}; @@ -23,7 +24,7 @@ pub(crate) fn prove, const D: usize>( prover_data: &ProverOnlyCircuitData, common_data: &CommonCircuitData, inputs: PartialWitness, -) -> Result> { +) -> Result> { let config = &common_data.config; let num_wires = config.num_wires; let num_challenges = config.num_challenges; @@ -39,6 +40,9 @@ pub(crate) fn prove, const D: usize>( "to generate witness" ); + let public_inputs = partial_witness.get_targets(&prover_data.public_inputs); + let public_inputs_hash = hash_n_to_hash(public_inputs.clone(), true); + // Display the marked targets for debugging purposes. for m in &prover_data.marked_targets { m.display(&partial_witness); @@ -119,6 +123,7 @@ pub(crate) fn prove, const D: usize>( compute_quotient_polys( common_data, prover_data, + &public_inputs_hash, &wires_commitment, &zs_partial_products_commitment, &betas, @@ -178,12 +183,16 @@ pub(crate) fn prove, const D: usize>( start_proof_gen.elapsed().as_secs_f32() ); - Ok(Proof { + let proof = Proof { wires_root: wires_commitment.merkle_tree.root, plonk_zs_partial_products_root: zs_partial_products_commitment.merkle_tree.root, quotient_polys_root: quotient_polys_commitment.merkle_tree.root, openings, opening_proof, + }; + Ok(ProofWithPublicInputs { + proof, + public_inputs, }) } @@ -284,6 +293,7 @@ fn compute_z, const D: usize>( fn compute_quotient_polys<'a, F: Extendable, const D: usize>( common_data: &CommonCircuitData, prover_data: &'a ProverOnlyCircuitData, + public_inputs_hash: &Hash, wires_commitment: &'a ListPolynomialCommitment, zs_partial_products_commitment: &'a ListPolynomialCommitment, betas: &[F], @@ -337,6 +347,7 @@ fn compute_quotient_polys<'a, F: Extendable, const D: usize>( let vars = EvaluationVarsBase { local_constants, local_wires, + public_inputs_hash, }; let mut quotient_values = eval_vanishing_poly_base( common_data, diff --git a/src/recursive_verifier.rs b/src/recursive_verifier.rs index 3dd135af..66b63e7f 100644 --- a/src/recursive_verifier.rs +++ b/src/recursive_verifier.rs @@ -3,7 +3,7 @@ use crate::circuit_data::{CircuitConfig, CommonCircuitData, VerifierCircuitTarge use crate::context; use crate::field::extension_field::Extendable; use crate::plonk_challenger::RecursiveChallenger; -use crate::proof::{HashTarget, ProofTarget}; +use crate::proof::{HashTarget, ProofWithPublicInputsTarget}; use crate::util::scaling::ReducingFactorTarget; use crate::vanishing_poly::eval_vanishing_poly_recursively; use crate::vars::EvaluationTargets; @@ -15,15 +15,21 @@ impl, const D: usize> CircuitBuilder { /// Recursively verifies an inner proof. pub fn add_recursive_verifier( &mut self, - proof: ProofTarget, + proof_with_pis: ProofWithPublicInputsTarget, inner_config: &CircuitConfig, inner_verifier_data: &VerifierCircuitTarget, inner_common_data: &CommonCircuitData, ) { assert!(self.config.num_wires >= MIN_WIRES); assert!(self.config.num_wires >= MIN_ROUTED_WIRES); + let ProofWithPublicInputsTarget { + proof, + public_inputs, + } = proof_with_pis; let one = self.one_extension(); + let public_inputs_hash = &self.hash_n_to_hash(public_inputs, true); + let num_challenges = inner_config.num_challenges; let mut challenger = RecursiveChallenger::new(self); @@ -53,6 +59,7 @@ impl, const D: usize> CircuitBuilder { let vars = EvaluationTargets { local_constants, local_wires, + public_inputs_hash, }; let local_zs = &proof.openings.plonk_zs; let next_zs = &proof.openings.plonk_zs_right; @@ -127,7 +134,7 @@ mod tests { use crate::polynomial::commitment::OpeningProofTarget; use crate::proof::{ FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget, - OpeningSetTarget, Proof, + OpeningSetTarget, Proof, ProofTarget, ProofWithPublicInputs, }; use crate::verifier::verify; use crate::witness::PartialWitness; @@ -167,9 +174,14 @@ mod tests { // Construct a `ProofTarget` with the same dimensions as `proof`. fn proof_to_proof_target, const D: usize>( - proof: &Proof, + proof_with_pis: &ProofWithPublicInputs, builder: &mut CircuitBuilder, - ) -> ProofTarget { + ) -> ProofWithPublicInputsTarget { + let ProofWithPublicInputs { + proof, + public_inputs, + } = proof_with_pis; + let wires_root = builder.add_virtual_hash(); let plonk_zs_root = builder.add_virtual_hash(); let quotient_polys_root = builder.add_virtual_hash(); @@ -208,21 +220,41 @@ mod tests { }, }; - ProofTarget { + let proof = ProofTarget { wires_root, plonk_zs_partial_products_root: plonk_zs_root, quotient_polys_root, openings, opening_proof, + }; + + let public_inputs = builder.add_virtual_targets(public_inputs.len()); + ProofWithPublicInputsTarget { + proof, + public_inputs, } } // Set the targets in a `ProofTarget` to their corresponding values in a `Proof`. fn set_proof_target, const D: usize>( - proof: &Proof, - pt: &ProofTarget, + proof: &ProofWithPublicInputs, + pt: &ProofWithPublicInputsTarget, pw: &mut PartialWitness, ) { + let ProofWithPublicInputs { + proof, + public_inputs, + } = proof; + let ProofWithPublicInputsTarget { + proof: pt, + public_inputs: pi_targets, + } = pt; + + // Set public inputs. + for (&pi_t, &pi) in pi_targets.iter().zip(public_inputs) { + pw.set_target(pi_t, pi); + } + pw.set_hash_target(pt.wires_root, proof.wires_root); pw.set_hash_target( pt.plonk_zs_partial_products_root, @@ -343,7 +375,7 @@ mod tests { num_query_rounds: 40, }, }; - let (proof, vd, cd) = { + let (proof_with_pis, vd, cd) = { let mut builder = CircuitBuilder::::new(config.clone()); let _two = builder.two(); let _two = builder.hash_n_to_hash(vec![_two], true).elements[0]; @@ -357,12 +389,12 @@ mod tests { data.common, ) }; - verify(proof.clone(), &vd, &cd)?; + verify(proof_with_pis.clone(), &vd, &cd)?; let mut builder = CircuitBuilder::::new(config.clone()); let mut pw = PartialWitness::new(); - let pt = proof_to_proof_target(&proof, &mut builder); - set_proof_target(&proof, &pt, &mut pw); + let pt = proof_to_proof_target(&proof_with_pis, &mut builder); + set_proof_target(&proof_with_pis, &pt, &mut pw); let inner_data = VerifierCircuitTarget { constants_sigmas_root: builder.add_virtual_hash(), diff --git a/src/target.rs b/src/target.rs index 52be8b5a..857a4378 100644 --- a/src/target.rs +++ b/src/target.rs @@ -7,9 +7,6 @@ use crate::wire::Wire; #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum Target { Wire(Wire), - PublicInput { - index: usize, - }, /// A target that doesn't have any inherent location in the witness (but it can be copied to /// another target that does). This is useful for representing intermediate values in witness /// generation. @@ -26,7 +23,6 @@ impl Target { pub fn is_routable(&self, config: &CircuitConfig) -> bool { match self { Target::Wire(wire) => wire.is_routable(config), - Target::PublicInput { .. } => true, Target::VirtualTarget { .. } => true, } } diff --git a/src/vars.rs b/src/vars.rs index 17d51051..8e98d41f 100644 --- a/src/vars.rs +++ b/src/vars.rs @@ -5,17 +5,20 @@ use crate::field::extension_field::algebra::ExtensionAlgebra; use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget}; use crate::field::extension_field::Extendable; use crate::field::field::Field; +use crate::proof::{Hash, HashTarget}; #[derive(Debug, Copy, Clone)] pub struct EvaluationVars<'a, F: Extendable, const D: usize> { pub(crate) local_constants: &'a [F::Extension], pub(crate) local_wires: &'a [F::Extension], + pub(crate) public_inputs_hash: &'a Hash, } #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBase<'a, F: Field> { pub(crate) local_constants: &'a [F], pub(crate) local_wires: &'a [F], + pub(crate) public_inputs_hash: &'a Hash, } impl<'a, F: Extendable, const D: usize> EvaluationVars<'a, F, D> { @@ -49,6 +52,7 @@ impl<'a, const D: usize> EvaluationTargets<'a, D> { pub struct EvaluationTargets<'a, const D: usize> { pub(crate) local_constants: &'a [ExtensionTarget], pub(crate) local_wires: &'a [ExtensionTarget], + pub(crate) public_inputs_hash: &'a HashTarget, } impl<'a, const D: usize> EvaluationTargets<'a, D> { diff --git a/src/verifier.rs b/src/verifier.rs index 6b4df627..878b630a 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -3,20 +3,27 @@ use anyhow::{ensure, Result}; use crate::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData}; use crate::field::extension_field::Extendable; use crate::field::field::Field; +use crate::hash::hash_n_to_hash; use crate::plonk_challenger::Challenger; use crate::plonk_common::reduce_with_powers; -use crate::proof::Proof; +use crate::proof::ProofWithPublicInputs; use crate::vanishing_poly::eval_vanishing_poly; use crate::vars::EvaluationVars; pub(crate) fn verify, const D: usize>( - proof: Proof, + proof_with_pis: ProofWithPublicInputs, verifier_data: &VerifierOnlyCircuitData, common_data: &CommonCircuitData, ) -> Result<()> { + let ProofWithPublicInputs { + proof, + public_inputs, + } = proof_with_pis; let config = &common_data.config; let num_challenges = config.num_challenges; + let public_inputs_hash = &hash_n_to_hash(public_inputs, true); + let mut challenger = Challenger::new(); // Observe the instance. // TODO: Need to include public inputs as well. @@ -37,6 +44,7 @@ pub(crate) fn verify, const D: usize>( let vars = EvaluationVars { local_constants, local_wires, + public_inputs_hash, }; let local_zs = &proof.openings.plonk_zs; let next_zs = &proof.openings.plonk_zs_right; diff --git a/src/witness.rs b/src/witness.rs index 25885ba3..cdeafcce 100644 --- a/src/witness.rs +++ b/src/witness.rs @@ -193,7 +193,6 @@ impl PartialWitness { gate, gate_instances[*gate].gate_type.0.id() ), - Target::PublicInput { index } => format!("{}-th public input", index), Target::VirtualTarget { index } => format!("{}-th virtual target", index), } };