@@ -4,15 +4,13 @@ use eth_types::Field;
4
4
use halo2_proofs:: {
5
5
arithmetic:: FieldExt ,
6
6
circuit:: { Chip , Region , Value } ,
7
- plonk:: { Advice , Column , ConstraintSystem , Error , Expression , VirtualCells } ,
7
+ plonk:: { Advice , Column , ConstraintSystem , Error , Expression , TableColumn , VirtualCells } ,
8
8
poly:: Rotation ,
9
9
} ;
10
10
11
- use crate :: util:: sum;
12
-
13
- use super :: {
11
+ use crate :: {
14
12
bool_check,
15
- util:: { expr_from_bytes, pow_of_two} ,
13
+ util:: { expr_from_bytes, pow_of_two, sum } ,
16
14
} ;
17
15
18
16
/// Instruction that the Lt chip needs to implement.
@@ -25,6 +23,11 @@ pub trait LtInstruction<F: FieldExt> {
25
23
lhs : F ,
26
24
rhs : F ,
27
25
) -> Result < ( ) , Error > ;
26
+
27
+ #[ cfg( test) ]
28
+ /// Load the u8 lookup table.
29
+ fn dev_load ( & self , layouter : & mut impl halo2_proofs:: circuit:: Layouter < F > )
30
+ -> Result < ( ) , Error > ;
28
31
}
29
32
30
33
/// Config for the Lt chip.
@@ -33,8 +36,9 @@ pub struct LtConfig<F, const N_BYTES: usize> {
33
36
/// Denotes the lt outcome. If lhs < rhs then lt == 1, otherwise lt == 0.
34
37
pub lt : Column < Advice > ,
35
38
/// Denotes the bytes representation of the difference between lhs and rhs.
36
- /// Note that the range of each byte is not checked by this config.
37
39
pub diff : [ Column < Advice > ; N_BYTES ] ,
40
+ /// Denotes the range within which each byte should lie.
41
+ pub u8_table : TableColumn ,
38
42
/// Denotes the range within which both lhs and rhs lie.
39
43
pub range : F ,
40
44
}
@@ -62,16 +66,17 @@ impl<F: Field, const N_BYTES: usize> LtChip<F, N_BYTES> {
62
66
/// Configures the Lt chip.
63
67
pub fn configure (
64
68
meta : & mut ConstraintSystem < F > ,
65
- q_enable : impl FnOnce ( & mut VirtualCells < ' _ , F > ) -> Expression < F > ,
69
+ q_enable : impl FnOnce ( & mut VirtualCells < ' _ , F > ) -> Expression < F > + Clone ,
66
70
lhs : impl FnOnce ( & mut VirtualCells < F > ) -> Expression < F > ,
67
71
rhs : impl FnOnce ( & mut VirtualCells < F > ) -> Expression < F > ,
72
+ u8_table : TableColumn ,
68
73
) -> LtConfig < F , N_BYTES > {
69
74
let lt = meta. advice_column ( ) ;
70
75
let diff = [ ( ) ; N_BYTES ] . map ( |_| meta. advice_column ( ) ) ;
71
76
let range = pow_of_two ( N_BYTES * 8 ) ;
72
77
73
78
meta. create_gate ( "lt gate" , |meta| {
74
- let q_enable = q_enable ( meta) ;
79
+ let q_enable = q_enable. clone ( ) ( meta) ;
75
80
let lt = meta. query_advice ( lt, Rotation :: cur ( ) ) ;
76
81
77
82
let diff_bytes = diff
@@ -89,7 +94,22 @@ impl<F: Field, const N_BYTES: usize> LtChip<F, N_BYTES> {
89
94
. map ( move |poly| q_enable. clone ( ) * poly)
90
95
} ) ;
91
96
92
- LtConfig { lt, diff, range }
97
+ for cell_column in diff {
98
+ meta. lookup ( "range check for u8" , |meta| {
99
+ let q_enable = q_enable. clone ( ) ( meta) ;
100
+ vec ! [ (
101
+ q_enable * meta. query_advice( cell_column, Rotation :: cur( ) ) ,
102
+ u8_table,
103
+ ) ]
104
+ } ) ;
105
+ }
106
+
107
+ LtConfig {
108
+ lt,
109
+ diff,
110
+ u8_table,
111
+ range,
112
+ }
93
113
}
94
114
95
115
/// Constructs a Lt chip given a config.
@@ -129,6 +149,29 @@ impl<F: Field, const N_BYTES: usize> LtInstruction<F> for LtChip<F, N_BYTES> {
129
149
130
150
Ok ( ( ) )
131
151
}
152
+
153
+ #[ cfg( test) ]
154
+ fn dev_load (
155
+ & self ,
156
+ layouter : & mut impl halo2_proofs:: circuit:: Layouter < F > ,
157
+ ) -> Result < ( ) , Error > {
158
+ const RANGE : usize = u8:: MAX as usize ;
159
+
160
+ layouter. assign_table (
161
+ || "load u8 range check table" ,
162
+ |mut table| {
163
+ for i in 0 ..=RANGE {
164
+ table. assign_cell (
165
+ || "assign cell in fixed column" ,
166
+ self . config . u8_table ,
167
+ i,
168
+ || Value :: known ( F :: from ( i as u64 ) ) ,
169
+ ) ?;
170
+ }
171
+ Ok ( ( ) )
172
+ } ,
173
+ )
174
+ }
132
175
}
133
176
134
177
impl < F : Field , const N_BYTES : usize > Chip < F > for LtChip < F , N_BYTES > {
@@ -164,7 +207,7 @@ mod test {
164
207
165
208
// TODO: remove zk blinding factors in halo2 to restore the
166
209
// correct k (without the extra + 2).
167
- let k = usize :: BITS - $values. len( ) . leading_zeros( ) + 2 ;
210
+ let k = ( usize :: BITS - $values. len( ) . leading_zeros( ) + 2 ) . max ( 9 ) ;
168
211
let circuit = TestCircuit :: <Fp > {
169
212
values: Some ( $values) ,
170
213
checks: Some ( $checks) ,
@@ -181,7 +224,7 @@ mod test {
181
224
182
225
// TODO: remove zk blinding factors in halo2 to restore the
183
226
// correct k (without the extra + 2).
184
- let k = usize :: BITS - $values. len( ) . leading_zeros( ) + 2 ;
227
+ let k = ( usize :: BITS - $values. len( ) . leading_zeros( ) + 2 ) . max ( 9 ) ;
185
228
let circuit = TestCircuit :: <Fp > {
186
229
values: Some ( $values) ,
187
230
checks: Some ( $checks) ,
@@ -222,12 +265,14 @@ mod test {
222
265
let q_enable = meta. complex_selector ( ) ;
223
266
let value = meta. advice_column ( ) ;
224
267
let check = meta. advice_column ( ) ;
268
+ let u8_table = meta. lookup_table_column ( ) ;
225
269
226
270
let lt = LtChip :: configure (
227
271
meta,
228
272
|meta| meta. query_selector ( q_enable) ,
229
273
|meta| meta. query_advice ( value, Rotation :: prev ( ) ) ,
230
274
|meta| meta. query_advice ( value, Rotation :: cur ( ) ) ,
275
+ u8_table,
231
276
) ;
232
277
233
278
let config = Self :: Config {
@@ -265,6 +310,8 @@ mod test {
265
310
let ( first_value, values) = values. split_at ( 1 ) ;
266
311
let first_value = first_value[ 0 ] ;
267
312
313
+ chip. dev_load ( & mut layouter) ?;
314
+
268
315
layouter. assign_region (
269
316
|| "witness" ,
270
317
|mut region| {
@@ -340,12 +387,14 @@ mod test {
340
387
let q_enable = meta. complex_selector ( ) ;
341
388
let ( value_a, value_b) = ( meta. advice_column ( ) , meta. advice_column ( ) ) ;
342
389
let check = meta. advice_column ( ) ;
390
+ let u16_table = meta. lookup_table_column ( ) ;
343
391
344
392
let lt = LtChip :: configure (
345
393
meta,
346
394
|meta| meta. query_selector ( q_enable) ,
347
395
|meta| meta. query_advice ( value_a, Rotation :: cur ( ) ) ,
348
396
|meta| meta. query_advice ( value_b, Rotation :: cur ( ) ) ,
397
+ u16_table,
349
398
) ;
350
399
351
400
let config = Self :: Config {
@@ -387,6 +436,8 @@ mod test {
387
436
. ok_or ( Error :: Synthesis ) ?;
388
437
let checks = self . checks . as_ref ( ) . ok_or ( Error :: Synthesis ) ?;
389
438
439
+ chip. dev_load ( & mut layouter) ?;
440
+
390
441
layouter. assign_region (
391
442
|| "witness" ,
392
443
|mut region| {
0 commit comments