2
2
//! verification cost, as well as resulting proof size.
3
3
4
4
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 } ;
6
7
7
8
use crate :: plonk:: Circuit ;
8
9
use ff:: { Field , FromUniformBytes } ;
9
10
use serde:: Deserialize ;
10
11
use serde_derive:: Serialize ;
12
+ use crate :: plonk:: Any :: Fixed ;
11
13
12
14
use super :: MockProver ;
13
15
@@ -46,11 +48,21 @@ pub struct CostOptions {
46
48
/// A permutation over N columns. May be repeated.
47
49
pub permutation : Permutation ,
48
50
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 ,
51
53
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 ,
54
66
}
55
67
56
68
/// Structure holding polynomial related data for benchmarks
@@ -110,19 +122,6 @@ impl Permutation {
110
122
}
111
123
}
112
124
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
-
126
125
/// High-level specifications of an abstract circuit.
127
126
#[ derive( Debug , Deserialize , Serialize ) ]
128
127
pub struct ModelCircuit {
@@ -136,8 +135,6 @@ pub struct ModelCircuit {
136
135
pub lookups : usize ,
137
136
/// Equality constraint enabled columns.
138
137
pub permutations : usize ,
139
- /// Number of shuffle arguments
140
- pub shuffles : usize ,
141
138
/// Number of distinct column queries across all gates.
142
139
pub column_queries : usize ,
143
140
/// Number of distinct sets of points in the multiopening argument.
@@ -160,7 +157,6 @@ impl CostOptions {
160
157
. cloned ( )
161
158
. chain ( self . lookup . iter ( ) . flat_map ( |l| l. queries ( ) ) )
162
159
. chain ( self . permutation . queries ( ) )
163
- . chain ( self . shuffle . iter ( ) . flat_map ( |s| s. queries ( ) ) )
164
160
. chain ( iter:: repeat ( "0" . parse ( ) . unwrap ( ) ) . take ( self . max_degree - 1 ) )
165
161
. collect ( ) ;
166
162
@@ -199,7 +195,7 @@ impl CostOptions {
199
195
// - inner product argument (k rounds * 2 * COMM bytes)
200
196
// - a (SCALAR bytes)
201
197
// - xi (SCALAR bytes)
202
- comp_bytes ( 1 + 2 * self . k , 2 )
198
+ comp_bytes ( 1 + 2 * self . min_k , 2 )
203
199
}
204
200
CommitmentScheme :: KZGGWC => {
205
201
let mut nr_rotations = HashSet :: new ( ) ;
@@ -227,12 +223,11 @@ impl CostOptions {
227
223
let size = plonk + vanishing + multiopen + polycomm;
228
224
229
225
ModelCircuit {
230
- k : self . k ,
226
+ k : self . min_k ,
231
227
max_deg : self . max_degree ,
232
228
advice_columns : self . advice . len ( ) ,
233
229
lookups : self . lookup . len ( ) ,
234
230
permutations : self . permutation . columns ,
235
- shuffles : self . shuffle . len ( ) ,
236
231
column_queries,
237
232
point_sets,
238
233
size,
@@ -247,7 +242,7 @@ pub fn from_circuit_to_model_circuit<
247
242
const COMM : usize ,
248
243
const SCALAR : usize ,
249
244
> (
250
- k : u32 ,
245
+ k : Option < u32 > ,
251
246
circuit : & C ,
252
247
instances : Vec < Vec < F > > ,
253
248
comm_scheme : CommitmentScheme ,
@@ -256,13 +251,34 @@ pub fn from_circuit_to_model_circuit<
256
251
options. into_model_circuit :: < COMM , SCALAR > ( comm_scheme)
257
252
}
258
253
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).
260
270
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 > ,
262
272
circuit : & C ,
263
273
instances : Vec < Vec < F > > ,
264
274
) -> 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
+
266
282
let cs = prover. cs ;
267
283
268
284
let fixed = {
@@ -298,16 +314,56 @@ pub fn from_circuit_to_cost_model_options<F: Ord + Field + FromUniformBytes<64>,
298
314
columns : cs. permutation ( ) . get_columns ( ) . len ( ) ,
299
315
} ;
300
316
301
- let shuffle = { cs. shuffles . iter ( ) . map ( |_| Shuffle ) . collect :: < Vec < _ > > ( ) } ;
302
-
303
317
let gate_degree = cs
304
318
. gates
305
319
. iter ( )
306
320
. flat_map ( |gate| gate. polynomials ( ) . iter ( ) . map ( |poly| poly. degree ( ) ) )
307
321
. max ( )
308
322
. unwrap_or ( 0 ) ;
309
323
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
+ }
311
367
312
368
CostOptions {
313
369
advice,
@@ -317,7 +373,9 @@ pub fn from_circuit_to_cost_model_options<F: Ord + Field + FromUniformBytes<64>,
317
373
max_degree : cs. degree ( ) ,
318
374
lookup,
319
375
permutation,
320
- shuffle,
321
- k,
376
+ min_k,
377
+ rows_count,
378
+ table_rows_count,
379
+ compressed_rows_count,
322
380
}
323
381
}
0 commit comments