Skip to content

Commit 0092a15

Browse files
committed
Cost model update
1 parent 961e7d2 commit 0092a15

File tree

2 files changed

+92
-34
lines changed

2 files changed

+92
-34
lines changed

examples/proof-size.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ fn main() {
8989
let circuit = TestCircuit {};
9090

9191
let model = from_circuit_to_model_circuit::<_, _, 56, 56>(
92-
K,
92+
Some(K),
9393
&circuit,
9494
vec![],
9595
CommitmentScheme::KZGGWC,

src/dev/cost_model.rs

Lines changed: 91 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
//! verification cost, as well as resulting proof size.
33
44
use std::collections::HashSet;
5-
use std::{iter, num::ParseIntError, str::FromStr};
5+
use std::panic::AssertUnwindSafe;
6+
use std::{iter, num::ParseIntError, panic, str::FromStr};
67

78
use crate::plonk::Circuit;
89
use ff::{Field, FromUniformBytes};
910
use serde::Deserialize;
1011
use serde_derive::Serialize;
12+
use crate::plonk::Any::Fixed;
1113

1214
use super::MockProver;
1315

@@ -46,11 +48,21 @@ pub struct CostOptions {
4648
/// A permutation over N columns. May be repeated.
4749
pub permutation: Permutation,
4850

49-
/// A shuffle over N columns with max input degree I and max shuffle degree T. May be repeated.
50-
pub shuffle: Vec<Shuffle>,
51+
/// 2^K bound on the number of rows, accounting for ZK, PIs and Lookup tables.
52+
pub min_k: usize,
5153

52-
/// 2^K bound on the number of rows.
53-
pub k: usize,
54+
/// Rows count, not including table rows and not accounting for compression
55+
/// (where multiple regions can use the same rows).
56+
pub rows_count: usize,
57+
58+
/// Table rows count, not accounting for compression (where multiple regions
59+
/// can use the same rows), but not much if any compression can happen with
60+
/// table rows anyway.
61+
pub table_rows_count: usize,
62+
63+
/// Compressed rows count, accounting for compression (where multiple
64+
/// regions can use the same rows).
65+
pub compressed_rows_count: usize,
5466
}
5567

5668
/// Structure holding polynomial related data for benchmarks
@@ -110,19 +122,6 @@ impl Permutation {
110122
}
111123
}
112124

113-
/// Structure holding the [Shuffle] related data for circuit benchmarks.
114-
#[derive(Debug, Clone)]
115-
pub struct Shuffle;
116-
117-
impl Shuffle {
118-
fn queries(&self) -> impl Iterator<Item = Poly> {
119-
// Open shuffle product commitment at x and \omega x
120-
let shuffle = "0, 1".parse().unwrap();
121-
122-
iter::empty().chain(Some(shuffle))
123-
}
124-
}
125-
126125
/// High-level specifications of an abstract circuit.
127126
#[derive(Debug, Deserialize, Serialize)]
128127
pub struct ModelCircuit {
@@ -136,8 +135,6 @@ pub struct ModelCircuit {
136135
pub lookups: usize,
137136
/// Equality constraint enabled columns.
138137
pub permutations: usize,
139-
/// Number of shuffle arguments
140-
pub shuffles: usize,
141138
/// Number of distinct column queries across all gates.
142139
pub column_queries: usize,
143140
/// Number of distinct sets of points in the multiopening argument.
@@ -160,7 +157,6 @@ impl CostOptions {
160157
.cloned()
161158
.chain(self.lookup.iter().flat_map(|l| l.queries()))
162159
.chain(self.permutation.queries())
163-
.chain(self.shuffle.iter().flat_map(|s| s.queries()))
164160
.chain(iter::repeat("0".parse().unwrap()).take(self.max_degree - 1))
165161
.collect();
166162

@@ -199,7 +195,7 @@ impl CostOptions {
199195
// - inner product argument (k rounds * 2 * COMM bytes)
200196
// - a (SCALAR bytes)
201197
// - xi (SCALAR bytes)
202-
comp_bytes(1 + 2 * self.k, 2)
198+
comp_bytes(1 + 2 * self.min_k, 2)
203199
}
204200
CommitmentScheme::KZGGWC => {
205201
let mut nr_rotations = HashSet::new();
@@ -227,12 +223,11 @@ impl CostOptions {
227223
let size = plonk + vanishing + multiopen + polycomm;
228224

229225
ModelCircuit {
230-
k: self.k,
226+
k: self.min_k,
231227
max_deg: self.max_degree,
232228
advice_columns: self.advice.len(),
233229
lookups: self.lookup.len(),
234230
permutations: self.permutation.columns,
235-
shuffles: self.shuffle.len(),
236231
column_queries,
237232
point_sets,
238233
size,
@@ -247,7 +242,7 @@ pub fn from_circuit_to_model_circuit<
247242
const COMM: usize,
248243
const SCALAR: usize,
249244
>(
250-
k: u32,
245+
k: Option<u32>,
251246
circuit: &C,
252247
instances: Vec<Vec<F>>,
253248
comm_scheme: CommitmentScheme,
@@ -256,13 +251,34 @@ pub fn from_circuit_to_model_circuit<
256251
options.into_model_circuit::<COMM, SCALAR>(comm_scheme)
257252
}
258253

259-
/// Given a Plonk circuit, this function returns [CostOptions]
254+
fn run_mock_prover_with_fallback<F: Ord + Field + FromUniformBytes<64>, C: Circuit<F>>(
255+
circuit: &C,
256+
instances: Vec<Vec<F>>,
257+
) -> MockProver<F> {
258+
(5..25)
259+
.find_map(|k| {
260+
panic::catch_unwind(AssertUnwindSafe(|| {
261+
MockProver::run(k, circuit, instances.clone()).unwrap()
262+
}))
263+
.ok()
264+
})
265+
.expect("A circuit which can be implemented with at most 2^24 rows.")
266+
}
267+
268+
/// Given a circuit, this function returns [CostOptions]. If no upper bound for `k` is
269+
/// provided, we iterate until a valid `k` is found (this might delay the computation).
260270
pub fn from_circuit_to_cost_model_options<F: Ord + Field + FromUniformBytes<64>, C: Circuit<F>>(
261-
k: u32,
271+
k_upper_bound: Option<u32>,
262272
circuit: &C,
263273
instances: Vec<Vec<F>>,
264274
) -> CostOptions {
265-
let prover = MockProver::run(k, circuit, instances).unwrap();
275+
let instance_len = instances.iter().map(Vec::len).max().unwrap_or(0);
276+
let prover = if let Some(k) = k_upper_bound {
277+
MockProver::run(k, circuit, instances).unwrap()
278+
} else {
279+
run_mock_prover_with_fallback(circuit, instances.clone())
280+
};
281+
266282
let cs = prover.cs;
267283

268284
let fixed = {
@@ -298,16 +314,56 @@ pub fn from_circuit_to_cost_model_options<F: Ord + Field + FromUniformBytes<64>,
298314
columns: cs.permutation().get_columns().len(),
299315
};
300316

301-
let shuffle = { cs.shuffles.iter().map(|_| Shuffle).collect::<Vec<_>>() };
302-
303317
let gate_degree = cs
304318
.gates
305319
.iter()
306320
.flat_map(|gate| gate.polynomials().iter().map(|poly| poly.degree()))
307321
.max()
308322
.unwrap_or(0);
309323

310-
let k = prover.k.try_into().unwrap();
324+
// Note that this computation does't assume that `regions` is already in
325+
// order of increasing row indices.
326+
let (rows_count, table_rows_count, compressed_rows_count) = {
327+
let mut rows_count = 0;
328+
let mut table_rows_count = 0;
329+
let mut compressed_rows_count = 0;
330+
for region in prover.regions {
331+
// If `region.rows == None`, then that region has no rows.
332+
if let Some((start, end)) = region.rows {
333+
// Note that `end` is the index of the last column, so when
334+
// counting rows this last column needs to be counted via `end +
335+
// 1`.
336+
337+
// A region is a _table region_ if all of its columns are `Fixed`
338+
// columns (see that [`plonk::circuit::TableColumn` is a wrapper
339+
// around `Column<Fixed>`]). All of a table region's rows are
340+
// counted towards `table_rows_count.`
341+
if region
342+
.columns
343+
.iter()
344+
.all(|c| *c.column_type() == Fixed)
345+
{
346+
table_rows_count += (end + 1) - start;
347+
} else {
348+
rows_count += (end + 1) - start;
349+
}
350+
compressed_rows_count = std::cmp::max(compressed_rows_count, end + 1);
351+
}
352+
}
353+
(rows_count, table_rows_count, compressed_rows_count)
354+
};
355+
356+
let min_k = [
357+
rows_count + cs.blinding_factors(),
358+
table_rows_count + cs.blinding_factors(),
359+
instance_len,
360+
]
361+
.into_iter()
362+
.max()
363+
.unwrap();
364+
if min_k == instance_len {
365+
println!("WARNING: The dominant factor in your circuit's size is the number of public inputs, which causes the verifier to perform linear work.");
366+
}
311367

312368
CostOptions {
313369
advice,
@@ -317,7 +373,9 @@ pub fn from_circuit_to_cost_model_options<F: Ord + Field + FromUniformBytes<64>,
317373
max_degree: cs.degree(),
318374
lookup,
319375
permutation,
320-
shuffle,
321-
k,
376+
min_k,
377+
rows_count,
378+
table_rows_count,
379+
compressed_rows_count,
322380
}
323381
}

0 commit comments

Comments
 (0)