2021-02-26 13:18:41 -08:00
|
|
|
use std::collections::HashSet;
|
2021-03-25 15:20:14 -07:00
|
|
|
use std::time::Instant;
|
2021-02-26 13:18:41 -08:00
|
|
|
|
2021-03-25 15:20:14 -07:00
|
|
|
use log::info;
|
|
|
|
|
|
|
|
|
|
use crate::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData, VerifierCircuitData, VerifierOnlyCircuitData};
|
2021-02-26 13:18:41 -08:00
|
|
|
use crate::field::field::Field;
|
2021-03-28 15:36:51 -07:00
|
|
|
use crate::gates::constant::ConstantGate;
|
2021-03-30 13:30:31 -07:00
|
|
|
use crate::gates::gate::{GateInstance, GateRef};
|
2021-03-28 15:36:51 -07:00
|
|
|
use crate::gates::noop::NoopGate;
|
2021-03-01 13:40:05 -08:00
|
|
|
use crate::generator::{CopyGenerator, WitnessGenerator};
|
2021-03-25 15:20:14 -07:00
|
|
|
use crate::hash::merkle_root_bit_rev_order;
|
2021-03-30 13:30:31 -07:00
|
|
|
use crate::polynomial::polynomial::PolynomialValues;
|
2021-02-26 13:18:41 -08:00
|
|
|
use crate::target::Target;
|
2021-03-30 13:30:31 -07:00
|
|
|
use crate::util::{log2_strict, transpose, transpose_poly_values};
|
2021-02-26 13:18:41 -08:00
|
|
|
use crate::wire::Wire;
|
2021-03-30 23:12:47 -07:00
|
|
|
use crate::partition::get_subgroup_shift;
|
2021-02-26 13:18:41 -08:00
|
|
|
|
2021-03-25 15:20:14 -07:00
|
|
|
pub struct CircuitBuilder<F: Field> {
|
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-02-26 13:18:41 -08:00
|
|
|
gates: HashSet<GateRef<F>>,
|
2021-03-21 11:57:33 -07:00
|
|
|
|
2021-02-26 13:18:41 -08:00
|
|
|
gate_instances: Vec<GateInstance<F>>,
|
2021-03-21 11:57:33 -07:00
|
|
|
|
2021-03-01 13:40:05 -08:00
|
|
|
generators: Vec<Box<dyn WitnessGenerator<F>>>,
|
2021-02-26 13:18:41 -08:00
|
|
|
}
|
|
|
|
|
|
2021-03-25 15:20:14 -07:00
|
|
|
impl<F: Field> CircuitBuilder<F> {
|
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(),
|
|
|
|
|
generators: Vec::new(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-25 15:20:14 -07:00
|
|
|
pub fn add_gate_no_constants(&mut self, gate_type: GateRef<F>) -> usize {
|
|
|
|
|
self.add_gate(gate_type, Vec::new())
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-26 13:18:41 -08:00
|
|
|
/// Adds a gate to the circuit, and returns its index.
|
|
|
|
|
pub fn add_gate(&mut self, gate_type: GateRef<F>, constants: Vec<F>) -> usize {
|
|
|
|
|
// If we haven't seen a gate of this type before, check that it's compatible with our
|
|
|
|
|
// circuit configuration, then register it.
|
|
|
|
|
if !self.gates.contains(&gate_type) {
|
|
|
|
|
self.check_gate_compatibility(&gate_type);
|
|
|
|
|
self.gates.insert(gate_type.clone());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let index = self.gate_instances.len();
|
|
|
|
|
self.gate_instances.push(GateInstance { gate_type, constants });
|
|
|
|
|
index
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn check_gate_compatibility(&self, gate: &GateRef<F>) {
|
2021-03-28 15:36:51 -07:00
|
|
|
assert!(gate.0.num_wires() <= self.config.num_wires);
|
2021-02-26 13:18:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Shorthand for `generate_copy` and `assert_equal`.
|
|
|
|
|
/// Both elements must be routable, otherwise this method will panic.
|
|
|
|
|
pub fn route(&mut self, src: Target, dst: Target) {
|
|
|
|
|
self.generate_copy(src, dst);
|
|
|
|
|
self.assert_equal(src, dst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Adds a generator which will copy `src` to `dst`.
|
|
|
|
|
pub fn generate_copy(&mut self, src: Target, dst: Target) {
|
|
|
|
|
self.add_generator(CopyGenerator { src, dst });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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));
|
|
|
|
|
assert!(y.is_routable(self.config));
|
2021-03-30 10:02:00 -07:00
|
|
|
// TODO: Add to copy_constraints.
|
2021-02-26 13:18:41 -08:00
|
|
|
}
|
|
|
|
|
|
2021-03-01 13:40:05 -08:00
|
|
|
pub fn add_generator<G: WitnessGenerator<F>>(&mut self, generator: G) {
|
2021-02-26 13:18:41 -08:00
|
|
|
self.generators.push(Box::new(generator));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns a routable target with a value of `ORDER - 1`.
|
|
|
|
|
pub fn neg_one(&mut self) -> Target {
|
|
|
|
|
self.constant(F::NEG_ONE)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns a routable target with the given constant value.
|
|
|
|
|
pub fn constant(&mut self, c: F) -> Target {
|
2021-03-28 15:36:51 -07:00
|
|
|
let gate = self.add_gate(ConstantGate::get(), vec![c]);
|
|
|
|
|
Target::Wire(Wire { gate, input: ConstantGate::WIRE_OUTPUT })
|
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-03-31 21:15:24 -07:00
|
|
|
pub fn permute(&mut self, inputs: [Target; 12]) -> [Target; 12] {
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-25 15:20:14 -07:00
|
|
|
fn blind_and_pad(&mut self) {
|
|
|
|
|
// TODO: Blind.
|
|
|
|
|
|
|
|
|
|
while !self.gate_instances.len().is_power_of_two() {
|
|
|
|
|
self.add_gate_no_constants(NoopGate::get());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_generators(&self) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
|
|
|
|
self.gate_instances.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.flat_map(|(gate_index, gate_inst)| gate_inst.gate_type.0.generators(
|
|
|
|
|
gate_index,
|
2021-03-28 15:36:51 -07:00
|
|
|
&gate_inst.constants,
|
|
|
|
|
&[])) // TODO: Not supporting next_const for now.
|
2021-03-25 15:20:14 -07:00
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 13:30:31 -07:00
|
|
|
fn constant_polys(&self) -> Vec<PolynomialValues<F>> {
|
2021-03-25 15:20:14 -07:00
|
|
|
let num_constants = self.gate_instances.iter()
|
|
|
|
|
.map(|gate_inst| gate_inst.constants.len())
|
|
|
|
|
.max()
|
|
|
|
|
.unwrap();
|
|
|
|
|
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 {
|
|
|
|
|
padded_constants.push(F::ZERO);
|
|
|
|
|
}
|
|
|
|
|
padded_constants
|
|
|
|
|
})
|
|
|
|
|
.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-03-30 13:30:31 -07:00
|
|
|
fn sigma_vecs(&self) -> Vec<PolynomialValues<F>> {
|
2021-03-30 23:12:47 -07:00
|
|
|
vec![PolynomialValues::zero(self.gate_instances.len()); self.config.num_routed_wires] // TODO
|
2021-03-25 15:20:14 -07:00
|
|
|
}
|
|
|
|
|
|
2021-03-21 11:17:00 -07:00
|
|
|
/// Builds a "full circuit", with both prover and verifier data.
|
2021-03-25 15:20:14 -07:00
|
|
|
pub fn build(mut self) -> CircuitData<F> {
|
|
|
|
|
let start = Instant::now();
|
|
|
|
|
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);
|
|
|
|
|
|
2021-03-30 13:30:31 -07:00
|
|
|
let constant_vecs = self.constant_polys();
|
|
|
|
|
let constant_ldes = PolynomialValues::lde_multiple(constant_vecs, self.config.rate_bits);
|
|
|
|
|
let constant_ldes_t = transpose_poly_values(constant_ldes);
|
2021-03-28 15:36:51 -07:00
|
|
|
let constants_root = merkle_root_bit_rev_order(constant_ldes_t.clone());
|
2021-03-25 15:20:14 -07:00
|
|
|
|
|
|
|
|
let sigma_vecs = self.sigma_vecs();
|
2021-03-30 13:30:31 -07:00
|
|
|
let sigma_ldes = PolynomialValues::lde_multiple(sigma_vecs, self.config.rate_bits);
|
2021-03-30 23:12:47 -07:00
|
|
|
let sigma_ldes_t = transpose_poly_values(sigma_ldes);
|
|
|
|
|
let sigmas_root = merkle_root_bit_rev_order(sigma_ldes_t.clone());
|
2021-03-25 15:20:14 -07:00
|
|
|
|
|
|
|
|
let generators = self.get_generators();
|
2021-03-30 23:12:47 -07:00
|
|
|
let prover_only = ProverOnlyCircuitData { generators, constant_ldes_t, sigma_ldes_t };
|
2021-03-25 15:20:14 -07:00
|
|
|
let verifier_only = VerifierOnlyCircuitData {};
|
|
|
|
|
|
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());
|
|
|
|
|
|
|
|
|
|
let num_gate_constraints = gates.iter()
|
|
|
|
|
.map(|gate| gate.0.num_constraints())
|
|
|
|
|
.max()
|
|
|
|
|
.expect("No gates?");
|
|
|
|
|
|
2021-03-30 23:12:47 -07:00
|
|
|
let k_is = (0..self.config.num_routed_wires)
|
|
|
|
|
.map(get_subgroup_shift)
|
|
|
|
|
.collect();
|
|
|
|
|
|
2021-03-25 15:20:14 -07:00
|
|
|
let common = CommonCircuitData {
|
|
|
|
|
config: self.config,
|
2021-03-28 15:36:51 -07:00
|
|
|
degree_bits: log2_strict(degree),
|
|
|
|
|
gates,
|
|
|
|
|
num_gate_constraints,
|
2021-03-25 15:20:14 -07:00
|
|
|
constants_root,
|
|
|
|
|
sigmas_root,
|
2021-03-30 23:12:47 -07:00
|
|
|
k_is,
|
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-03-25 15:20:14 -07:00
|
|
|
pub fn build_prover(mut self) -> ProverCircuitData<F> {
|
|
|
|
|
// TODO: Can skip parts of this.
|
2021-03-30 20:16:20 -07:00
|
|
|
let CircuitData { prover_only, common, .. } = self.build();
|
2021-03-25 15:20:14 -07:00
|
|
|
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-03-25 15:20:14 -07:00
|
|
|
pub fn build_verifier(mut self) -> VerifierCircuitData<F> {
|
|
|
|
|
// TODO: Can skip parts of this.
|
2021-03-30 20:16:20 -07:00
|
|
|
let CircuitData { verifier_only, common, .. } = self.build();
|
2021-03-25 15:20:14 -07:00
|
|
|
VerifierCircuitData { verifier_only, common }
|
2021-03-21 11:17:00 -07:00
|
|
|
}
|
2021-02-26 13:18:41 -08:00
|
|
|
}
|