diff --git a/circuit-benchmarks/src/mpt_circuit.rs b/circuit-benchmarks/src/mpt_circuit.rs index 3f850eb3b4..5160e66a76 100644 --- a/circuit-benchmarks/src/mpt_circuit.rs +++ b/circuit-benchmarks/src/mpt_circuit.rs @@ -48,10 +48,12 @@ mod tests { } } + let max_nodes = 720; let circuit = MPTCircuit:: { nodes, keccak_data, degree: degree as usize, + max_nodes, disable_preimage_check: false, _marker: PhantomData, }; diff --git a/light-client-poc/src/circuit/mod.rs b/light-client-poc/src/circuit/mod.rs index 69756e2dbc..cdd773caf1 100644 --- a/light-client-poc/src/circuit/mod.rs +++ b/light-client-poc/src/circuit/mod.rs @@ -5,5 +5,7 @@ mod witness; pub use prover::StateUpdateCircuitKeys; -pub use state_update::{StateUpdateCircuit, DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_PROOF_COUNT}; +pub use state_update::{ + StateUpdateCircuit, DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_NODES, DEFAULT_MAX_PROOF_COUNT, +}; pub use witness::{PublicInputs, StateUpdateWitness}; diff --git a/light-client-poc/src/circuit/state_update.rs b/light-client-poc/src/circuit/state_update.rs index 1c57f7e0d8..15464e311b 100644 --- a/light-client-poc/src/circuit/state_update.rs +++ b/light-client-poc/src/circuit/state_update.rs @@ -34,6 +34,7 @@ use zkevm_circuits::{ util::{SubCircuit, SubCircuitConfig}, }; +pub const DEFAULT_MAX_NODES: usize = 4000; pub const DEFAULT_MAX_PROOF_COUNT: usize = 20; pub const DEFAULT_CIRCUIT_DEGREE: usize = 14; @@ -90,6 +91,7 @@ impl Circuit for StateUpdateCircuit { MPTCircuitParams { degree: self.mpt_circuit.degree, disable_preimage_check: self.mpt_circuit.disable_preimage_check, + max_nodes: self.mpt_circuit.max_nodes, } } @@ -301,14 +303,15 @@ impl Circuit for StateUpdateCircuit { // assign MPT witness - let height = - config - .mpt_config - .assign(&mut layouter, &self.mpt_circuit.nodes, &challenges)?; - config.mpt_config.load_fixed_table(&mut layouter)?; config .mpt_config - .load_mult_table(&mut layouter, &challenges, height)?; + .assign(&mut layouter, &self.mpt_circuit.nodes, &challenges)?; + config.mpt_config.load_fixed_table(&mut layouter)?; + config.mpt_config.load_mult_table( + &mut layouter, + &challenges, + self.mpt_circuit.max_nodes, + )?; #[cfg(feature = "disable-keccak")] config.mpt_config.keccak_table.dev_load( @@ -466,6 +469,7 @@ impl StateUpdateCircuit { pub fn new( witness: StateUpdateWitness, degree: usize, + max_nodes: usize, max_proof_count: usize, ) -> Result> { let StateUpdateWitness { @@ -489,6 +493,7 @@ impl StateUpdateCircuit { nodes: mpt_witness, keccak_data: keccak_data.clone(), degree, + max_nodes, disable_preimage_check, _marker: std::marker::PhantomData, }; diff --git a/light-client-poc/src/server.rs b/light-client-poc/src/server.rs index c07c397bba..c9b68c616b 100644 --- a/light-client-poc/src/server.rs +++ b/light-client-poc/src/server.rs @@ -9,7 +9,7 @@ use std::{collections::HashMap, str::FromStr, time::SystemTime}; use crate::circuit::{ PublicInputs, StateUpdateCircuit, StateUpdateCircuitKeys, StateUpdateWitness, - DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_PROOF_COUNT, + DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_NODES, DEFAULT_MAX_PROOF_COUNT, }; pub async fn serve() -> Result<()> { @@ -62,8 +62,12 @@ pub async fn serve() -> Result<()> { }; let public_inputs: PublicInputs = (&witness.lc_witness).into(); - let circuit = - StateUpdateCircuit::new(witness, DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_PROOF_COUNT)?; + let circuit = StateUpdateCircuit::new( + witness, + DEFAULT_CIRCUIT_DEGREE, + DEFAULT_MAX_NODES, + DEFAULT_MAX_PROOF_COUNT, + )?; println!("trns: {:#?}", circuit.transforms); diff --git a/light-client-poc/src/tests/mainnet.rs b/light-client-poc/src/tests/mainnet.rs index b2f1db597d..6910b7e480 100644 --- a/light-client-poc/src/tests/mainnet.rs +++ b/light-client-poc/src/tests/mainnet.rs @@ -10,7 +10,7 @@ mod test { use crate::circuit::{ PublicInputs, StateUpdateCircuit, StateUpdateCircuitKeys, StateUpdateWitness, - DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_PROOF_COUNT, + DEFAULT_CIRCUIT_DEGREE, DEFAULT_MAX_NODES, DEFAULT_MAX_PROOF_COUNT, }; #[ctor::ctor] @@ -23,6 +23,7 @@ mod test { block_no: u64, access_list: &[(&str, Vec<&str>)], degree: usize, + max_nodes: usize, max_proof_count: usize, ) -> Result> { const PVK: &str = "7ccb34dc5fd31fd0aa7860de89a4adc37ccb34dc5fd31fd0aa7860de89a4adc3"; @@ -54,7 +55,7 @@ mod test { println!("trns: {:#?}", witness.transforms); - let circuit = StateUpdateCircuit::new(witness, degree, max_proof_count)?; + let circuit = StateUpdateCircuit::new(witness, degree, max_nodes, max_proof_count)?; circuit.assert_satisfied(); @@ -150,7 +151,14 @@ mod test { async fn test_block_436875() -> Result<()> { let block_no = 436875; let access_list = blocks().get(&block_no).unwrap().clone(); - let _ = mock_prove(block_no, &access_list, 16, DEFAULT_MAX_PROOF_COUNT).await?; + let _ = mock_prove( + block_no, + &access_list, + 16, + DEFAULT_MAX_NODES, + DEFAULT_MAX_PROOF_COUNT, + ) + .await?; Ok(()) } @@ -159,7 +167,14 @@ mod test { async fn test_block_107() -> Result<()> { let block_no = 107; let access_list = blocks().get(&block_no).unwrap().clone(); - let _ = mock_prove(block_no, &access_list, 15, DEFAULT_MAX_PROOF_COUNT).await?; + let _ = mock_prove( + block_no, + &access_list, + 15, + DEFAULT_MAX_NODES, + DEFAULT_MAX_PROOF_COUNT, + ) + .await?; Ok(()) } @@ -169,7 +184,14 @@ mod test { let block_no = 107; let access_list = blocks().get(&block_no).unwrap().clone(); - let circuit = mock_prove(block_no, &access_list, 15, DEFAULT_MAX_PROOF_COUNT).await?; + let circuit = mock_prove( + block_no, + &access_list, + 15, + DEFAULT_MAX_NODES, + DEFAULT_MAX_PROOF_COUNT, + ) + .await?; let public_inputs: PublicInputs = (&circuit.lc_witness).into(); let keys = StateUpdateCircuitKeys::new(&circuit); @@ -186,6 +208,7 @@ mod test { block_no, &access_list, DEFAULT_CIRCUIT_DEGREE, + DEFAULT_MAX_NODES, DEFAULT_MAX_PROOF_COUNT, ) .await?; @@ -214,7 +237,14 @@ mod test { async fn test_block_2000007() -> Result<()> { let block_no = 2000007; let access_list = blocks().get(&block_no).unwrap().clone(); - let _ = mock_prove(block_no, &access_list, 18, DEFAULT_MAX_PROOF_COUNT).await?; + let _ = mock_prove( + block_no, + &access_list, + 18, + DEFAULT_MAX_NODES, + DEFAULT_MAX_PROOF_COUNT, + ) + .await?; Ok(()) } @@ -223,7 +253,14 @@ mod test { async fn test_block_2000004() -> Result<()> { let block_no = 2000004; let access_list = blocks().get(&block_no).unwrap().clone(); - let _ = mock_prove(block_no, &access_list, 18, DEFAULT_MAX_PROOF_COUNT).await?; + let _ = mock_prove( + block_no, + &access_list, + 18, + DEFAULT_MAX_NODES, + DEFAULT_MAX_PROOF_COUNT, + ) + .await?; Ok(()) } @@ -232,7 +269,14 @@ mod test { async fn test_block_2000070() -> Result<()> { let block_no = 2000070; let access_list = blocks().get(&block_no).unwrap().clone(); - let _ = mock_prove(block_no, &access_list, 18, DEFAULT_MAX_PROOF_COUNT).await?; + let _ = mock_prove( + block_no, + &access_list, + 18, + DEFAULT_MAX_NODES, + DEFAULT_MAX_PROOF_COUNT, + ) + .await?; Ok(()) } } diff --git a/light-client-poc/src/utils.rs b/light-client-poc/src/utils.rs index a4706ac848..384e9dd221 100644 --- a/light-client-poc/src/utils.rs +++ b/light-client-poc/src/utils.rs @@ -146,10 +146,12 @@ pub fn verify_mpt_witness(nodes: Vec) -> Result<()> { // verify the circuit let disable_preimage_check = nodes[0].start.clone().unwrap().disable_preimage_check; let degree = 15; + let max_nodes = 520; let circuit = zkevm_circuits::mpt_circuit::MPTCircuit:: { nodes, keccak_data, degree, + max_nodes, disable_preimage_check, _marker: std::marker::PhantomData, }; diff --git a/zkevm-circuits/src/mpt_circuit.rs b/zkevm-circuits/src/mpt_circuit.rs index db73d02588..bc9ca04398 100644 --- a/zkevm-circuits/src/mpt_circuit.rs +++ b/zkevm-circuits/src/mpt_circuit.rs @@ -174,7 +174,6 @@ impl MPTContext { pub struct MPTConfig { pub(crate) q_enable: Column, pub(crate) q_first: Column, - pub(crate) q_last: Column, pub(crate) memory: MptMemory, /// MPT table pub mpt_table: MptTable, @@ -219,7 +218,6 @@ impl MPTConfig { ) -> Self { let q_enable = meta.fixed_column(); let q_first = meta.fixed_column(); - let q_last = meta.fixed_column(); let mpt_table = MptTable::construct(meta); @@ -308,7 +306,7 @@ impl MPTConfig { // Main MPT circuit // State machine cb.base.set_cell_manager(state_cm.clone()); - ifx! {f!(q_first) + f!(q_last) => { + ifx! {f!(q_first) => { require!(a!(state_machine.is_start) => true); }}; // Main state machine @@ -370,7 +368,6 @@ impl MPTConfig { MPTConfig { q_enable, q_first, - q_last, memory, keccak_table, fixed_table, @@ -390,8 +387,7 @@ impl MPTConfig { layouter: &mut impl Layouter, nodes: &[Node], challenges: &Challenges>, - ) -> Result { - let mut height = 0; + ) -> Result<(), Error> { layouter.assign_region( || "MPT", |mut region| { @@ -497,24 +493,28 @@ impl MPTConfig { cached_region.assign_stored_expressions(&self.cb.base, challenges)?; } - height = offset; - // Make sure the circuit is high enough for the mult table - while height < (2 * HASH_WIDTH + 1) { - height += 1; - } + assert!( self.params.max_nodes >= (2 * HASH_WIDTH + 1), + "The parameter max_nodes is set too low for the mult table: {}, mult table height: {}", + self.params.max_nodes, + 2 * HASH_WIDTH + 1, + ); + assert!( offset <= self.params.max_nodes, + "The parameter max_nodes is set too low, max_nodes: {}, offset: {}", + self.params.max_nodes, + offset, + ); - for offset in 0..height { + for offset in 0..self.params.max_nodes { assignf!(region, (self.q_enable, offset) => true.scalar())?; assignf!(region, (self.q_first, offset) => (offset == 0).scalar())?; - assignf!(region, (self.q_last, offset) => (offset == height - 2).scalar())?; } Ok(()) }, )?; - Ok(height) + Ok(()) } /// Loads MPT fixed table @@ -653,6 +653,8 @@ pub struct MPTCircuit { pub keccak_data: Vec>, /// log2(height) pub degree: usize, + /// Maximal number of nodes MPT can prove (for example, one branch has 16 nodes) + pub max_nodes: usize, /// Can be used to test artificially created tests with keys without known their known /// preimage. ONLY ENABLE FOR TESTS! pub disable_preimage_check: bool, @@ -667,6 +669,8 @@ pub struct MPTCircuitParams { pub degree: usize, /// pub disable_preimage_check: bool, + /// Maximal number of nodes MPT can prove (for example, one branch has 16 nodes) + pub max_nodes: usize, } impl MPTCircuitParams { @@ -694,6 +698,7 @@ impl Circuit for MPTCircuit { MPTCircuitParams { degree: self.degree, disable_preimage_check: self.disable_preimage_check, + max_nodes: self.max_nodes, } } @@ -717,9 +722,9 @@ impl Circuit for MPTCircuit { mut layouter: impl Layouter, ) -> Result<(), Error> { let challenges = _challenges.values(&mut layouter); - let height = config.assign(&mut layouter, &self.nodes, &challenges)?; + config.assign(&mut layouter, &self.nodes, &challenges)?; config.load_fixed_table(&mut layouter)?; - config.load_mult_table(&mut layouter, &challenges, height)?; + config.load_mult_table(&mut layouter, &challenges, self.max_nodes)?; config .keccak_table .dev_load(&mut layouter, &self.keccak_data, &challenges)?; @@ -789,10 +794,12 @@ mod tests { let disable_preimage_check = nodes[0].start.clone().unwrap().disable_preimage_check; let degree = 15; + let max_nodes = 520; let circuit = MPTCircuit:: { nodes, keccak_data, degree, + max_nodes, disable_preimage_check, _marker: PhantomData, };