Skip to content

Commit 69d0a63

Browse files
authored
[MPT] Add minimal RLP encoding check (privacy-scaling-explorations#1588)
### Description Some small improvements to the MPT circuit. Most notably: - Added a check that the RLP encoding of the RLP values are minimal (no leading zeros) in the main RLP value decoding unit - Fixed bug: byte lookups were not generated correctly - Some other misc small improvements ### Issue Link [_link issue here_] ### Type of change - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] This change requires a documentation update ### Contents - [_item_] ### Rationale [_design decisions and extended information_] ### How Has This Been Tested? - All MPT tests run - make test-all
1 parent 342faab commit 69d0a63

16 files changed

+1002
-1218
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ To run the same tests as the CI, please use: `make test-all`.
1212
## Running benchmarks
1313

1414
There are currently several benchmarks to run in the workspace in regards to the circuits.
15-
All use the `DEGREE` env var to specify the degree of the `K` parameter that you want
15+
All use the `DEGREE` env var to specify the degree of the `K` parameter that you want
1616
to use for your circuit in the bench process.
1717
- Keccak Circuit prover benches. -> `DEGREE=16 make packed_multi_keccak_bench`
1818
- EVM Circuit prover benches. -> `DEGREE=18 make evm_bench`.
1919
- State Circuit prover benches. -> `DEGREE=18 make state_bench`
20-
- MPT Circuit prover benches. -> `DEGREE=14 make mpt_bench`
20+
- MPT Circuit prover benches. -> `DEGREE=15 make mpt_bench`
2121

2222
You can also run all benchmarks by running: `make circuit_benches DEGREE=18`.
2323

zkevm-circuits/src/circuit_tools/cached_region.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ use std::{
1010
hash::{Hash, Hasher},
1111
};
1212

13-
use super::{cell_manager::CellType, constraint_builder::ConstraintBuilder};
13+
use super::{
14+
cell_manager::{CellColumn, CellType},
15+
constraint_builder::ConstraintBuilder,
16+
};
1417

1518
pub trait ChallengeSet<F: Field> {
1619
fn indexed(&self) -> Vec<&Value<F>>;
@@ -64,13 +67,28 @@ impl<'r, 'b, F: Field> CachedRegion<'r, 'b, F> {
6467
) -> Result<(), Error> {
6568
for (offset, region_id) in self.regions.clone() {
6669
for stored_expression in cb.get_stored_expressions(region_id).iter() {
67-
// println!("stored expression: {}", stored_expression.name);
6870
stored_expression.assign(self, challenges, offset)?;
6971
}
7072
}
7173
Ok(())
7274
}
7375

76+
pub(crate) fn annotate_columns<C: CellType>(&mut self, cell_columns: &[CellColumn<F, C>]) {
77+
for c in cell_columns {
78+
self.region.name_column(
79+
|| {
80+
format!(
81+
"{:?} {:?}: {:?} queried",
82+
c.cell_type.clone(),
83+
c.index,
84+
c.height
85+
)
86+
},
87+
c.column,
88+
);
89+
}
90+
}
91+
7492
/// Assign an advice column value (witness).
7593
pub fn assign_advice<'v, V, VR, A, AR>(
7694
&'v mut self,

zkevm-circuits/src/circuit_tools/cell_manager.rs

+98-64
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
//! Cell manager
2+
use super::constraint_builder::ConstraintBuilder;
23
use crate::{
34
circuit_tools::cached_region::CachedRegion,
5+
evm_circuit::util::rlc,
6+
table::LookupTable,
47
util::{query_expression, word::Word, Expr},
58
};
6-
7-
use crate::table::LookupTable;
89
use eth_types::Field;
910
use halo2_proofs::{
1011
circuit::{AssignedCell, Value},
@@ -113,47 +114,39 @@ impl<F: Field> WordCell<F> {
113114
#[derive(Clone, Debug)]
114115
pub struct CellConfig<C: CellType> {
115116
pub cell_type: C,
116-
pub num_columns: usize,
117117
pub phase: u8,
118118
pub is_permute: bool,
119119
}
120120

121-
impl<C: CellType> From<(C, usize, u8, bool)> for CellConfig<C> {
122-
fn from((cell_type, num_columns, phase, is_permute): (C, usize, u8, bool)) -> Self {
121+
impl<C: CellType> CellConfig<C> {
122+
fn new(cell_type: C, phase: u8, is_permute: bool) -> Self {
123123
Self {
124124
cell_type,
125-
num_columns,
126125
phase,
127126
is_permute,
128127
}
129128
}
130-
}
131129

132-
impl<C: CellType> CellConfig<C> {
133-
pub fn init_columns<F: Field>(&self, meta: &mut ConstraintSystem<F>) -> Vec<Column<Advice>> {
134-
let mut columns = Vec::with_capacity(self.num_columns);
135-
for _ in 0..self.num_columns {
136-
let tmp = match self.phase {
137-
1 => meta.advice_column_in(FirstPhase),
138-
2 => meta.advice_column_in(SecondPhase),
139-
3 => meta.advice_column_in(ThirdPhase),
140-
_ => unreachable!(),
141-
};
142-
columns.push(tmp);
143-
}
130+
pub fn init_column<F: Field>(&self, meta: &mut ConstraintSystem<F>) -> Column<Advice> {
131+
let column = match self.phase {
132+
0 => meta.advice_column_in(FirstPhase),
133+
1 => meta.advice_column_in(SecondPhase),
134+
2 => meta.advice_column_in(ThirdPhase),
135+
_ => unreachable!(),
136+
};
144137
if self.is_permute {
145-
let _ = columns
146-
.iter()
147-
.map(|c| meta.enable_equality(*c))
148-
.collect::<Vec<()>>();
138+
meta.enable_equality(column);
149139
}
150-
columns
140+
column
151141
}
152142
}
153143

154144
pub trait CellType:
155145
Clone + Copy + Debug + PartialEq + Eq + PartialOrd + Ord + Hash + Default
156146
{
147+
/// This is the table type for lookups
148+
type TableType: Clone + Copy + Debug + PartialEq + Eq + PartialOrd + Ord + Hash;
149+
157150
fn byte_type() -> Option<Self>;
158151

159152
// The phase that given `Expression` becomes evaluateable.
@@ -171,6 +164,12 @@ pub trait CellType:
171164
/// Return the storage phase of phase
172165
fn storage_for_phase(phase: u8) -> Self;
173166

167+
/// Creates a type from a unique id
168+
fn create_type(id: usize) -> Self;
169+
170+
/// Returns the table type of the lookup (if it's a lookup)
171+
fn lookup_table_type(&self) -> Option<Self::TableType>;
172+
174173
/// Return the storage cell of the expression
175174
fn storage_for_expr<F: Field>(expr: &Expression<F>) -> Self {
176175
Self::storage_for_phase(Self::expr_phase::<F>(expr))
@@ -184,36 +183,48 @@ pub enum DefaultCellType {
184183
StoragePhase3,
185184
}
186185

186+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
187+
pub enum DefaultLookupType {}
188+
187189
impl Default for DefaultCellType {
188190
fn default() -> Self {
189191
Self::StoragePhase1
190192
}
191193
}
192194

193195
impl CellType for DefaultCellType {
196+
type TableType = DefaultLookupType;
197+
194198
fn byte_type() -> Option<Self> {
195199
Some(DefaultCellType::StoragePhase1)
196200
}
197201

198202
fn storage_for_phase(phase: u8) -> Self {
199-
// println!("phase: {}", phase);
200203
match phase {
201-
1 => DefaultCellType::StoragePhase1,
202-
2 => DefaultCellType::StoragePhase2,
203-
3 => DefaultCellType::StoragePhase3,
204+
0 => DefaultCellType::StoragePhase1,
205+
1 => DefaultCellType::StoragePhase2,
206+
2 => DefaultCellType::StoragePhase3,
204207
_ => unreachable!(),
205208
}
206209
}
210+
211+
fn create_type(_id: usize) -> Self {
212+
unreachable!()
213+
}
214+
215+
fn lookup_table_type(&self) -> Option<Self::TableType> {
216+
None
217+
}
207218
}
208219

209220
#[derive(Clone, Debug)]
210221
pub(crate) struct CellColumn<F, C: CellType> {
211222
pub(crate) column: Column<Advice>,
212-
index: usize,
213223
pub(crate) cell_type: C,
214-
height: usize,
215-
cells: Vec<Cell<F>>,
224+
pub(crate) cells: Vec<Cell<F>>,
216225
pub(crate) expr: Expression<F>,
226+
pub(super) height: usize,
227+
pub(super) index: usize,
217228
}
218229

219230
impl<F: Field, C: CellType> PartialEq for CellColumn<F, C> {
@@ -244,51 +255,74 @@ impl<F: Field, C: CellType> Expr<F> for CellColumn<F, C> {
244255
}
245256
}
246257

247-
#[derive(Clone, Debug)]
258+
#[derive(Clone, Debug, Default)]
248259
pub struct CellManager<F, C: CellType> {
249260
configs: Vec<CellConfig<C>>,
250261
columns: Vec<CellColumn<F, C>>,
251262
height: usize,
252263
height_limit: usize,
264+
offset: usize,
253265
}
254266

255267
impl<F: Field, C: CellType> CellManager<F, C> {
256-
pub(crate) fn new(
257-
meta: &mut ConstraintSystem<F>,
258-
configs: Vec<(C, usize, u8, bool)>,
259-
offset: usize,
260-
max_height: usize,
261-
) -> Self {
262-
let configs = configs
263-
.into_iter()
264-
.map(|c| c.into())
265-
.collect::<Vec<CellConfig<C>>>();
268+
pub(crate) fn new(max_height: usize, offset: usize) -> Self {
269+
Self {
270+
configs: Vec::new(),
271+
columns: Vec::new(),
272+
height: max_height,
273+
height_limit: max_height,
274+
offset,
275+
}
276+
}
266277

267-
let mut columns = Vec::new();
268-
for config in configs.iter() {
269-
let cols = config.init_columns(meta);
270-
for col in cols.iter() {
271-
let mut cells = Vec::new();
272-
for r in 0..max_height {
273-
query_expression(meta, |meta| {
274-
cells.push(Cell::new(meta, *col, offset + r));
275-
});
276-
}
277-
columns.push(CellColumn {
278-
column: *col,
279-
index: columns.len(),
280-
cell_type: config.cell_type,
281-
height: 0,
282-
expr: cells[0].expr(),
283-
cells,
278+
pub(crate) fn add_columns(
279+
&mut self,
280+
meta: &mut ConstraintSystem<F>,
281+
cb: &mut ConstraintBuilder<F, C>,
282+
cell_type: C,
283+
phase: u8,
284+
permutable: bool,
285+
num_columns: usize,
286+
) {
287+
for _ in 0..num_columns {
288+
// Add a column of the specified type
289+
let config = CellConfig::new(cell_type, phase, permutable);
290+
let col = config.init_column(meta);
291+
let mut cells = Vec::new();
292+
for r in 0..self.height_limit {
293+
query_expression(meta, |meta| {
294+
cells.push(Cell::new(meta, col, self.offset + r));
284295
});
285296
}
297+
let column_expr = cells[0].expr();
298+
self.columns.push(CellColumn {
299+
column: col,
300+
index: self.columns.len(),
301+
cell_type: config.cell_type,
302+
height: 0,
303+
expr: column_expr.expr(),
304+
cells,
305+
});
306+
self.configs.push(config);
307+
308+
// For cell types that are lookups, generate the lookup here
309+
if let Some(table) = cell_type.lookup_table_type() {
310+
cb.add_lookup(
311+
format!("{:?}", table),
312+
vec![column_expr.expr()],
313+
vec![rlc::expr(
314+
&cb.table(table),
315+
cb.lookup_challenge.clone().unwrap(),
316+
)],
317+
);
318+
}
286319
}
287-
Self {
288-
configs,
289-
columns,
290-
height: max_height,
291-
height_limit: max_height,
320+
}
321+
322+
pub(crate) fn restart(&mut self) {
323+
self.height = self.height_limit;
324+
for col in self.columns.iter_mut() {
325+
col.height = 0;
292326
}
293327
}
294328

0 commit comments

Comments
 (0)