2021-04-22 16:32:57 -07:00
|
|
|
use std::collections::{HashMap, HashSet};
|
2021-07-08 17:16:26 +02:00
|
|
|
use std::convert::TryInto;
|
2021-03-25 15:20:14 -07:00
|
|
|
use std::time::Instant;
|
2021-02-26 13:18:41 -08:00
|
|
|
|
2021-08-02 10:38:09 -07:00
|
|
|
use log::{info, Level};
|
2021-03-25 15:20:14 -07:00
|
|
|
|
2021-04-22 16:32:57 -07:00
|
|
|
use crate::field::cosets::get_unique_coset_shifts;
|
2021-06-07 17:55:27 +02:00
|
|
|
use crate::field::extension_field::target::ExtensionTarget;
|
2021-07-30 09:03:11 -07:00
|
|
|
use crate::field::extension_field::{Extendable, FieldExtension};
|
2021-09-07 18:28:28 -07:00
|
|
|
use crate::field::field_types::RichField;
|
2021-07-29 22:00:29 -07:00
|
|
|
use crate::fri::commitment::PolynomialBatchCommitment;
|
2021-08-17 09:12:40 +02:00
|
|
|
use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS};
|
2021-03-28 15:36:51 -07:00
|
|
|
use crate::gates::constant::ConstantGate;
|
2021-07-22 23:48:03 -07:00
|
|
|
use crate::gates::gate::{Gate, GateInstance, GateRef, PrefixedGate};
|
2021-06-22 16:54:20 +02:00
|
|
|
use crate::gates::gate_tree::Tree;
|
2021-03-28 15:36:51 -07:00
|
|
|
use crate::gates::noop::NoopGate;
|
2021-07-21 08:26:19 -07:00
|
|
|
use crate::gates::public_input::PublicInputGate;
|
2021-09-01 16:38:10 -07:00
|
|
|
use crate::gates::switch::SwitchGate;
|
2021-08-10 13:33:44 +02:00
|
|
|
use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget};
|
2021-07-29 22:00:29 -07:00
|
|
|
use crate::hash::hashing::hash_n_to_hash;
|
2021-09-02 15:03:03 -07:00
|
|
|
use crate::iop::generator::{
|
|
|
|
|
CopyGenerator, RandomValueGenerator, SimpleGenerator, WitnessGenerator,
|
|
|
|
|
};
|
2021-08-14 08:53:39 -07:00
|
|
|
use crate::iop::target::{BoolTarget, Target};
|
2021-07-29 22:00:29 -07:00
|
|
|
use crate::iop::wire::Wire;
|
2021-08-20 11:13:40 +02:00
|
|
|
use crate::iop::witness::PartitionWitness;
|
2021-07-29 22:00:29 -07:00
|
|
|
use crate::plonk::circuit_data::{
|
|
|
|
|
CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData,
|
|
|
|
|
VerifierCircuitData, VerifierOnlyCircuitData,
|
|
|
|
|
};
|
|
|
|
|
use crate::plonk::copy_constraint::CopyConstraint;
|
|
|
|
|
use crate::plonk::plonk_common::PlonkPolynomials;
|
2021-03-30 13:30:31 -07:00
|
|
|
use crate::polynomial::polynomial::PolynomialValues;
|
2021-07-29 22:00:29 -07:00
|
|
|
use crate::util::context_tree::ContextTree;
|
2021-07-14 20:54:30 +02:00
|
|
|
use crate::util::marking::{Markable, MarkedTargets};
|
2021-07-01 15:41:01 +02:00
|
|
|
use crate::util::partial_products::num_partial_products;
|
2021-08-02 10:38:09 -07:00
|
|
|
use crate::util::timing::TimingTree;
|
2021-06-29 10:07:05 -07:00
|
|
|
use crate::util::{log2_ceil, log2_strict, transpose, transpose_poly_values};
|
2021-02-26 13:18:41 -08:00
|
|
|
|
2021-09-07 18:28:28 -07:00
|
|
|
pub struct CircuitBuilder<F: RichField + Extendable<D>, const D: usize> {
|
2021-03-28 15:36:51 -07:00
|
|
|
pub(crate) config: CircuitConfig,
|
2021-03-21 11:57:33 -07:00
|
|
|
|
|
|
|
|
/// The types of gates used in this circuit.
|
2021-05-30 13:25:53 -07:00
|
|
|
gates: HashSet<GateRef<F, D>>,
|
2021-03-21 11:57:33 -07:00
|
|
|
|
2021-04-07 22:21:45 -07:00
|
|
|
/// The concrete placement of each gate.
|
2021-08-24 18:35:30 -07:00
|
|
|
pub(crate) gate_instances: Vec<GateInstance<F, D>>,
|
2021-03-21 11:57:33 -07:00
|
|
|
|
2021-07-21 08:26:19 -07:00
|
|
|
/// Targets to be made public.
|
|
|
|
|
public_inputs: Vec<Target>,
|
2021-04-25 17:02:02 -07:00
|
|
|
|
2021-07-01 08:12:12 -07:00
|
|
|
/// The next available index for a `VirtualTarget`.
|
2021-07-15 10:55:18 +02:00
|
|
|
virtual_target_index: usize,
|
2021-04-07 22:21:45 -07:00
|
|
|
|
2021-07-14 20:54:30 +02:00
|
|
|
copy_constraints: Vec<CopyConstraint>,
|
|
|
|
|
|
2021-07-19 12:22:18 -07:00
|
|
|
/// A tree of named scopes, used for debugging.
|
|
|
|
|
context_log: ContextTree,
|
2021-07-14 20:54:30 +02:00
|
|
|
|
2021-07-15 10:24:11 +02:00
|
|
|
/// A vector of marked targets. The values assigned to these targets will be displayed by the prover.
|
|
|
|
|
marked_targets: Vec<MarkedTargets<D>>,
|
2021-04-25 17:02:02 -07:00
|
|
|
|
2021-04-07 22:21:45 -07:00
|
|
|
/// Generators used to generate the witness.
|
2021-07-15 10:13:13 +02:00
|
|
|
generators: Vec<Box<dyn WitnessGenerator<F>>>,
|
2021-04-21 11:47:18 -07:00
|
|
|
|
|
|
|
|
constants_to_targets: HashMap<F, Target>,
|
|
|
|
|
targets_to_constants: HashMap<Target, F>,
|
2021-08-13 14:28:05 +02:00
|
|
|
|
2021-08-16 10:18:10 +02:00
|
|
|
/// A map `(c0, c1) -> (g, i)` from constants `(c0,c1)` to an available arithmetic gate using
|
|
|
|
|
/// these constants with gate index `g` and already using `i` arithmetic operations.
|
|
|
|
|
pub(crate) free_arithmetic: HashMap<(F, F), (usize, usize)>,
|
2021-08-24 18:35:30 -07:00
|
|
|
|
2021-09-01 16:38:10 -07:00
|
|
|
// `current_switch_gates[chunk_size - 1]` contains None if we have no switch gates with the value
|
|
|
|
|
// chunk_size, and contains `(g, i, c)`, if the gate `g`, at index `i`, already contains `c` copies
|
|
|
|
|
// of switches
|
|
|
|
|
pub(crate) current_switch_gates: Vec<Option<(SwitchGate<F, D>, usize, usize)>>,
|
2021-02-26 13:18:41 -08:00
|
|
|
}
|
|
|
|
|
|
2021-09-07 18:28:28 -07:00
|
|
|
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
2021-02-26 13:18:41 -08:00
|
|
|
pub fn new(config: CircuitConfig) -> Self {
|
2021-03-25 15:20:14 -07:00
|
|
|
CircuitBuilder {
|
2021-02-26 13:18:41 -08:00
|
|
|
config,
|
|
|
|
|
gates: HashSet::new(),
|
|
|
|
|
gate_instances: Vec::new(),
|
2021-07-21 08:26:19 -07:00
|
|
|
public_inputs: Vec::new(),
|
2021-04-07 22:21:45 -07:00
|
|
|
virtual_target_index: 0,
|
2021-04-25 17:02:02 -07:00
|
|
|
copy_constraints: Vec::new(),
|
2021-07-19 12:22:18 -07:00
|
|
|
context_log: ContextTree::new(),
|
2021-07-14 20:54:30 +02:00
|
|
|
marked_targets: Vec::new(),
|
2021-02-26 13:18:41 -08:00
|
|
|
generators: Vec::new(),
|
2021-04-21 11:47:18 -07:00
|
|
|
constants_to_targets: HashMap::new(),
|
|
|
|
|
targets_to_constants: HashMap::new(),
|
2021-08-16 10:18:10 +02:00
|
|
|
free_arithmetic: HashMap::new(),
|
2021-08-24 18:35:30 -07:00
|
|
|
current_switch_gates: Vec::new(),
|
2021-02-26 13:18:41 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-29 12:33:11 -07:00
|
|
|
pub fn num_gates(&self) -> usize {
|
|
|
|
|
self.gate_instances.len()
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-21 08:26:19 -07:00
|
|
|
/// Registers the given target as a public input.
|
|
|
|
|
pub fn register_public_input(&mut self, target: Target) {
|
|
|
|
|
self.public_inputs.push(target);
|
2021-04-25 17:02:02 -07:00
|
|
|
}
|
|
|
|
|
|
2021-07-21 08:26:19 -07:00
|
|
|
/// 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));
|
2021-04-25 17:02:02 -07:00
|
|
|
}
|
|
|
|
|
|
2021-07-01 08:12:12 -07:00
|
|
|
/// Adds a new "virtual" target. This is not an actual wire in the witness, but just a target
|
|
|
|
|
/// that help facilitate witness generation. In particular, a generator can assign a values to a
|
|
|
|
|
/// virtual target, which can then be copied to other (virtual or concrete) targets. When we
|
|
|
|
|
/// generate the final witness (a grid of wire values), these virtual targets will go away.
|
|
|
|
|
pub fn add_virtual_target(&mut self) -> Target {
|
2021-04-07 22:21:45 -07:00
|
|
|
let index = self.virtual_target_index;
|
|
|
|
|
self.virtual_target_index += 1;
|
2021-07-01 08:12:12 -07:00
|
|
|
Target::VirtualTarget { index }
|
2021-04-07 22:21:45 -07:00
|
|
|
}
|
|
|
|
|
|
2021-07-01 08:12:12 -07:00
|
|
|
pub fn add_virtual_targets(&mut self, n: usize) -> Vec<Target> {
|
|
|
|
|
(0..n).map(|_i| self.add_virtual_target()).collect()
|
2021-04-07 22:21:45 -07:00
|
|
|
}
|
|
|
|
|
|
2021-07-29 22:00:29 -07:00
|
|
|
pub fn add_virtual_hash(&mut self) -> HashOutTarget {
|
|
|
|
|
HashOutTarget::from_vec(self.add_virtual_targets(4))
|
2021-07-08 17:16:26 +02:00
|
|
|
}
|
|
|
|
|
|
2021-08-10 13:33:44 +02:00
|
|
|
pub fn add_virtual_cap(&mut self, cap_height: usize) -> MerkleCapTarget {
|
|
|
|
|
MerkleCapTarget(self.add_virtual_hashes(1 << cap_height))
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-29 22:00:29 -07:00
|
|
|
pub fn add_virtual_hashes(&mut self, n: usize) -> Vec<HashOutTarget> {
|
2021-07-08 17:16:26 +02:00
|
|
|
(0..n).map(|_i| self.add_virtual_hash()).collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn add_virtual_extension_target(&mut self) -> ExtensionTarget<D> {
|
|
|
|
|
ExtensionTarget(self.add_virtual_targets(D).try_into().unwrap())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn add_virtual_extension_targets(&mut self, n: usize) -> Vec<ExtensionTarget<D>> {
|
|
|
|
|
(0..n)
|
|
|
|
|
.map(|_i| self.add_virtual_extension_target())
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-14 08:53:39 -07:00
|
|
|
// TODO: Unsafe
|
|
|
|
|
pub fn add_virtual_bool_target(&mut self) -> BoolTarget {
|
|
|
|
|
BoolTarget::new_unsafe(self.add_virtual_target())
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-26 13:18:41 -08:00
|
|
|
/// Adds a gate to the circuit, and returns its index.
|
2021-07-22 23:48:03 -07:00
|
|
|
pub fn add_gate<G: Gate<F, D>>(&mut self, gate_type: G, constants: Vec<F>) -> usize {
|
|
|
|
|
self.check_gate_compatibility(&gate_type);
|
2021-06-23 18:04:43 +02:00
|
|
|
assert_eq!(
|
2021-07-22 23:48:03 -07:00
|
|
|
gate_type.num_constants(),
|
2021-06-23 18:04:43 +02:00
|
|
|
constants.len(),
|
|
|
|
|
"Number of constants doesn't match."
|
|
|
|
|
);
|
2021-02-26 13:18:41 -08:00
|
|
|
|
|
|
|
|
let index = self.gate_instances.len();
|
2021-07-22 23:48:03 -07:00
|
|
|
self.add_generators(gate_type.generators(index, &constants));
|
2021-04-02 15:29:21 -07:00
|
|
|
|
2021-07-22 23:48:03 -07:00
|
|
|
// Register this gate type if we haven't seen it before.
|
|
|
|
|
let gate_ref = GateRef::new(gate_type);
|
|
|
|
|
self.gates.insert(gate_ref.clone());
|
2021-04-02 15:29:21 -07:00
|
|
|
|
2021-04-22 16:32:57 -07:00
|
|
|
self.gate_instances.push(GateInstance {
|
2021-07-22 23:48:03 -07:00
|
|
|
gate_ref,
|
2021-04-22 16:32:57 -07:00
|
|
|
constants,
|
|
|
|
|
});
|
2021-02-26 13:18:41 -08:00
|
|
|
index
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-22 23:48:03 -07:00
|
|
|
fn check_gate_compatibility<G: Gate<F, D>>(&self, gate: &G) {
|
2021-04-22 16:32:57 -07:00
|
|
|
assert!(
|
2021-07-22 23:48:03 -07:00
|
|
|
gate.num_wires() <= self.config.num_wires,
|
2021-04-22 16:32:57 -07:00
|
|
|
"{:?} requires {} wires, but our GateConfig has only {}",
|
2021-07-22 23:48:03 -07:00
|
|
|
gate.id(),
|
|
|
|
|
gate.num_wires(),
|
2021-04-22 16:32:57 -07:00
|
|
|
self.config.num_wires
|
|
|
|
|
);
|
2021-02-26 13:18:41 -08:00
|
|
|
}
|
|
|
|
|
|
2021-08-24 08:25:11 +02:00
|
|
|
pub fn connect_extension(&mut self, src: ExtensionTarget<D>, dst: ExtensionTarget<D>) {
|
2021-06-07 17:55:27 +02:00
|
|
|
for i in 0..D {
|
2021-08-24 08:25:11 +02:00
|
|
|
self.connect(src.0[i], dst.0[i]);
|
2021-06-07 17:55:27 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-26 13:18:41 -08:00
|
|
|
/// Adds a generator which will copy `src` to `dst`.
|
|
|
|
|
pub fn generate_copy(&mut self, src: Target, dst: Target) {
|
2021-09-02 15:03:03 -07:00
|
|
|
self.add_simple_generator(CopyGenerator { src, dst });
|
2021-02-26 13:18:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Uses Plonk's permutation argument to require that two elements be equal.
|
|
|
|
|
/// Both elements must be routable, otherwise this method will panic.
|
2021-08-24 08:25:11 +02:00
|
|
|
pub fn connect(&mut self, x: Target, y: Target) {
|
2021-04-22 16:32:57 -07:00
|
|
|
assert!(
|
2021-05-07 11:30:03 +02:00
|
|
|
x.is_routable(&self.config),
|
2021-04-22 16:32:57 -07:00
|
|
|
"Tried to route a wire that isn't routable"
|
|
|
|
|
);
|
|
|
|
|
assert!(
|
2021-05-07 11:30:03 +02:00
|
|
|
y.is_routable(&self.config),
|
2021-04-22 16:32:57 -07:00
|
|
|
"Tried to route a wire that isn't routable"
|
|
|
|
|
);
|
2021-07-14 20:54:30 +02:00
|
|
|
self.copy_constraints
|
2021-07-19 12:22:18 -07:00
|
|
|
.push(CopyConstraint::new((x, y), self.context_log.open_stack()));
|
2021-07-14 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
2021-06-04 16:02:48 +02:00
|
|
|
pub fn assert_zero(&mut self, x: Target) {
|
|
|
|
|
let zero = self.zero();
|
2021-08-24 08:25:11 +02:00
|
|
|
self.connect(x, zero);
|
2021-06-04 16:02:48 +02:00
|
|
|
}
|
|
|
|
|
|
2021-04-02 15:29:21 -07:00
|
|
|
pub fn add_generators(&mut self, generators: Vec<Box<dyn WitnessGenerator<F>>>) {
|
|
|
|
|
self.generators.extend(generators);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-02 15:03:03 -07:00
|
|
|
pub fn add_simple_generator<G: SimpleGenerator<F>>(&mut self, generator: G) {
|
|
|
|
|
self.generators.push(Box::new(generator.adapter()));
|
2021-02-26 13:18:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns a routable target with a value of 0.
|
|
|
|
|
pub fn zero(&mut self) -> Target {
|
|
|
|
|
self.constant(F::ZERO)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns a routable target with a value of 1.
|
|
|
|
|
pub fn one(&mut self) -> Target {
|
|
|
|
|
self.constant(F::ONE)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns a routable target with a value of 2.
|
|
|
|
|
pub fn two(&mut self) -> Target {
|
|
|
|
|
self.constant(F::TWO)
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-21 13:05:32 -07:00
|
|
|
/// Returns a routable target with a value of `order() - 1`.
|
2021-02-26 13:18:41 -08:00
|
|
|
pub fn neg_one(&mut self) -> Target {
|
|
|
|
|
self.constant(F::NEG_ONE)
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-14 08:53:39 -07:00
|
|
|
pub fn _false(&mut self) -> BoolTarget {
|
|
|
|
|
BoolTarget::new_unsafe(self.zero())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn _true(&mut self) -> BoolTarget {
|
|
|
|
|
BoolTarget::new_unsafe(self.one())
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-26 13:18:41 -08:00
|
|
|
/// Returns a routable target with the given constant value.
|
|
|
|
|
pub fn constant(&mut self, c: F) -> Target {
|
2021-04-21 11:47:18 -07:00
|
|
|
if let Some(&target) = self.constants_to_targets.get(&c) {
|
|
|
|
|
// We already have a wire for this constant.
|
|
|
|
|
return target;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-22 23:48:03 -07:00
|
|
|
let gate = self.add_gate(ConstantGate, vec![c]);
|
2021-04-22 16:32:57 -07:00
|
|
|
let target = Target::Wire(Wire {
|
|
|
|
|
gate,
|
|
|
|
|
input: ConstantGate::WIRE_OUTPUT,
|
|
|
|
|
});
|
2021-04-21 11:47:18 -07:00
|
|
|
self.constants_to_targets.insert(c, target);
|
|
|
|
|
self.targets_to_constants.insert(target, c);
|
|
|
|
|
target
|
2021-02-26 13:18:41 -08:00
|
|
|
}
|
2021-03-21 11:17:00 -07:00
|
|
|
|
2021-04-02 14:00:26 -07:00
|
|
|
pub fn constants(&mut self, constants: &[F]) -> Vec<Target> {
|
|
|
|
|
constants.iter().map(|&c| self.constant(c)).collect()
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-14 08:53:39 -07:00
|
|
|
pub fn constant_bool(&mut self, b: bool) -> BoolTarget {
|
|
|
|
|
if b {
|
|
|
|
|
self._true()
|
|
|
|
|
} else {
|
|
|
|
|
self._false()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-21 11:47:18 -07:00
|
|
|
/// If the given target is a constant (i.e. it was created by the `constant(F)` method), returns
|
|
|
|
|
/// its constant value. Otherwise, returns `None`.
|
|
|
|
|
pub fn target_as_constant(&self, target: Target) -> Option<F> {
|
|
|
|
|
self.targets_to_constants.get(&target).cloned()
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-30 09:03:11 -07:00
|
|
|
/// If the given `ExtensionTarget` is a constant (i.e. it was created by the
|
|
|
|
|
/// `constant_extension(F)` method), returns its constant value. Otherwise, returns `None`.
|
|
|
|
|
pub fn target_as_constant_ext(&self, target: ExtensionTarget<D>) -> Option<F::Extension> {
|
|
|
|
|
// Get a Vec of any coefficients that are constant. If we end up with exactly D of them,
|
|
|
|
|
// then the `ExtensionTarget` as a whole is constant.
|
|
|
|
|
let const_coeffs: Vec<F> = target
|
|
|
|
|
.0
|
2021-08-02 10:58:03 -07:00
|
|
|
.iter()
|
2021-07-30 09:03:11 -07:00
|
|
|
.filter_map(|&t| self.target_as_constant(t))
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
if let Ok(d_const_coeffs) = const_coeffs.try_into() {
|
|
|
|
|
Some(F::Extension::from_basefield_array(d_const_coeffs))
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Reduce noise in FRI logging (#129)
* Reduce noise in FRI logging
Previously, all logs related to gate counts were at the `Debug` log level. This PR gives us more flexibility to adjust the log levels of particular scopes.
In particular, our circuit checks 40 FRI queries, and we log a bunch of steps for each query, creating a lot of noise. With this change, we log just a single FRI query at the `Debug` level, and demote others to the `Trace` level.
With `RUST_LOG=debug`, our logs now look like
```
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] 17631 gates to root
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 8 gates to observe proof and generates challenges
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 4150 gates to evaluate the vanishing polynomial at our challenge point, zeta.
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 3184 gates to evaluate gate constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 227 gates to evaluate InterpolationGate { num_points: 4, _phantom: PhantomData }<D=4> constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 867 gates to evaluate <R=101> GMiMCGate { ... } constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 576 gates to evaluate BaseSumGate { num_limbs: 63 } + Base: 2 constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 78 gates to evaluate ArithmeticExtensionGate constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 288 gates to evaluate BaseSumGate { num_limbs: 31 } + Base: 2 constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 115 gates to evaluate InsertionGate { vec_size: 3, _phantom: PhantomData }<D=4> constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 26 gates to evaluate BaseSumGate { num_limbs: 2 } + Base: 2 constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 633 gates to evaluate ReducingGate { num_coeffs: 21 } constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 4 gates to evaluate ConstantGate constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 11 gates to evaluate PublicInputGate constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 2 gates to evaluate NoopGate constraints
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 16 gates to check vanishing and quotient polynomials.
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | 13336 gates to verify FRI proof
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 6 gates to recover the random betas used in the FRI reductions.
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 4 gates to check PoW
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 104 gates to precompute reduced evaluations
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 330 gates to verify one (of 40) query rounds
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 95 gates to check FRI initial proof
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 22 gates to verify 0'th initial Merkle proof
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 33 gates to verify 1'th initial Merkle proof
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 20 gates to verify 2'th initial Merkle proof
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | | 20 gates to verify 3'th initial Merkle proof
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 34 gates to compute x from its index
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 32 gates to combine initial oracles
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 17 gates to verify FRI round Merkle proof.
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 15 gates to verify FRI round Merkle proof.
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 13 gates to verify FRI round Merkle proof.
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 11 gates to verify FRI round Merkle proof.
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 9 gates to verify FRI round Merkle proof.
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer evaluation using interpolation
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 7 gates to verify FRI round Merkle proof.
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 10 gates to infer final evaluation using interpolation
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | | 8 gates to evaluate final polynomial
```
This bit corresponds to the single FRI query being shown:
```
[2021-07-26T21:07:45Z DEBUG plonky2::context_tree] | | 330 gates to verify one (of 40) query rounds
```
* Minor cleanup
* Address feedback
2021-07-26 16:21:14 -07:00
|
|
|
pub fn push_context(&mut self, level: log::Level, ctx: &str) {
|
|
|
|
|
self.context_log.push(ctx, level, self.num_gates());
|
2021-07-19 12:22:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn pop_context(&mut self) {
|
|
|
|
|
self.context_log.pop(self.num_gates());
|
2021-07-14 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
2021-07-15 09:52:42 +02:00
|
|
|
pub fn add_marked(&mut self, targets: Markable<D>, name: &str) {
|
2021-07-14 20:54:30 +02:00
|
|
|
self.marked_targets.push(MarkedTargets {
|
|
|
|
|
targets,
|
|
|
|
|
name: name.to_string(),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-28 23:08:24 -07:00
|
|
|
/// The number of polynomial values that will be revealed per opening, both for the "regular"
|
|
|
|
|
/// polynomials and for the Z polynomials. Because calculating these values involves a recursive
|
|
|
|
|
/// dependence (the amount of blinding depends on the degree, which depends on the blinding),
|
|
|
|
|
/// this function takes in an estimate of the degree.
|
2021-06-28 09:45:56 -07:00
|
|
|
fn num_blinding_gates(&self, degree_estimate: usize) -> (usize, usize) {
|
2021-06-24 22:02:20 -07:00
|
|
|
let fri_queries = self.config.fri_config.num_query_rounds;
|
2021-06-28 17:07:27 -07:00
|
|
|
let arities: Vec<usize> = self
|
|
|
|
|
.config
|
|
|
|
|
.fri_config
|
|
|
|
|
.reduction_arity_bits
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|x| 1 << x)
|
|
|
|
|
.collect();
|
|
|
|
|
let total_fri_folding_points: usize = arities.iter().map(|x| x - 1).sum::<usize>();
|
2021-06-29 11:04:05 -07:00
|
|
|
let final_poly_coeffs: usize = degree_estimate / arities.iter().product::<usize>();
|
2021-06-28 23:08:24 -07:00
|
|
|
let fri_openings = fri_queries * (1 + D * total_fri_folding_points + D * final_poly_coeffs);
|
2021-06-24 22:02:20 -07:00
|
|
|
|
2021-07-18 23:24:33 -07:00
|
|
|
// We add D for openings at zeta.
|
2021-06-24 22:02:20 -07:00
|
|
|
let regular_poly_openings = D + fri_openings;
|
2021-07-18 23:24:33 -07:00
|
|
|
// We add 2 * D for openings at zeta and g * zeta.
|
2021-06-24 22:02:20 -07:00
|
|
|
let z_openings = 2 * D + fri_openings;
|
|
|
|
|
|
2021-06-28 09:45:56 -07:00
|
|
|
(regular_poly_openings, z_openings)
|
2021-06-24 22:02:20 -07:00
|
|
|
}
|
|
|
|
|
|
2021-06-28 23:08:24 -07:00
|
|
|
/// The number of polynomial values that will be revealed per opening, both for the "regular"
|
|
|
|
|
/// polynomials (which are opened at only one location) and for the Z polynomials (which are
|
|
|
|
|
/// opened at two).
|
2021-06-28 09:45:56 -07:00
|
|
|
fn blinding_counts(&self) -> (usize, usize) {
|
2021-06-30 12:54:45 -07:00
|
|
|
let num_gates = self.gate_instances.len();
|
2021-06-24 22:02:20 -07:00
|
|
|
let mut degree_estimate = 1 << log2_ceil(num_gates);
|
|
|
|
|
|
|
|
|
|
loop {
|
2021-06-28 09:45:56 -07:00
|
|
|
let (regular_poly_openings, z_openings) = self.num_blinding_gates(degree_estimate);
|
2021-06-24 22:02:20 -07:00
|
|
|
|
2021-06-28 09:45:56 -07:00
|
|
|
// For most polynomials, we add one random element to offset each opened value.
|
|
|
|
|
// But blinding Z is separate. For that, we add two random elements with a copy
|
|
|
|
|
// constraint between them.
|
|
|
|
|
let total_blinding_count = regular_poly_openings + 2 * z_openings;
|
|
|
|
|
|
|
|
|
|
if num_gates + total_blinding_count <= degree_estimate {
|
|
|
|
|
return (regular_poly_openings, z_openings);
|
2021-06-24 22:02:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The blinding gates do not fit within our estimated degree; increase our estimate.
|
|
|
|
|
degree_estimate *= 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-15 10:13:13 +02:00
|
|
|
fn blind_and_pad(&mut self) {
|
2021-07-18 23:24:33 -07:00
|
|
|
if self.config.zero_knowledge {
|
|
|
|
|
self.blind();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while !self.gate_instances.len().is_power_of_two() {
|
2021-07-22 23:48:03 -07:00
|
|
|
self.add_gate(NoopGate, vec![]);
|
2021-07-18 23:24:33 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn blind(&mut self) {
|
2021-06-28 09:45:56 -07:00
|
|
|
let (regular_poly_openings, z_openings) = self.blinding_counts();
|
2021-07-01 10:53:42 -07:00
|
|
|
info!(
|
|
|
|
|
"Adding {} blinding terms for witness polynomials, and {}*2 for Z polynomials",
|
|
|
|
|
regular_poly_openings, z_openings
|
|
|
|
|
);
|
2021-06-28 09:45:56 -07:00
|
|
|
|
|
|
|
|
let num_routed_wires = self.config.num_routed_wires;
|
|
|
|
|
let num_wires = self.config.num_wires;
|
2021-06-24 22:02:20 -07:00
|
|
|
|
2021-06-28 23:08:24 -07:00
|
|
|
// For each "regular" blinding factor, we simply add a no-op gate, and insert a random value
|
|
|
|
|
// for each wire.
|
2021-06-28 17:07:09 -07:00
|
|
|
for _ in 0..regular_poly_openings {
|
2021-07-22 23:48:03 -07:00
|
|
|
let gate = self.add_gate(NoopGate, vec![]);
|
2021-06-28 09:45:56 -07:00
|
|
|
for w in 0..num_wires {
|
2021-09-02 15:03:03 -07:00
|
|
|
self.add_simple_generator(RandomValueGenerator {
|
2021-06-28 09:45:56 -07:00
|
|
|
target: Target::Wire(Wire { gate, input: w }),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-28 23:08:24 -07:00
|
|
|
// For each z poly blinding factor, we add two new gates with the same random value, and
|
|
|
|
|
// enforce a copy constraint between them.
|
|
|
|
|
// See https://mirprotocol.org/blog/Adding-zero-knowledge-to-Plonk-Halo
|
2021-06-28 17:07:09 -07:00
|
|
|
for _ in 0..z_openings {
|
2021-07-22 23:48:03 -07:00
|
|
|
let gate_1 = self.add_gate(NoopGate, vec![]);
|
|
|
|
|
let gate_2 = self.add_gate(NoopGate, vec![]);
|
2021-06-28 09:45:56 -07:00
|
|
|
|
2021-06-28 17:07:09 -07:00
|
|
|
for w in 0..num_routed_wires {
|
2021-09-02 15:03:03 -07:00
|
|
|
self.add_simple_generator(RandomValueGenerator {
|
2021-06-28 17:07:27 -07:00
|
|
|
target: Target::Wire(Wire {
|
|
|
|
|
gate: gate_1,
|
|
|
|
|
input: w,
|
|
|
|
|
}),
|
2021-06-28 09:45:56 -07:00
|
|
|
});
|
2021-06-30 16:58:06 -07:00
|
|
|
self.generate_copy(
|
|
|
|
|
Target::Wire(Wire {
|
2021-06-28 17:07:27 -07:00
|
|
|
gate: gate_1,
|
|
|
|
|
input: w,
|
|
|
|
|
}),
|
2021-06-30 16:58:06 -07:00
|
|
|
Target::Wire(Wire {
|
2021-06-28 17:07:27 -07:00
|
|
|
gate: gate_2,
|
|
|
|
|
input: w,
|
|
|
|
|
}),
|
2021-06-30 16:58:06 -07:00
|
|
|
);
|
2021-06-28 09:45:56 -07:00
|
|
|
}
|
|
|
|
|
}
|
2021-03-25 15:20:14 -07:00
|
|
|
}
|
|
|
|
|
|
2021-07-15 10:13:13 +02:00
|
|
|
fn constant_polys(
|
2021-06-28 11:27:43 +02:00
|
|
|
&self,
|
|
|
|
|
gates: &[PrefixedGate<F, D>],
|
|
|
|
|
num_constants: usize,
|
|
|
|
|
) -> Vec<PolynomialValues<F>> {
|
2021-04-22 16:32:57 -07:00
|
|
|
let constants_per_gate = self
|
|
|
|
|
.gate_instances
|
|
|
|
|
.iter()
|
2021-06-24 18:06:48 +02:00
|
|
|
.map(|gate| {
|
|
|
|
|
let prefix = &gates
|
|
|
|
|
.iter()
|
2021-07-22 23:48:03 -07:00
|
|
|
.find(|g| g.gate.0.id() == gate.gate_ref.0.id())
|
2021-06-24 18:06:48 +02:00
|
|
|
.unwrap()
|
|
|
|
|
.prefix;
|
2021-06-24 20:53:15 +02:00
|
|
|
let mut prefixed_constants = Vec::with_capacity(num_constants);
|
2021-06-24 18:06:48 +02:00
|
|
|
prefixed_constants.extend(prefix.iter().map(|&b| if b { F::ONE } else { F::ZERO }));
|
|
|
|
|
prefixed_constants.extend_from_slice(&gate.constants);
|
2021-06-22 16:54:20 +02:00
|
|
|
prefixed_constants.resize(num_constants, F::ZERO);
|
|
|
|
|
prefixed_constants
|
2021-03-25 15:20:14 -07:00
|
|
|
})
|
|
|
|
|
.collect::<Vec<_>>();
|
2021-03-30 13:30:31 -07:00
|
|
|
|
2021-03-25 15:20:14 -07:00
|
|
|
transpose(&constants_per_gate)
|
2021-03-30 13:30:31 -07:00
|
|
|
.into_iter()
|
|
|
|
|
.map(PolynomialValues::new)
|
|
|
|
|
.collect()
|
2021-03-25 15:20:14 -07:00
|
|
|
}
|
|
|
|
|
|
2021-08-19 14:54:11 +02:00
|
|
|
fn sigma_vecs(
|
|
|
|
|
&self,
|
|
|
|
|
k_is: &[F],
|
|
|
|
|
subgroup: &[F],
|
2021-08-20 10:44:19 +02:00
|
|
|
) -> (Vec<PolynomialValues<F>>, PartitionWitness<F>) {
|
2021-04-25 17:02:02 -07:00
|
|
|
let degree = self.gate_instances.len();
|
|
|
|
|
let degree_log = log2_strict(degree);
|
2021-08-22 10:36:44 +02:00
|
|
|
let mut partition_witness = PartitionWitness::new(
|
|
|
|
|
self.config.num_wires,
|
|
|
|
|
self.config.num_routed_wires,
|
|
|
|
|
degree,
|
|
|
|
|
self.virtual_target_index,
|
|
|
|
|
);
|
2021-04-25 17:02:02 -07:00
|
|
|
|
|
|
|
|
for gate in 0..degree {
|
2021-08-20 10:44:19 +02:00
|
|
|
for input in 0..self.config.num_wires {
|
2021-08-20 13:06:07 +02:00
|
|
|
partition_witness.add(Target::Wire(Wire { gate, input }));
|
2021-04-25 17:02:02 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-01 08:12:12 -07:00
|
|
|
for index in 0..self.virtual_target_index {
|
2021-08-20 13:06:07 +02:00
|
|
|
partition_witness.add(Target::VirtualTarget { index });
|
2021-04-25 17:02:02 -07:00
|
|
|
}
|
|
|
|
|
|
2021-07-14 20:54:30 +02:00
|
|
|
for &CopyConstraint { pair: (a, b), .. } in &self.copy_constraints {
|
2021-08-20 13:06:07 +02:00
|
|
|
partition_witness.merge(a, b);
|
2021-04-25 17:02:02 -07:00
|
|
|
}
|
|
|
|
|
|
2021-08-20 13:06:07 +02:00
|
|
|
let wire_partition = partition_witness.wire_partition();
|
2021-08-19 14:54:11 +02:00
|
|
|
(
|
|
|
|
|
wire_partition.get_sigma_polys(degree_log, k_is, subgroup),
|
2021-08-20 13:06:07 +02:00
|
|
|
partition_witness,
|
2021-08-19 14:54:11 +02:00
|
|
|
)
|
2021-03-25 15:20:14 -07:00
|
|
|
}
|
|
|
|
|
|
2021-08-17 09:12:40 +02:00
|
|
|
/// Fill the remaining unused arithmetic operations with zeros, so that all
|
|
|
|
|
/// `ArithmeticExtensionGenerator` are run.
|
|
|
|
|
fn fill_arithmetic_gates(&mut self) {
|
|
|
|
|
let zero = self.zero_extension();
|
|
|
|
|
let remaining_arithmetic_gates = self.free_arithmetic.values().copied().collect::<Vec<_>>();
|
|
|
|
|
for (gate, i) in remaining_arithmetic_gates {
|
|
|
|
|
for j in i..NUM_ARITHMETIC_OPS {
|
|
|
|
|
let wires_multiplicand_0 = ExtensionTarget::from_range(
|
|
|
|
|
gate,
|
|
|
|
|
ArithmeticExtensionGate::<D>::wires_ith_multiplicand_0(j),
|
|
|
|
|
);
|
|
|
|
|
let wires_multiplicand_1 = ExtensionTarget::from_range(
|
|
|
|
|
gate,
|
|
|
|
|
ArithmeticExtensionGate::<D>::wires_ith_multiplicand_1(j),
|
|
|
|
|
);
|
|
|
|
|
let wires_addend = ExtensionTarget::from_range(
|
|
|
|
|
gate,
|
|
|
|
|
ArithmeticExtensionGate::<D>::wires_ith_addend(j),
|
|
|
|
|
);
|
|
|
|
|
|
2021-08-24 08:25:11 +02:00
|
|
|
self.connect_extension(zero, wires_multiplicand_0);
|
|
|
|
|
self.connect_extension(zero, wires_multiplicand_1);
|
|
|
|
|
self.connect_extension(zero, wires_addend);
|
2021-08-17 09:12:40 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-01 16:38:10 -07:00
|
|
|
/// Fill the remaining unused switch gates with dummy values, so that all
|
|
|
|
|
/// `SwitchGenerator` are run.
|
|
|
|
|
fn fill_switch_gates(&mut self) {
|
|
|
|
|
let zero = self.zero();
|
|
|
|
|
|
|
|
|
|
for chunk_size in 1..=self.current_switch_gates.len() {
|
2021-09-02 15:59:17 -07:00
|
|
|
if let Some((gate, gate_index, mut copy)) =
|
2021-09-01 16:38:10 -07:00
|
|
|
self.current_switch_gates[chunk_size - 1].clone()
|
|
|
|
|
{
|
2021-09-02 15:59:17 -07:00
|
|
|
while copy < gate.num_copies {
|
|
|
|
|
for element in 0..chunk_size {
|
|
|
|
|
let wire_first_input =
|
|
|
|
|
Target::wire(gate_index, gate.wire_first_input(copy, element));
|
|
|
|
|
let wire_second_input =
|
|
|
|
|
Target::wire(gate_index, gate.wire_second_input(copy, element));
|
|
|
|
|
let wire_switch_bool =
|
|
|
|
|
Target::wire(gate_index, gate.wire_switch_bool(copy));
|
|
|
|
|
self.connect(zero, wire_first_input);
|
|
|
|
|
self.connect(zero, wire_second_input);
|
|
|
|
|
self.connect(zero, wire_switch_bool);
|
|
|
|
|
}
|
|
|
|
|
copy += 1;
|
2021-09-01 16:38:10 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-19 12:22:18 -07:00
|
|
|
pub fn print_gate_counts(&self, min_delta: usize) {
|
|
|
|
|
self.context_log
|
|
|
|
|
.filter(self.num_gates(), min_delta)
|
|
|
|
|
.print(self.num_gates());
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-21 11:17:00 -07:00
|
|
|
/// Builds a "full circuit", with both prover and verifier data.
|
2021-05-30 13:25:53 -07:00
|
|
|
pub fn build(mut self) -> CircuitData<F, D> {
|
2021-08-02 10:38:09 -07:00
|
|
|
let mut timing = TimingTree::new("preprocess", Level::Trace);
|
2021-03-25 15:20:14 -07:00
|
|
|
let start = Instant::now();
|
2021-07-21 08:26:19 -07:00
|
|
|
|
2021-08-17 09:12:40 +02:00
|
|
|
self.fill_arithmetic_gates();
|
2021-09-02 15:59:17 -07:00
|
|
|
self.fill_switch_gates();
|
2021-08-17 09:12:40 +02:00
|
|
|
|
2021-07-21 08:26:19 -07:00
|
|
|
// 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);
|
2021-07-22 23:48:03 -07:00
|
|
|
let pi_gate = self.add_gate(PublicInputGate, vec![]);
|
2021-07-21 08:26:19 -07:00
|
|
|
for (&hash_part, wire) in public_inputs_hash
|
|
|
|
|
.elements
|
|
|
|
|
.iter()
|
|
|
|
|
.zip(PublicInputGate::wires_public_inputs_hash())
|
|
|
|
|
{
|
2021-08-24 08:25:11 +02:00
|
|
|
self.connect(hash_part, Target::wire(pi_gate, wire))
|
2021-07-21 08:26:19 -07:00
|
|
|
}
|
|
|
|
|
|
2021-04-22 16:32:57 -07:00
|
|
|
info!(
|
2021-07-01 10:53:42 -07:00
|
|
|
"Degree before blinding & padding: {}",
|
2021-04-22 16:32:57 -07:00
|
|
|
self.gate_instances.len()
|
|
|
|
|
);
|
2021-03-25 15:20:14 -07:00
|
|
|
self.blind_and_pad();
|
|
|
|
|
let degree = self.gate_instances.len();
|
2021-07-01 10:53:42 -07:00
|
|
|
info!("Degree after blinding & padding: {}", degree);
|
2021-07-19 16:24:21 +02:00
|
|
|
let degree_bits = log2_strict(degree);
|
|
|
|
|
assert!(
|
|
|
|
|
self.config
|
|
|
|
|
.fri_config
|
|
|
|
|
.reduction_arity_bits
|
|
|
|
|
.iter()
|
|
|
|
|
.sum::<usize>()
|
|
|
|
|
<= degree_bits,
|
|
|
|
|
"FRI total reduction arity is too large."
|
|
|
|
|
);
|
2021-03-25 15:20:14 -07:00
|
|
|
|
2021-06-22 16:54:20 +02:00
|
|
|
let gates = self.gates.iter().cloned().collect();
|
2021-06-28 11:27:43 +02:00
|
|
|
let (gate_tree, max_filtered_constraint_degree, num_constants) = Tree::from_gates(gates);
|
2021-08-09 19:08:52 +02:00
|
|
|
// `quotient_degree_factor` has to be between `max_filtered_constraint_degree-1` and `1<<rate_bits`.
|
|
|
|
|
// We find the value that minimizes `num_partial_product + quotient_degree_factor`.
|
|
|
|
|
let quotient_degree_factor = (max_filtered_constraint_degree - 1
|
|
|
|
|
..=1 << self.config.rate_bits)
|
|
|
|
|
.min_by_key(|&q| num_partial_products(self.config.num_routed_wires, q).0 + q)
|
|
|
|
|
.unwrap();
|
|
|
|
|
info!("Quotient degree factor set to: {}.", quotient_degree_factor);
|
2021-06-24 18:06:48 +02:00
|
|
|
let prefixed_gates = PrefixedGate::from_tree(gate_tree);
|
2021-06-22 16:54:20 +02:00
|
|
|
|
2021-06-16 17:43:41 +02:00
|
|
|
let subgroup = F::two_adic_subgroup(degree_bits);
|
|
|
|
|
|
2021-06-28 11:27:43 +02:00
|
|
|
let constant_vecs = self.constant_polys(&prefixed_gates, num_constants);
|
2021-03-25 15:20:14 -07:00
|
|
|
|
2021-04-25 17:02:02 -07:00
|
|
|
let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires);
|
2021-08-20 13:06:07 +02:00
|
|
|
let (sigma_vecs, partition_witness) = self.sigma_vecs(&k_is, &subgroup);
|
2021-04-23 14:18:03 -07:00
|
|
|
|
2021-06-28 08:56:36 -07:00
|
|
|
let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat();
|
2021-08-09 10:11:35 -07:00
|
|
|
let constants_sigmas_commitment = PolynomialBatchCommitment::from_values(
|
2021-06-25 11:24:26 +02:00
|
|
|
constants_sigmas_vecs,
|
2021-07-18 23:24:33 -07:00
|
|
|
self.config.rate_bits,
|
|
|
|
|
self.config.zero_knowledge & PlonkPolynomials::CONSTANTS_SIGMAS.blinding,
|
2021-08-10 13:33:44 +02:00
|
|
|
self.config.cap_height,
|
2021-08-02 10:38:09 -07:00
|
|
|
&mut timing,
|
2021-05-07 11:30:03 +02:00
|
|
|
);
|
2021-04-23 14:18:03 -07:00
|
|
|
|
2021-08-10 15:53:27 +02:00
|
|
|
let constants_sigmas_cap = constants_sigmas_commitment.merkle_tree.cap.clone();
|
2021-04-23 14:18:03 -07:00
|
|
|
let verifier_only = VerifierOnlyCircuitData {
|
2021-08-10 15:53:27 +02:00
|
|
|
constants_sigmas_cap: constants_sigmas_cap.clone(),
|
2021-04-23 14:18:03 -07:00
|
|
|
};
|
2021-03-25 15:20:14 -07:00
|
|
|
|
2021-04-22 16:32:57 -07:00
|
|
|
let prover_only = ProverOnlyCircuitData {
|
2021-06-23 14:16:05 +02:00
|
|
|
generators: self.generators,
|
2021-06-25 11:24:26 +02:00
|
|
|
constants_sigmas_commitment,
|
2021-06-28 08:56:36 -07:00
|
|
|
sigmas: transpose_poly_values(sigma_vecs),
|
2021-06-16 17:43:41 +02:00
|
|
|
subgroup,
|
2021-07-21 08:26:19 -07:00
|
|
|
public_inputs: self.public_inputs,
|
2021-07-14 20:54:30 +02:00
|
|
|
marked_targets: self.marked_targets,
|
2021-08-20 13:06:07 +02:00
|
|
|
partition_witness,
|
2021-04-22 16:32:57 -07:00
|
|
|
};
|
2021-03-25 15:20:14 -07:00
|
|
|
|
2021-03-28 15:36:51 -07:00
|
|
|
// The HashSet of gates will have a non-deterministic order. When converting to a Vec, we
|
|
|
|
|
// sort by ID to make the ordering deterministic.
|
|
|
|
|
let mut gates = self.gates.iter().cloned().collect::<Vec<_>>();
|
|
|
|
|
gates.sort_unstable_by_key(|gate| gate.0.id());
|
|
|
|
|
|
2021-04-22 16:32:57 -07:00
|
|
|
let num_gate_constraints = gates
|
|
|
|
|
.iter()
|
2021-03-28 15:36:51 -07:00
|
|
|
.map(|gate| gate.0.num_constraints())
|
|
|
|
|
.max()
|
|
|
|
|
.expect("No gates?");
|
|
|
|
|
|
2021-07-08 15:13:29 +02:00
|
|
|
let num_partial_products =
|
2021-07-08 15:16:05 +02:00
|
|
|
num_partial_products(self.config.num_routed_wires, quotient_degree_factor);
|
2021-07-01 15:41:01 +02:00
|
|
|
|
2021-04-22 16:32:57 -07:00
|
|
|
// TODO: This should also include an encoding of gate constraints.
|
2021-06-25 11:49:29 +02:00
|
|
|
let circuit_digest_parts = [
|
2021-08-14 08:47:03 -07:00
|
|
|
constants_sigmas_cap.flatten(),
|
2021-06-25 11:49:29 +02:00
|
|
|
vec![/* Add other circuit data here */],
|
|
|
|
|
];
|
2021-04-22 16:32:57 -07:00
|
|
|
let circuit_digest = hash_n_to_hash(circuit_digest_parts.concat(), false);
|
|
|
|
|
|
2021-03-25 15:20:14 -07:00
|
|
|
let common = CommonCircuitData {
|
|
|
|
|
config: self.config,
|
2021-04-04 11:35:58 -07:00
|
|
|
degree_bits,
|
2021-06-24 18:06:48 +02:00
|
|
|
gates: prefixed_gates,
|
2021-07-08 15:16:05 +02:00
|
|
|
quotient_degree_factor,
|
2021-03-28 15:36:51 -07:00
|
|
|
num_gate_constraints,
|
2021-06-25 11:24:26 +02:00
|
|
|
num_constants,
|
2021-03-30 23:12:47 -07:00
|
|
|
k_is,
|
2021-07-01 15:41:01 +02:00
|
|
|
num_partial_products,
|
2021-04-22 16:32:57 -07:00
|
|
|
circuit_digest,
|
2021-03-25 15:20:14 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
info!("Building circuit took {}s", start.elapsed().as_secs_f32());
|
|
|
|
|
CircuitData {
|
|
|
|
|
prover_only,
|
|
|
|
|
verifier_only,
|
|
|
|
|
common,
|
|
|
|
|
}
|
2021-03-21 11:17:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Builds a "prover circuit", with data needed to generate proofs but not verify them.
|
2021-05-30 13:25:53 -07:00
|
|
|
pub fn build_prover(self) -> ProverCircuitData<F, D> {
|
2021-03-25 15:20:14 -07:00
|
|
|
// TODO: Can skip parts of this.
|
2021-04-22 16:32:57 -07:00
|
|
|
let CircuitData {
|
|
|
|
|
prover_only,
|
|
|
|
|
common,
|
|
|
|
|
..
|
|
|
|
|
} = self.build();
|
|
|
|
|
ProverCircuitData {
|
|
|
|
|
prover_only,
|
|
|
|
|
common,
|
|
|
|
|
}
|
2021-03-21 11:17:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Builds a "verifier circuit", with data needed to verify proofs but not generate them.
|
2021-05-30 13:25:53 -07:00
|
|
|
pub fn build_verifier(self) -> VerifierCircuitData<F, D> {
|
2021-03-25 15:20:14 -07:00
|
|
|
// TODO: Can skip parts of this.
|
2021-04-22 16:32:57 -07:00
|
|
|
let CircuitData {
|
|
|
|
|
verifier_only,
|
|
|
|
|
common,
|
|
|
|
|
..
|
|
|
|
|
} = self.build();
|
|
|
|
|
VerifierCircuitData {
|
|
|
|
|
verifier_only,
|
|
|
|
|
common,
|
|
|
|
|
}
|
2021-03-21 11:17:00 -07:00
|
|
|
}
|
2021-02-26 13:18:41 -08:00
|
|
|
}
|