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

Commit b303b28

Browse files
authored
MPT max nodes (#1745)
### Description This PR resolves the test failure in #1706. The parameter `max_nodes` has been added to the MPT to have always the same fixed column `q_enable`. The fixed column `q_last` has been removed because it is not necessary - if some nodes are added to the MPT proof after the account/storage leaf to enable some non-valid lookups, the proof would fail because of address/key RLC constraints (the RLC is being built node by node). ### Issue Link #1700 ### 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
1 parent d972588 commit b303b28

File tree

7 files changed

+100
-34
lines changed

7 files changed

+100
-34
lines changed

circuit-benchmarks/src/mpt_circuit.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@ mod tests {
4848
}
4949
}
5050

51+
let max_nodes = 720;
5152
let circuit = MPTCircuit::<Fr> {
5253
nodes,
5354
keccak_data,
5455
degree: degree as usize,
56+
max_nodes,
5557
disable_preimage_check: false,
5658
_marker: PhantomData,
5759
};

light-client-poc/src/circuit/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ mod witness;
55

66
pub use prover::StateUpdateCircuitKeys;
77

8-
pub use state_update::{StateUpdateCircuit, DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_PROOF_COUNT};
8+
pub use state_update::{
9+
StateUpdateCircuit, DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_NODES, DEFAULT_MAX_PROOF_COUNT,
10+
};
911
pub use witness::{PublicInputs, StateUpdateWitness};

light-client-poc/src/circuit/state_update.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use zkevm_circuits::{
3434
util::{SubCircuit, SubCircuitConfig},
3535
};
3636

37+
pub const DEFAULT_MAX_NODES: usize = 4000;
3738
pub const DEFAULT_MAX_PROOF_COUNT: usize = 20;
3839
pub const DEFAULT_CIRCUIT_DEGREE: usize = 14;
3940

@@ -90,6 +91,7 @@ impl<F: Field> Circuit<F> for StateUpdateCircuit<F> {
9091
MPTCircuitParams {
9192
degree: self.mpt_circuit.degree,
9293
disable_preimage_check: self.mpt_circuit.disable_preimage_check,
94+
max_nodes: self.mpt_circuit.max_nodes,
9395
}
9496
}
9597

@@ -301,14 +303,15 @@ impl<F: Field> Circuit<F> for StateUpdateCircuit<F> {
301303

302304
// assign MPT witness
303305

304-
let height =
305-
config
306-
.mpt_config
307-
.assign(&mut layouter, &self.mpt_circuit.nodes, &challenges)?;
308-
config.mpt_config.load_fixed_table(&mut layouter)?;
309306
config
310307
.mpt_config
311-
.load_mult_table(&mut layouter, &challenges, height)?;
308+
.assign(&mut layouter, &self.mpt_circuit.nodes, &challenges)?;
309+
config.mpt_config.load_fixed_table(&mut layouter)?;
310+
config.mpt_config.load_mult_table(
311+
&mut layouter,
312+
&challenges,
313+
self.mpt_circuit.max_nodes,
314+
)?;
312315

313316
#[cfg(feature = "disable-keccak")]
314317
config.mpt_config.keccak_table.dev_load(
@@ -466,6 +469,7 @@ impl StateUpdateCircuit<Fr> {
466469
pub fn new(
467470
witness: StateUpdateWitness<Fr>,
468471
degree: usize,
472+
max_nodes: usize,
469473
max_proof_count: usize,
470474
) -> Result<StateUpdateCircuit<Fr>> {
471475
let StateUpdateWitness {
@@ -489,6 +493,7 @@ impl StateUpdateCircuit<Fr> {
489493
nodes: mpt_witness,
490494
keccak_data: keccak_data.clone(),
491495
degree,
496+
max_nodes,
492497
disable_preimage_check,
493498
_marker: std::marker::PhantomData,
494499
};

light-client-poc/src/server.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{collections::HashMap, str::FromStr, time::SystemTime};
99

1010
use crate::circuit::{
1111
PublicInputs, StateUpdateCircuit, StateUpdateCircuitKeys, StateUpdateWitness,
12-
DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_PROOF_COUNT,
12+
DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_NODES, DEFAULT_MAX_PROOF_COUNT,
1313
};
1414

1515
pub async fn serve() -> Result<()> {
@@ -62,8 +62,12 @@ pub async fn serve() -> Result<()> {
6262
};
6363

6464
let public_inputs: PublicInputs<Fr> = (&witness.lc_witness).into();
65-
let circuit =
66-
StateUpdateCircuit::new(witness, DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_PROOF_COUNT)?;
65+
let circuit = StateUpdateCircuit::new(
66+
witness,
67+
DEFAULT_CIRCUIT_DEGREE,
68+
DEFAULT_MAX_NODES,
69+
DEFAULT_MAX_PROOF_COUNT,
70+
)?;
6771

6872
println!("trns: {:#?}", circuit.transforms);
6973

light-client-poc/src/tests/mainnet.rs

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod test {
1010

1111
use crate::circuit::{
1212
PublicInputs, StateUpdateCircuit, StateUpdateCircuitKeys, StateUpdateWitness,
13-
DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_PROOF_COUNT,
13+
DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_NODES, DEFAULT_MAX_PROOF_COUNT,
1414
};
1515

1616
#[ctor::ctor]
@@ -23,6 +23,7 @@ mod test {
2323
block_no: u64,
2424
access_list: &[(&str, Vec<&str>)],
2525
degree: usize,
26+
max_nodes: usize,
2627
max_proof_count: usize,
2728
) -> Result<StateUpdateCircuit<Fr>> {
2829
const PVK: &str = "7ccb34dc5fd31fd0aa7860de89a4adc37ccb34dc5fd31fd0aa7860de89a4adc3";
@@ -54,7 +55,7 @@ mod test {
5455

5556
println!("trns: {:#?}", witness.transforms);
5657

57-
let circuit = StateUpdateCircuit::new(witness, degree, max_proof_count)?;
58+
let circuit = StateUpdateCircuit::new(witness, degree, max_nodes, max_proof_count)?;
5859

5960
circuit.assert_satisfied();
6061

@@ -150,7 +151,14 @@ mod test {
150151
async fn test_block_436875() -> Result<()> {
151152
let block_no = 436875;
152153
let access_list = blocks().get(&block_no).unwrap().clone();
153-
let _ = mock_prove(block_no, &access_list, 16, DEFAULT_MAX_PROOF_COUNT).await?;
154+
let _ = mock_prove(
155+
block_no,
156+
&access_list,
157+
16,
158+
DEFAULT_MAX_NODES,
159+
DEFAULT_MAX_PROOF_COUNT,
160+
)
161+
.await?;
154162
Ok(())
155163
}
156164

@@ -159,7 +167,14 @@ mod test {
159167
async fn test_block_107() -> Result<()> {
160168
let block_no = 107;
161169
let access_list = blocks().get(&block_no).unwrap().clone();
162-
let _ = mock_prove(block_no, &access_list, 15, DEFAULT_MAX_PROOF_COUNT).await?;
170+
let _ = mock_prove(
171+
block_no,
172+
&access_list,
173+
15,
174+
DEFAULT_MAX_NODES,
175+
DEFAULT_MAX_PROOF_COUNT,
176+
)
177+
.await?;
163178
Ok(())
164179
}
165180

@@ -169,7 +184,14 @@ mod test {
169184
let block_no = 107;
170185
let access_list = blocks().get(&block_no).unwrap().clone();
171186

172-
let circuit = mock_prove(block_no, &access_list, 15, DEFAULT_MAX_PROOF_COUNT).await?;
187+
let circuit = mock_prove(
188+
block_no,
189+
&access_list,
190+
15,
191+
DEFAULT_MAX_NODES,
192+
DEFAULT_MAX_PROOF_COUNT,
193+
)
194+
.await?;
173195
let public_inputs: PublicInputs<Fr> = (&circuit.lc_witness).into();
174196

175197
let keys = StateUpdateCircuitKeys::new(&circuit);
@@ -186,6 +208,7 @@ mod test {
186208
block_no,
187209
&access_list,
188210
DEFAULT_CIRCUIT_DEGREE,
211+
DEFAULT_MAX_NODES,
189212
DEFAULT_MAX_PROOF_COUNT,
190213
)
191214
.await?;
@@ -214,7 +237,14 @@ mod test {
214237
async fn test_block_2000007() -> Result<()> {
215238
let block_no = 2000007;
216239
let access_list = blocks().get(&block_no).unwrap().clone();
217-
let _ = mock_prove(block_no, &access_list, 18, DEFAULT_MAX_PROOF_COUNT).await?;
240+
let _ = mock_prove(
241+
block_no,
242+
&access_list,
243+
18,
244+
DEFAULT_MAX_NODES,
245+
DEFAULT_MAX_PROOF_COUNT,
246+
)
247+
.await?;
218248
Ok(())
219249
}
220250

@@ -223,7 +253,14 @@ mod test {
223253
async fn test_block_2000004() -> Result<()> {
224254
let block_no = 2000004;
225255
let access_list = blocks().get(&block_no).unwrap().clone();
226-
let _ = mock_prove(block_no, &access_list, 18, DEFAULT_MAX_PROOF_COUNT).await?;
256+
let _ = mock_prove(
257+
block_no,
258+
&access_list,
259+
18,
260+
DEFAULT_MAX_NODES,
261+
DEFAULT_MAX_PROOF_COUNT,
262+
)
263+
.await?;
227264
Ok(())
228265
}
229266

@@ -232,7 +269,14 @@ mod test {
232269
async fn test_block_2000070() -> Result<()> {
233270
let block_no = 2000070;
234271
let access_list = blocks().get(&block_no).unwrap().clone();
235-
let _ = mock_prove(block_no, &access_list, 18, DEFAULT_MAX_PROOF_COUNT).await?;
272+
let _ = mock_prove(
273+
block_no,
274+
&access_list,
275+
18,
276+
DEFAULT_MAX_NODES,
277+
DEFAULT_MAX_PROOF_COUNT,
278+
)
279+
.await?;
236280
Ok(())
237281
}
238282
}

light-client-poc/src/utils.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,12 @@ pub fn verify_mpt_witness(nodes: Vec<Node>) -> Result<()> {
146146
// verify the circuit
147147
let disable_preimage_check = nodes[0].start.clone().unwrap().disable_preimage_check;
148148
let degree = 15;
149+
let max_nodes = 520;
149150
let circuit = zkevm_circuits::mpt_circuit::MPTCircuit::<Fr> {
150151
nodes,
151152
keccak_data,
152153
degree,
154+
max_nodes,
153155
disable_preimage_check,
154156
_marker: std::marker::PhantomData,
155157
};

zkevm-circuits/src/mpt_circuit.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ impl<F: Field> MPTContext<F> {
174174
pub struct MPTConfig<F: Field> {
175175
pub(crate) q_enable: Column<Fixed>,
176176
pub(crate) q_first: Column<Fixed>,
177-
pub(crate) q_last: Column<Fixed>,
178177
pub(crate) memory: MptMemory<F>,
179178
/// MPT table
180179
pub mpt_table: MptTable,
@@ -219,7 +218,6 @@ impl<F: Field> MPTConfig<F> {
219218
) -> Self {
220219
let q_enable = meta.fixed_column();
221220
let q_first = meta.fixed_column();
222-
let q_last = meta.fixed_column();
223221

224222
let mpt_table = MptTable::construct(meta);
225223

@@ -308,7 +306,7 @@ impl<F: Field> MPTConfig<F> {
308306
// Main MPT circuit
309307
// State machine
310308
cb.base.set_cell_manager(state_cm.clone());
311-
ifx! {f!(q_first) + f!(q_last) => {
309+
ifx! {f!(q_first) => {
312310
require!(a!(state_machine.is_start) => true);
313311
}};
314312
// Main state machine
@@ -370,7 +368,6 @@ impl<F: Field> MPTConfig<F> {
370368
MPTConfig {
371369
q_enable,
372370
q_first,
373-
q_last,
374371
memory,
375372
keccak_table,
376373
fixed_table,
@@ -390,8 +387,7 @@ impl<F: Field> MPTConfig<F> {
390387
layouter: &mut impl Layouter<F>,
391388
nodes: &[Node],
392389
challenges: &Challenges<Value<F>>,
393-
) -> Result<usize, Error> {
394-
let mut height = 0;
390+
) -> Result<(), Error> {
395391
layouter.assign_region(
396392
|| "MPT",
397393
|mut region| {
@@ -497,24 +493,28 @@ impl<F: Field> MPTConfig<F> {
497493

498494
cached_region.assign_stored_expressions(&self.cb.base, challenges)?;
499495
}
500-
height = offset;
501496

502-
// Make sure the circuit is high enough for the mult table
503-
while height < (2 * HASH_WIDTH + 1) {
504-
height += 1;
505-
}
497+
assert!( self.params.max_nodes >= (2 * HASH_WIDTH + 1),
498+
"The parameter max_nodes is set too low for the mult table: {}, mult table height: {}",
499+
self.params.max_nodes,
500+
2 * HASH_WIDTH + 1,
501+
);
502+
assert!( offset <= self.params.max_nodes,
503+
"The parameter max_nodes is set too low, max_nodes: {}, offset: {}",
504+
self.params.max_nodes,
505+
offset,
506+
);
506507

507-
for offset in 0..height {
508+
for offset in 0..self.params.max_nodes {
508509
assignf!(region, (self.q_enable, offset) => true.scalar())?;
509510
assignf!(region, (self.q_first, offset) => (offset == 0).scalar())?;
510-
assignf!(region, (self.q_last, offset) => (offset == height - 2).scalar())?;
511511
}
512512

513513
Ok(())
514514
},
515515
)?;
516516

517-
Ok(height)
517+
Ok(())
518518
}
519519

520520
/// Loads MPT fixed table
@@ -653,6 +653,8 @@ pub struct MPTCircuit<F: Field> {
653653
pub keccak_data: Vec<Vec<u8>>,
654654
/// log2(height)
655655
pub degree: usize,
656+
/// Maximal number of nodes MPT can prove (for example, one branch has 16 nodes)
657+
pub max_nodes: usize,
656658
/// Can be used to test artificially created tests with keys without known their known
657659
/// preimage. ONLY ENABLE FOR TESTS!
658660
pub disable_preimage_check: bool,
@@ -667,6 +669,8 @@ pub struct MPTCircuitParams {
667669
pub degree: usize,
668670
///
669671
pub disable_preimage_check: bool,
672+
/// Maximal number of nodes MPT can prove (for example, one branch has 16 nodes)
673+
pub max_nodes: usize,
670674
}
671675

672676
impl MPTCircuitParams {
@@ -694,6 +698,7 @@ impl<F: Field> Circuit<F> for MPTCircuit<F> {
694698
MPTCircuitParams {
695699
degree: self.degree,
696700
disable_preimage_check: self.disable_preimage_check,
701+
max_nodes: self.max_nodes,
697702
}
698703
}
699704

@@ -717,9 +722,9 @@ impl<F: Field> Circuit<F> for MPTCircuit<F> {
717722
mut layouter: impl Layouter<F>,
718723
) -> Result<(), Error> {
719724
let challenges = _challenges.values(&mut layouter);
720-
let height = config.assign(&mut layouter, &self.nodes, &challenges)?;
725+
config.assign(&mut layouter, &self.nodes, &challenges)?;
721726
config.load_fixed_table(&mut layouter)?;
722-
config.load_mult_table(&mut layouter, &challenges, height)?;
727+
config.load_mult_table(&mut layouter, &challenges, self.max_nodes)?;
723728
config
724729
.keccak_table
725730
.dev_load(&mut layouter, &self.keccak_data, &challenges)?;
@@ -789,10 +794,12 @@ mod tests {
789794

790795
let disable_preimage_check = nodes[0].start.clone().unwrap().disable_preimage_check;
791796
let degree = 15;
797+
let max_nodes = 520;
792798
let circuit = MPTCircuit::<Fr> {
793799
nodes,
794800
keccak_data,
795801
degree,
802+
max_nodes,
796803
disable_preimage_check,
797804
_marker: PhantomData,
798805
};

0 commit comments

Comments
 (0)