diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index a7e87339..06d4d8bf 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -1,16 +1,19 @@ -use std::collections::{HashSet, HashMap}; +use std::collections::{HashMap, HashSet}; use std::time::Instant; use log::info; -use crate::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData, VerifierCircuitData, VerifierOnlyCircuitData}; +use crate::circuit_data::{ + CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData, + VerifierCircuitData, VerifierOnlyCircuitData, +}; +use crate::field::cosets::get_unique_coset_shifts; use crate::field::field::Field; use crate::gates::constant::ConstantGate; use crate::gates::gate::{GateInstance, GateRef}; use crate::gates::noop::NoopGate; use crate::generator::{CopyGenerator, WitnessGenerator}; -use crate::hash::merkle_root_bit_rev_order; -use crate::field::cosets::get_unique_coset_shifts; +use crate::hash::{hash_n_to_hash, merkle_root_bit_rev_order}; use crate::polynomial::polynomial::PolynomialValues; use crate::target::Target; use crate::util::{log2_strict, transpose, transpose_poly_values}; @@ -84,14 +87,21 @@ impl CircuitBuilder { // TODO: Not passing next constants for now. Not sure if it's really useful... self.add_generators(gate_type.0.generators(index, &constants, &[])); - self.gate_instances.push(GateInstance { gate_type, constants }); + self.gate_instances.push(GateInstance { + gate_type, + constants, + }); index } fn check_gate_compatibility(&self, gate: &GateRef) { - assert!(gate.0.num_wires() <= self.config.num_wires, - "{:?} requires {} wires, but our GateConfig has only {}", - gate.0.id(), gate.0.num_wires(), self.config.num_wires); + assert!( + gate.0.num_wires() <= self.config.num_wires, + "{:?} requires {} wires, but our GateConfig has only {}", + gate.0.id(), + gate.0.num_wires(), + self.config.num_wires + ); } /// Shorthand for `generate_copy` and `assert_equal`. @@ -109,8 +119,14 @@ impl CircuitBuilder { /// Uses Plonk's permutation argument to require that two elements be equal. /// Both elements must be routable, otherwise this method will panic. pub fn assert_equal(&mut self, x: Target, y: Target) { - assert!(x.is_routable(self.config), "Tried to route a wire that isn't routable"); - assert!(y.is_routable(self.config), "Tried to route a wire that isn't routable"); + assert!( + x.is_routable(self.config), + "Tried to route a wire that isn't routable" + ); + assert!( + y.is_routable(self.config), + "Tried to route a wire that isn't routable" + ); // TODO: Add to copy_constraints. } @@ -150,7 +166,10 @@ impl CircuitBuilder { } let gate = self.add_gate(ConstantGate::get(), vec![c]); - let target = Target::Wire(Wire { gate, input: ConstantGate::WIRE_OUTPUT }); + let target = Target::Wire(Wire { + gate, + input: ConstantGate::WIRE_OUTPUT, + }); self.constants_to_targets.insert(c, target); self.targets_to_constants.insert(target, c); target @@ -175,11 +194,15 @@ impl CircuitBuilder { } fn constant_polys(&self) -> Vec> { - let num_constants = self.gate_instances.iter() + let num_constants = self + .gate_instances + .iter() .map(|gate_inst| gate_inst.constants.len()) .max() .unwrap(); - let constants_per_gate = self.gate_instances.iter() + let constants_per_gate = self + .gate_instances + .iter() .map(|gate_inst| { let mut padded_constants = gate_inst.constants.clone(); for _ in padded_constants.len()..num_constants { @@ -196,13 +219,17 @@ impl CircuitBuilder { } fn sigma_vecs(&self) -> Vec> { - vec![PolynomialValues::zero(self.gate_instances.len()); self.config.num_routed_wires] // TODO + vec![PolynomialValues::zero(self.gate_instances.len()); self.config.num_routed_wires] + // TODO } /// Builds a "full circuit", with both prover and verifier data. pub fn build(mut self) -> CircuitData { let start = Instant::now(); - info!("degree before blinding & padding: {}", self.gate_instances.len()); + info!( + "degree before blinding & padding: {}", + self.gate_instances.len() + ); self.blind_and_pad(); let degree = self.gate_instances.len(); info!("degree after blinding & padding: {}", degree); @@ -218,7 +245,11 @@ impl CircuitBuilder { let sigmas_root = merkle_root_bit_rev_order(sigma_ldes_t.clone()); let generators = self.generators; - let prover_only = ProverOnlyCircuitData { generators, constant_ldes_t, sigma_ldes_t }; + let prover_only = ProverOnlyCircuitData { + generators, + constant_ldes_t, + sigma_ldes_t, + }; let verifier_only = VerifierOnlyCircuitData {}; // The HashSet of gates will have a non-deterministic order. When converting to a Vec, we @@ -226,7 +257,8 @@ impl CircuitBuilder { let mut gates = self.gates.iter().cloned().collect::>(); gates.sort_unstable_by_key(|gate| gate.0.id()); - let num_gate_constraints = gates.iter() + let num_gate_constraints = gates + .iter() .map(|gate| gate.0.num_constraints()) .max() .expect("No gates?"); @@ -234,6 +266,13 @@ impl CircuitBuilder { let degree_bits = log2_strict(degree); let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires); + // TODO: This should also include an encoding of gate constraints. + let circuit_digest_parts = [ + constants_root.elements, + sigmas_root.elements, + ]; + let circuit_digest = hash_n_to_hash(circuit_digest_parts.concat(), false); + let common = CommonCircuitData { config: self.config, degree_bits, @@ -242,6 +281,7 @@ impl CircuitBuilder { constants_root, sigmas_root, k_is, + circuit_digest, }; info!("Building circuit took {}s", start.elapsed().as_secs_f32()); @@ -255,14 +295,28 @@ impl CircuitBuilder { /// 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. - let CircuitData { prover_only, common, .. } = self.build(); - ProverCircuitData { prover_only, common } + let CircuitData { + prover_only, + common, + .. + } = self.build(); + ProverCircuitData { + prover_only, + common, + } } /// Builds a "verifier circuit", with data needed to verify proofs but not generate them. pub fn build_verifier(self) -> VerifierCircuitData { // TODO: Can skip parts of this. - let CircuitData { verifier_only, common, .. } = self.build(); - VerifierCircuitData { verifier_only, common } + let CircuitData { + verifier_only, + common, + .. + } = self.build(); + VerifierCircuitData { + verifier_only, + common, + } } } diff --git a/src/circuit_data.rs b/src/circuit_data.rs index ef0a74c6..bb21e0c6 100644 --- a/src/circuit_data.rs +++ b/src/circuit_data.rs @@ -112,6 +112,10 @@ pub(crate) struct CommonCircuitData { /// The `{k_i}` valued used in `S_ID_i` in Plonk's permutation argument. pub(crate) k_is: Vec, + + /// A digest of the "circuit" (i.e. the instance, minus public inputs), which can be used to + /// seed Fiat-Shamir. + pub(crate) circuit_digest: Hash, } impl CommonCircuitData { diff --git a/src/gadgets/arithmetic.rs b/src/gadgets/arithmetic.rs index 8fa727bb..00885e7e 100644 --- a/src/gadgets/arithmetic.rs +++ b/src/gadgets/arithmetic.rs @@ -1,9 +1,9 @@ use crate::circuit_builder::CircuitBuilder; use crate::field::field::Field; use crate::gates::arithmetic::ArithmeticGate; +use crate::generator::SimpleGenerator; use crate::target::Target; use crate::wire::Wire; -use crate::generator::SimpleGenerator; use crate::witness::PartialWitness; impl CircuitBuilder { @@ -22,8 +22,9 @@ impl CircuitBuilder { addend: Target, ) -> Target { // See if we can determine the result without adding an `ArithmeticGate`. - if let Some(result) = self.arithmetic_special_cases( - const_0, multiplicand_0, multiplicand_1, const_1, addend) { + if let Some(result) = + self.arithmetic_special_cases(const_0, multiplicand_0, multiplicand_1, const_1, addend) + { return result; } @@ -69,7 +70,8 @@ impl CircuitBuilder { let mul_1_const = self.target_as_constant(multiplicand_1); let addend_const = self.target_as_constant(addend); - let first_term_zero = const_0 == F::ZERO || multiplicand_0 == zero || multiplicand_1 == zero; + let first_term_zero = + const_0 == F::ZERO || multiplicand_0 == zero || multiplicand_1 == zero; let second_term_zero = const_1 == F::ZERO || addend == zero; // If both terms are constant, return their (constant) sum. @@ -156,17 +158,31 @@ impl CircuitBuilder { if y == one { return x; } - if let (Some(x_const), Some(y_const)) = (self.target_as_constant(x), self.target_as_constant(y)) { + if let (Some(x_const), Some(y_const)) = + (self.target_as_constant(x), self.target_as_constant(y)) + { return self.constant(x_const / y_const); } // Add an `ArithmeticGate` to compute `q * y`. let gate = self.add_gate(ArithmeticGate::new(), vec![F::ONE, F::ZERO]); - let wire_multiplicand_0 = Wire { gate, input: ArithmeticGate::WIRE_MULTIPLICAND_0 }; - let wire_multiplicand_1 = Wire { gate, input: ArithmeticGate::WIRE_MULTIPLICAND_1 }; - let wire_addend = Wire { gate, input: ArithmeticGate::WIRE_ADDEND }; - let wire_output = Wire { gate, input: ArithmeticGate::WIRE_OUTPUT }; + let wire_multiplicand_0 = Wire { + gate, + input: ArithmeticGate::WIRE_MULTIPLICAND_0, + }; + let wire_multiplicand_1 = Wire { + gate, + input: ArithmeticGate::WIRE_MULTIPLICAND_1, + }; + let wire_addend = Wire { + gate, + input: ArithmeticGate::WIRE_ADDEND, + }; + let wire_output = Wire { + gate, + input: ArithmeticGate::WIRE_OUTPUT, + }; let q = Target::Wire(wire_multiplicand_0); self.add_generator(QuotientGenerator { diff --git a/src/prover.rs b/src/prover.rs index 32735e17..17b52ded 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -68,6 +68,10 @@ pub(crate) fn prove( ); let mut challenger = Challenger::new(); + // Observe the instance. + // TODO: Need to include public inputs as well. + challenger.observe_hash(&common_data.circuit_digest); + challenger.observe_hash(&wires_root); let betas = challenger.get_n_challenges(num_checks); let gammas = challenger.get_n_challenges(num_checks); diff --git a/src/recursive_verifier.rs b/src/recursive_verifier.rs index 54d35bf0..b850e587 100644 --- a/src/recursive_verifier.rs +++ b/src/recursive_verifier.rs @@ -17,4 +17,6 @@ pub fn add_recursive_verifier( ) { assert!(builder.config.num_wires >= MIN_WIRES); assert!(builder.config.num_wires >= MIN_ROUTED_WIRES); + + todo!() }