Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.

Commit 3ac930f

Browse files
authored
[MPT] Misc refactoring (#972)
Some refactoring which I believe decreases code duplication and increases code readability. Some TODOs: - [x] The code required to get the previous rlc/mult data or the inclusion in the parent check is quite complicated because of the different node types. Instead it may be better to use a fixed location to store this data in so a node can simply use this data directly instead of having to figure out on its own where to find the data. This is cleaner because this way each node can decide on its own how these should be handled. - [x] Currently RLP decoding is done using a couple of selectors that are inputs from the prover. Then there are some checks if these are correct, though these are not complete. I think it's easier to think about this if we would just use a lookup to directly verify if these selectors are set correctly so we don't have to worry about edge cases are cases that are hard to constrain using custom gates. - [x] There are currently many cases in the main state maching because each row type is it's own state. However there is not really any reuse between custom gates between these rows, except for branches. It'll likely be quite a bit simple to just have a single state for account, storage and extension and just use multiple rows in those states - [x] May be a good idea to split up branches and extension nodes. (semi done) - [ ] There's a couple of circuit tools that were added in this PR to make writing the MPT circuit more manageable. A lot of these tools can still be greatly improved. - [ ] Number of lookups has been reduced a lot, but there are still many optimization possibilities (have not looked into reducing the expression degree for example). - [x] The circuit uses a fixed layout which uses around 100 columns (of which a lot need to be byte constrained so needs a lot of lookups as well). This makes the circuit quite a bit more dense than probably required, a more flexible way to manager the required data so the width/height can be choses would be very useful I think.
1 parent 8b2f66d commit 3ac930f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+6886
-16794
lines changed

gadgets/src/is_zero.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! - witnesses `inv0(value)`, where `inv0(x)` is 0 when `x` = 0, and
55
//! `1/x` otherwise
66
7+
use eth_types::Field;
78
use halo2_proofs::{
89
arithmetic::FieldExt,
910
circuit::{Chip, Region, Value},
@@ -51,7 +52,7 @@ pub struct IsZeroChip<F> {
5152
}
5253

5354
#[rustfmt::skip]
54-
impl<F: FieldExt> IsZeroChip<F> {
55+
impl<F: Field> IsZeroChip<F> {
5556
/// Sets up the configuration of the chip by creating the required columns
5657
/// and defining the constraints that take part when using `is_zero` gate.
5758
///
@@ -138,8 +139,8 @@ impl<F: FieldExt> Chip<F> for IsZeroChip<F> {
138139
#[cfg(test)]
139140
mod test {
140141
use super::{IsZeroChip, IsZeroConfig, IsZeroInstruction};
142+
use eth_types::Field;
141143
use halo2_proofs::{
142-
arithmetic::FieldExt,
143144
circuit::{Layouter, SimpleFloorPlanner, Value},
144145
dev::MockProver,
145146
halo2curves::bn256::Fr as Fp,
@@ -193,14 +194,14 @@ mod test {
193194
}
194195

195196
#[derive(Default)]
196-
struct TestCircuit<F: FieldExt> {
197+
struct TestCircuit<F: Field> {
197198
values: Option<Vec<u64>>,
198199
// checks[i] = is_zero(values[i + 1] - values[i])
199200
checks: Option<Vec<bool>>,
200201
_marker: PhantomData<F>,
201202
}
202203

203-
impl<F: FieldExt> Circuit<F> for TestCircuit<F> {
204+
impl<F: Field> Circuit<F> for TestCircuit<F> {
204205
type Config = TestCircuitConfig<F>;
205206
type FloorPlanner = SimpleFloorPlanner;
206207

@@ -325,14 +326,14 @@ mod test {
325326
}
326327

327328
#[derive(Default)]
328-
struct TestCircuit<F: FieldExt> {
329+
struct TestCircuit<F: Field> {
329330
values: Option<Vec<(u64, u64)>>,
330331
// checks[i] = is_zero(values[i].0 - values[i].1)
331332
checks: Option<Vec<bool>>,
332333
_marker: PhantomData<F>,
333334
}
334335

335-
impl<F: FieldExt> Circuit<F> for TestCircuit<F> {
336+
impl<F: Field> Circuit<F> for TestCircuit<F> {
336337
type Config = TestCircuitConfig<F>;
337338
type FloorPlanner = SimpleFloorPlanner;
338339

gadgets/src/util.rs

+81-29
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
//! Utility traits, functions used in the crate.
2-
use eth_types::evm_types::{GasCost, OpcodeId};
3-
use halo2_proofs::{arithmetic::FieldExt, plonk::Expression};
2+
use eth_types::{
3+
evm_types::{GasCost, OpcodeId},
4+
Field,
5+
};
6+
use halo2_proofs::plonk::Expression;
47

58
/// Returns the sum of the passed in cells
69
pub mod sum {
710
use crate::util::Expr;
11+
use eth_types::Field;
812
use halo2_proofs::{arithmetic::FieldExt, plonk::Expression};
913

1014
/// Returns an expression for the sum of the list of expressions.
11-
pub fn expr<F: FieldExt, E: Expr<F>, I: IntoIterator<Item = E>>(inputs: I) -> Expression<F> {
15+
pub fn expr<F: Field, E: Expr<F>, I: IntoIterator<Item = E>>(inputs: I) -> Expression<F> {
1216
inputs
1317
.into_iter()
1418
.fold(0.expr(), |acc, input| acc + input.expr())
@@ -26,11 +30,12 @@ pub mod sum {
2630
/// otherwise. Inputs need to be boolean
2731
pub mod and {
2832
use crate::util::Expr;
33+
use eth_types::Field;
2934
use halo2_proofs::{arithmetic::FieldExt, plonk::Expression};
3035

3136
/// Returns an expression that evaluates to 1 only if all the expressions in
3237
/// the given list are 1, else returns 0.
33-
pub fn expr<F: FieldExt, E: Expr<F>, I: IntoIterator<Item = E>>(inputs: I) -> Expression<F> {
38+
pub fn expr<F: Field, E: Expr<F>, I: IntoIterator<Item = E>>(inputs: I) -> Expression<F> {
3439
inputs
3540
.into_iter()
3641
.fold(1.expr(), |acc, input| acc * input.expr())
@@ -47,11 +52,12 @@ pub mod and {
4752
pub mod or {
4853
use super::{and, not};
4954
use crate::util::Expr;
55+
use eth_types::Field;
5056
use halo2_proofs::{arithmetic::FieldExt, plonk::Expression};
5157

5258
/// Returns an expression that evaluates to 1 if any expression in the given
5359
/// list is 1. Returns 0 if all the expressions were 0.
54-
pub fn expr<F: FieldExt, E: Expr<F>, I: IntoIterator<Item = E>>(inputs: I) -> Expression<F> {
60+
pub fn expr<F: Field, E: Expr<F>, I: IntoIterator<Item = E>>(inputs: I) -> Expression<F> {
5561
not::expr(and::expr(inputs.into_iter().map(not::expr)))
5662
}
5763

@@ -65,10 +71,11 @@ pub mod or {
6571
/// `b` needs to be boolean
6672
pub mod not {
6773
use crate::util::Expr;
74+
use eth_types::Field;
6875
use halo2_proofs::{arithmetic::FieldExt, plonk::Expression};
6976

7077
/// Returns an expression that represents the NOT of the given expression.
71-
pub fn expr<F: FieldExt, E: Expr<F>>(b: E) -> Expression<F> {
78+
pub fn expr<F: Field, E: Expr<F>>(b: E) -> Expression<F> {
7279
1.expr() - b.expr()
7380
}
7481

@@ -82,10 +89,11 @@ pub mod not {
8289
/// `a` and `b` needs to be boolean
8390
pub mod xor {
8491
use crate::util::Expr;
92+
use eth_types::Field;
8593
use halo2_proofs::{arithmetic::FieldExt, plonk::Expression};
8694

8795
/// Returns an expression that represents the XOR of the given expression.
88-
pub fn expr<F: FieldExt, E: Expr<F>>(a: E, b: E) -> Expression<F> {
96+
pub fn expr<F: Field, E: Expr<F>>(a: E, b: E) -> Expression<F> {
8997
a.expr() + b.expr() - 2.expr() * a.expr() * b.expr()
9098
}
9199

@@ -99,11 +107,12 @@ pub mod xor {
99107
/// `selector == 0`. `selector` needs to be boolean.
100108
pub mod select {
101109
use crate::util::Expr;
102-
use halo2_proofs::{arithmetic::FieldExt, plonk::Expression};
110+
use eth_types::Field;
111+
use halo2_proofs::plonk::Expression;
103112

104113
/// Returns the `when_true` expression when the selector is true, else
105114
/// returns the `when_false` expression.
106-
pub fn expr<F: FieldExt>(
115+
pub fn expr<F: Field>(
107116
selector: Expression<F>,
108117
when_true: Expression<F>,
109118
when_false: Expression<F>,
@@ -113,13 +122,13 @@ pub mod select {
113122

114123
/// Returns the `when_true` value when the selector is true, else returns
115124
/// the `when_false` value.
116-
pub fn value<F: FieldExt>(selector: F, when_true: F, when_false: F) -> F {
125+
pub fn value<F: Field>(selector: F, when_true: F, when_false: F) -> F {
117126
selector * when_true + (F::one() - selector) * when_false
118127
}
119128

120129
/// Returns the `when_true` word when selector is true, else returns the
121130
/// `when_false` word.
122-
pub fn value_word<F: FieldExt>(
131+
pub fn value_word<F: Field>(
123132
selector: F,
124133
when_true: [u8; 32],
125134
when_false: [u8; 32],
@@ -132,9 +141,37 @@ pub mod select {
132141
}
133142
}
134143

144+
/// Trait that implements functionality to get a scalar from
145+
/// commonly used types.
146+
pub trait Scalar<F: Field> {
147+
/// Returns a scalar for the type.
148+
fn scalar(&self) -> F;
149+
}
150+
151+
/// Implementation trait `Scalar` for type able to be casted to u64
152+
#[macro_export]
153+
macro_rules! impl_scalar {
154+
($type:ty) => {
155+
impl<F: eth_types::Field> $crate::util::Scalar<F> for $type {
156+
#[inline]
157+
fn scalar(&self) -> F {
158+
F::from(*self as u64)
159+
}
160+
}
161+
};
162+
($type:ty, $method:path) => {
163+
impl<F: eth_types::Field> $crate::util::Scalar<F> for $type {
164+
#[inline]
165+
fn scalar(&self) -> F {
166+
F::from($method(self) as u64)
167+
}
168+
}
169+
};
170+
}
171+
135172
/// Trait that implements functionality to get a constant expression from
136173
/// commonly used types.
137-
pub trait Expr<F: FieldExt> {
174+
pub trait Expr<F: Field> {
138175
/// Returns an expression for the type.
139176
fn expr(&self) -> Expression<F>;
140177
}
@@ -143,15 +180,17 @@ pub trait Expr<F: FieldExt> {
143180
#[macro_export]
144181
macro_rules! impl_expr {
145182
($type:ty) => {
146-
impl<F: halo2_proofs::arithmetic::FieldExt> $crate::util::Expr<F> for $type {
183+
$crate::impl_scalar!($type);
184+
impl<F: eth_types::Field> $crate::util::Expr<F> for $type {
147185
#[inline]
148186
fn expr(&self) -> Expression<F> {
149187
Expression::Constant(F::from(*self as u64))
150188
}
151189
}
152190
};
153191
($type:ty, $method:path) => {
154-
impl<F: halo2_proofs::arithmetic::FieldExt> $crate::util::Expr<F> for $type {
192+
$crate::impl_scalar!($type, $method);
193+
impl<F: eth_types::Field> $crate::util::Expr<F> for $type {
155194
#[inline]
156195
fn expr(&self) -> Expression<F> {
157196
Expression::Constant(F::from($method(self) as u64))
@@ -164,40 +203,53 @@ impl_expr!(bool);
164203
impl_expr!(u8);
165204
impl_expr!(u64);
166205
impl_expr!(usize);
206+
impl_expr!(isize);
167207
impl_expr!(OpcodeId, OpcodeId::as_u8);
168208
impl_expr!(GasCost, GasCost::as_u64);
169209

170-
impl<F: FieldExt> Expr<F> for Expression<F> {
210+
impl<F: Field> Scalar<F> for i32 {
211+
#[inline]
212+
fn scalar(&self) -> F {
213+
F::from(self.unsigned_abs() as u64)
214+
* if self.is_negative() {
215+
-F::one()
216+
} else {
217+
F::one()
218+
}
219+
}
220+
}
221+
222+
impl<F: Field> Scalar<F> for &F {
223+
#[inline]
224+
fn scalar(&self) -> F {
225+
*self.clone()
226+
}
227+
}
228+
229+
impl<F: Field> Expr<F> for i32 {
171230
#[inline]
172231
fn expr(&self) -> Expression<F> {
173-
self.clone()
232+
Expression::Constant(self.scalar())
174233
}
175234
}
176235

177-
impl<F: FieldExt> Expr<F> for &Expression<F> {
236+
impl<F: Field> Expr<F> for Expression<F> {
178237
#[inline]
179238
fn expr(&self) -> Expression<F> {
180-
(*self).clone()
239+
self.clone()
181240
}
182241
}
183242

184-
impl<F: FieldExt> Expr<F> for i32 {
243+
impl<F: Field> Expr<F> for &Expression<F> {
185244
#[inline]
186245
fn expr(&self) -> Expression<F> {
187-
Expression::Constant(
188-
F::from(self.unsigned_abs() as u64)
189-
* if self.is_negative() {
190-
-F::one()
191-
} else {
192-
F::one()
193-
},
194-
)
246+
(*self).clone()
195247
}
196248
}
197249

198250
/// Given a bytes-representation of an expression, it computes and returns the
199251
/// single expression.
200-
pub fn expr_from_bytes<F: FieldExt, E: Expr<F>>(bytes: &[E]) -> Expression<F> {
252+
pub fn expr_from_bytes<F: Field, E: Expr<F>>(bytes: &[E]) -> Expression<F> {
201253
let mut value = 0.expr();
202254
let mut multiplier = F::one();
203255
for byte in bytes.iter() {
@@ -208,6 +260,6 @@ pub fn expr_from_bytes<F: FieldExt, E: Expr<F>>(bytes: &[E]) -> Expression<F> {
208260
}
209261

210262
/// Returns 2**by as FieldExt
211-
pub fn pow_of_two<F: FieldExt>(by: usize) -> F {
263+
pub fn pow_of_two<F: Field>(by: usize) -> F {
212264
F::from(2).pow(&[by as u64, 0, 0, 0])
213265
}

zkevm-circuits/src/circuit_tools.rs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//! Circuit utilities
2+
#[macro_use]
3+
pub mod constraint_builder;
4+
pub mod cell_manager;
5+
pub mod gadgets;
6+
pub mod memory;

0 commit comments

Comments
 (0)