From 19fcbd54dfcf7e3569e8b824b4a7d52098cb15fa Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Sat, 12 Aug 2023 15:56:09 +0800 Subject: [PATCH 01/10] stage --- zkevm-circuits/src/pi_circuit.rs | 105 +++++++++++++++++++++++----- zkevm-circuits/src/witness/block.rs | 14 ++++ 2 files changed, 100 insertions(+), 19 deletions(-) diff --git a/zkevm-circuits/src/pi_circuit.rs b/zkevm-circuits/src/pi_circuit.rs index dcd617324d..70af2e24fb 100644 --- a/zkevm-circuits/src/pi_circuit.rs +++ b/zkevm-circuits/src/pi_circuit.rs @@ -7,7 +7,7 @@ mod param; #[cfg(any(feature = "test", test, feature = "test-circuits"))] mod test; -use std::{iter, marker::PhantomData, str::FromStr}; +use std::{collections::BTreeMap, iter, marker::PhantomData, str::FromStr}; use crate::{evm_circuit::util::constraint_builder::ConstrainBuilderCommon, table::KeccakTable}; use bus_mapping::circuit_input_builder::get_dummy_tx_hash; @@ -47,11 +47,15 @@ use once_cell::sync::Lazy; use crate::{ evm_circuit::param::{N_BYTES_ACCOUNT_ADDRESS, N_BYTES_U64, N_BYTES_WORD}, pi_circuit::param::{COINBASE_OFFSET, DIFFICULTY_OFFSET}, - table::BlockContextFieldTag::{ - BaseFee, ChainId, Coinbase, CumNumTxs, Difficulty, GasLimit, NumTxs, Number, Timestamp, + table::{ + BlockContextFieldTag, + BlockContextFieldTag::{ + BaseFee, ChainId, Coinbase, CumNumTxs, Difficulty, GasLimit, NumTxs, Number, Timestamp, + }, }, util::rlc_be_bytes, }; +use eth_types::geth_types::TxType::L1Msg; use halo2_proofs::circuit::{Cell, RegionIndex}; #[cfg(any(feature = "test", test, feature = "test-circuits"))] use halo2_proofs::{circuit::SimpleFloorPlanner, plonk::Circuit}; @@ -70,6 +74,8 @@ pub(crate) static DIFFICULTY: Lazy = Lazy::new(|| read_env_var("DIFFICULTY pub struct PublicData { /// chain id pub chain_id: u64, + /// Start L1 QueueIndex + pub start_l1_queue_index: u64, /// Block Transactions pub transactions: Vec, /// Block contexts @@ -84,6 +90,7 @@ impl Default for PublicData { fn default() -> Self { PublicData { chain_id: 0, + start_l1_queue_index: 0, transactions: vec![], prev_state_root: H256::zero(), withdraw_trie_root: H256::zero(), @@ -93,16 +100,57 @@ impl Default for PublicData { } impl PublicData { + fn get_num_txs(&self) -> BTreeMap { + let mut num_txs_in_blocks = BTreeMap::new(); + // short for total number of l1 msgs popped before + let mut total_l1_popped = self.start_l1_queue_index; + for &block_num in self + .block_ctxs + .ctxs + .iter() + .map(|(block_num, ctx)| block_num) + { + let num_l2_txs = self + .transactions + .iter() + .filter(|tx| !tx.tx_type.is_l1_msg() && tx.block_number == *block_num) + .count(); + let num_l1_msgs = self + .transactions + .iter() + .filter(|tx| tx.tx_type.is_l1_msg() && tx.block_number == *block_num) + // tx.nonce alias for queue_index for l1 msg tx + .map(|tx| tx.nonce) + .max() + .map_or(0, |max_queue_index| max_queue_index - total_l1_popped + 1); + total_l1_popped += num_l1_msgs; + + let num_txs = num_l2_txs + num_l1_msgs; + num_txs_in_blocks.insert(block_num, num_txs); + + log::trace!( + "[block {}] total_l1_popped: {}, num_l1_msgs: {}, num_l2_txs: {}, num_txs: {}", + block_num, + total_l1_popped, + num_l1_msgs, + num_l2_txs, + num_txs + ); + } + + num_txs_in_blocks + } + /// Compute the bytes for dataHash from the verifier's perspective. fn data_bytes(&self) -> Vec { + let num_txs_in_blocks = self.get_num_txs(); let result = iter::empty() .chain(self.block_ctxs.ctxs.iter().flat_map(|(block_num, block)| { - let num_txs = self - .transactions - .iter() - .filter(|tx| tx.block_number == *block_num) - .count() as u16; - + let num_txs = num_txs_in_blocks + .get(block_num) + .cloned() + .expect(format!("get num_txs in block {block_num}").as_str()) + as u16; iter::empty() // Block Values .chain(block.number.as_u64().to_be_bytes()) @@ -541,6 +589,14 @@ impl SubCircuitConfig for PiCircuitConfig { meta.query_advice(cum_num_txs, Rotation::cur()) + num_txs, ); + cb.require_equal( + "block_table.value' == cum_num_txs' if block_table.tag == Nums", + meta.query_advice(block_table.value, Rotation::next()), + meta.query_advice(cum_num_txs, Rotation::next()), + ); + + // NOTE: cum_num_txs is already enforced to start with 0 using copy constraint. + cb.gate(meta.query_fixed(q_block_tag, Rotation::cur())) } ); @@ -605,6 +661,7 @@ impl PiCircuitConfig { .iter() .map(|tx| tx.hash) .collect::>(); + let num_txs_in_blocks = public_data.get_num_txs(); let mut offset = 0; let mut block_copy_cells = vec![]; @@ -636,11 +693,12 @@ impl PiCircuitConfig { .enumerate() { let is_rpi_padding = i >= block_values.ctxs.len(); - let num_txs = public_data - .transactions - .iter() - .filter(|tx| tx.block_number == block.number.as_u64()) - .count() as u16; + let block_num = block.number.as_u64(); + let num_txs = num_txs_in_blocks + .get(&block_num) + .cloned() + .expect(format!("get num_txs in block {block_num}").as_str()) + as u16; // Assign fields in pi columns and connect them to block table let fields = vec![ @@ -1274,6 +1332,12 @@ impl PiCircuitConfig { || Value::known(F::zero()), )?; } + region.assign_fixed( + || "tag of first row of block table", + self.block_table.tag, + offset, + || Value::known(F::from(BlockContextFieldTag::Null as u64)), + )?; for column in block_table_columns .iter() .chain(iter::once(&self.cum_num_txs)) @@ -1290,16 +1354,16 @@ impl PiCircuitConfig { let mut cum_num_txs = 0usize; let mut block_value_cells = vec![]; let block_ctxs = &public_data.block_ctxs; + let num_txs_in_blocks = public_data.get_num_txs(); for block_ctx in block_ctxs.ctxs.values().cloned().chain( (block_ctxs.ctxs.len()..max_inner_blocks) .into_iter() .map(|_| BlockContext::padding(public_data.chain_id)), ) { - let num_txs = public_data - .transactions - .iter() - .filter(|tx| tx.block_number == block_ctx.number.as_u64()) - .count(); + let num_txs = num_txs_in_blocks + .get(&block_ctx.number.as_u64()) + .cloned() + .unwrap(); let tag = [ Coinbase, Timestamp, Number, Difficulty, GasLimit, BaseFee, ChainId, NumTxs, CumNumTxs, @@ -1363,10 +1427,12 @@ impl PiCircuitConfig { )?; } if *tag == CumNumTxs { + // only increase cum_num_txs when the block_table.tag = CumNumTxs cum_num_txs_field = F::from(cum_num_txs as u64); } if offset == 1 { assert_eq!(cum_num_txs_field, F::zero()); + // use copy constraint to make sure that cum_num_txs starts with 0 region.assign_advice_from_constant( || "cum_num_txs", self.cum_num_txs, @@ -1414,6 +1480,7 @@ impl PiCircuit { let chain_id = block.chain_id; let public_data = PublicData { chain_id, + start_l1_queue_index: block.start_l1_queue_index, transactions: block.txs.clone(), block_ctxs: block.context.clone(), prev_state_root: H256(block.mpt_updates.old_root().to_be_bytes()), diff --git a/zkevm-circuits/src/witness/block.rs b/zkevm-circuits/src/witness/block.rs index 7e6976acdf..a7d6013680 100644 --- a/zkevm-circuits/src/witness/block.rs +++ b/zkevm-circuits/src/witness/block.rs @@ -65,6 +65,8 @@ pub struct Block { pub mpt_updates: MptUpdates, /// Chain ID pub chain_id: u64, + /// StartL1QueueIndex + pub start_l1_queue_index: u64, /// IO to/from precompile calls. pub precompile_events: PrecompileEvents, } @@ -458,10 +460,22 @@ pub fn block_convert( keccak_inputs: circuit_input_builder::keccak_inputs(block, code_db)?, mpt_updates, chain_id, + start_l1_queue_index: 0, precompile_events: block.precompile_events.clone(), }) } +pub fn block_convert_with_l1_queue_index( + block: &circuit_input_builder::Block, + code_db: &bus_mapping::state_db::CodeDB, + start_l1_queue_index: u64, +) -> Result, Error> { + let mut block = block_convert(block, code_db)?; + block.start_l1_queue_index = start_l1_queue_index; + + Ok(block) +} + /// Attach witness block with mpt states pub fn block_apply_mpt_state(block: &mut Block, mpt_state: &MptState) { block.mpt_updates.fill_state_roots(mpt_state); From d0de5c5ea993642a997140a63a150de802ed37d9 Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Sat, 12 Aug 2023 18:43:42 +0800 Subject: [PATCH 02/10] do not copy num_txs to block table --- zkevm-circuits/src/pi_circuit.rs | 44 ++++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/zkevm-circuits/src/pi_circuit.rs b/zkevm-circuits/src/pi_circuit.rs index 70af2e24fb..ad0d0614f3 100644 --- a/zkevm-circuits/src/pi_circuit.rs +++ b/zkevm-circuits/src/pi_circuit.rs @@ -55,7 +55,6 @@ use crate::{ }, util::rlc_be_bytes, }; -use eth_types::geth_types::TxType::L1Msg; use halo2_proofs::circuit::{Cell, RegionIndex}; #[cfg(any(feature = "test", test, feature = "test-circuits"))] use halo2_proofs::{circuit::SimpleFloorPlanner, plonk::Circuit}; @@ -100,25 +99,20 @@ impl Default for PublicData { } impl PublicData { - fn get_num_txs(&self) -> BTreeMap { + fn get_num_txs(&self) -> BTreeMap { let mut num_txs_in_blocks = BTreeMap::new(); // short for total number of l1 msgs popped before let mut total_l1_popped = self.start_l1_queue_index; - for &block_num in self - .block_ctxs - .ctxs - .iter() - .map(|(block_num, ctx)| block_num) - { + for &block_num in self.block_ctxs.ctxs.iter().map(|(block_num, _)| block_num) { let num_l2_txs = self .transactions .iter() - .filter(|tx| !tx.tx_type.is_l1_msg() && tx.block_number == *block_num) - .count(); + .filter(|tx| !tx.tx_type.is_l1_msg() && tx.block_number == block_num) + .count() as u64; let num_l1_msgs = self .transactions .iter() - .filter(|tx| tx.tx_type.is_l1_msg() && tx.block_number == *block_num) + .filter(|tx| tx.tx_type.is_l1_msg() && tx.block_number == block_num) // tx.nonce alias for queue_index for l1 msg tx .map(|tx| tx.nonce) .max() @@ -149,7 +143,7 @@ impl PublicData { let num_txs = num_txs_in_blocks .get(block_num) .cloned() - .expect(format!("get num_txs in block {block_num}").as_str()) + .unwrap_or_else(|| panic!("get num_txs in block {block_num}")) as u16; iter::empty() // Block Values @@ -697,7 +691,7 @@ impl PiCircuitConfig { let num_txs = num_txs_in_blocks .get(&block_num) .cloned() - .expect(format!("get num_txs in block {block_num}").as_str()) + .unwrap_or_else(|| panic!("get num_txs in block {block_num}")) as u16; // Assign fields in pi columns and connect them to block table @@ -726,10 +720,14 @@ impl PiCircuitConfig { false, challenges, )?; - block_copy_cells.push(( - cells[RPI_CELL_IDX].clone(), - block_table_offset + block_offset, - )); + // do not copy num_txs to block table as the meaning of num_txs + // in block table is len(block.txs), and this is different from num_l1_msgs + num_l2_txs + if block_offset != NUM_TXS_OFFSET { + block_copy_cells.push(( + cells[RPI_CELL_IDX].clone(), + block_table_offset + block_offset, + )); + } } block_table_offset += BLOCK_LEN; @@ -1354,16 +1352,18 @@ impl PiCircuitConfig { let mut cum_num_txs = 0usize; let mut block_value_cells = vec![]; let block_ctxs = &public_data.block_ctxs; - let num_txs_in_blocks = public_data.get_num_txs(); + // let num_txs_in_blocks = public_data.get_num_txs(); for block_ctx in block_ctxs.ctxs.values().cloned().chain( (block_ctxs.ctxs.len()..max_inner_blocks) .into_iter() .map(|_| BlockContext::padding(public_data.chain_id)), ) { - let num_txs = num_txs_in_blocks - .get(&block_ctx.number.as_u64()) - .cloned() - .unwrap(); + // note that + let num_txs = public_data + .transactions + .iter() + .filter(|tx| tx.block_number == block_ctx.number.as_u64()) + .count(); let tag = [ Coinbase, Timestamp, Number, Difficulty, GasLimit, BaseFee, ChainId, NumTxs, CumNumTxs, From 59f77cc76c3b2a3d2cd12006d44364253b3666b9 Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Sat, 12 Aug 2023 19:23:35 +0800 Subject: [PATCH 03/10] fix --- bus-mapping/src/circuit_input_builder.rs | 21 +++++++++--- .../src/circuit_input_builder/block.rs | 32 +++++++++++++++++++ zkevm-circuits/src/pi_circuit.rs | 23 +++++++------ 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/bus-mapping/src/circuit_input_builder.rs b/bus-mapping/src/circuit_input_builder.rs index d313459fb0..e4f4965c28 100644 --- a/bus-mapping/src/circuit_input_builder.rs +++ b/bus-mapping/src/circuit_input_builder.rs @@ -644,6 +644,7 @@ pub fn keccak_inputs(block: &Block, code_db: &CodeDB) -> Result>, Er // PI circuit keccak_inputs.extend(keccak_inputs_pi_circuit( block.chain_id, + block.start_l1_queue_index, block.prev_state_root, block.withdraw_root, &block.headers, @@ -736,17 +737,29 @@ pub fn get_dummy_tx_hash() -> H256 { fn keccak_inputs_pi_circuit( chain_id: u64, + start_l1_queue_index: u64, prev_state_root: Word, withdraw_trie_root: Word, block_headers: &BTreeMap, transactions: &[Transaction], ) -> Vec> { + let mut total_l1_popped = start_l1_queue_index; let data_bytes = iter::empty() - .chain(block_headers.iter().flat_map(|(block_num, block)| { - let num_txs = transactions + .chain(block_headers.iter().flat_map(|(&block_num, block)| { + let num_l2_txs = transactions .iter() - .filter(|tx| tx.block_num == *block_num) - .count() as u16; + .filter(|tx| !tx.tx_type.is_l1_msg() && tx.block_num == block_num) + .count() as u64; + let num_l1_msgs = transactions + .iter() + .filter(|tx| tx.tx_type.is_l1_msg() && tx.block_num == block_num) + // tx.nonce alias for queue_index for l1 msg tx + .map(|tx| tx.nonce) + .max() + .map_or(0, |max_queue_index| max_queue_index - total_l1_popped + 1); + total_l1_popped += num_l1_msgs; + + let num_txs = num_l2_txs + num_l1_msgs; iter::empty() // Block Values diff --git a/bus-mapping/src/circuit_input_builder/block.rs b/bus-mapping/src/circuit_input_builder/block.rs index 99f6882845..b0fc8159f8 100644 --- a/bus-mapping/src/circuit_input_builder/block.rs +++ b/bus-mapping/src/circuit_input_builder/block.rs @@ -163,6 +163,8 @@ pub struct Block { pub circuits_params: CircuitsParams, /// chain id pub chain_id: u64, + /// start_l1_queue_index + pub start_l1_queue_index: u64, /// IO to/from the precompiled contract calls. pub precompile_events: PrecompileEvents, } @@ -217,6 +219,36 @@ impl Block { Ok(block) } + /// Create a new block. + pub fn new_with_l1_queue_index( + chain_id: u64, + start_l1_queue_index: u64, + history_hashes: Vec, + eth_block: ð_types::Block, + circuits_params: CircuitsParams, + ) -> Result { + let mut block = Self { + block_steps: BlockSteps { + end_block_not_last: ExecStep { + exec_state: ExecState::EndBlock, + ..ExecStep::default() + }, + end_block_last: ExecStep { + exec_state: ExecState::EndBlock, + ..ExecStep::default() + }, + }, + exp_events: Vec::new(), + chain_id, + start_l1_queue_index, + circuits_params, + ..Default::default() + }; + let info = BlockHead::new(chain_id, history_hashes, eth_block)?; + block.headers.insert(info.number.as_u64(), info); + Ok(block) + } + /// Return the list of transactions of this block. pub fn txs(&self) -> &[Transaction] { &self.txs diff --git a/zkevm-circuits/src/pi_circuit.rs b/zkevm-circuits/src/pi_circuit.rs index ad0d0614f3..7afde5e679 100644 --- a/zkevm-circuits/src/pi_circuit.rs +++ b/zkevm-circuits/src/pi_circuit.rs @@ -103,7 +103,7 @@ impl PublicData { let mut num_txs_in_blocks = BTreeMap::new(); // short for total number of l1 msgs popped before let mut total_l1_popped = self.start_l1_queue_index; - for &block_num in self.block_ctxs.ctxs.iter().map(|(block_num, _)| block_num) { + for &block_num in self.block_ctxs.ctxs.keys() { let num_l2_txs = self .transactions .iter() @@ -583,11 +583,13 @@ impl SubCircuitConfig for PiCircuitConfig { meta.query_advice(cum_num_txs, Rotation::cur()) + num_txs, ); - cb.require_equal( - "block_table.value' == cum_num_txs' if block_table.tag == Nums", - meta.query_advice(block_table.value, Rotation::next()), - meta.query_advice(cum_num_txs, Rotation::next()), - ); + cb.condition(meta.query_fixed(is_block_num_txs, Rotation::cur()), |cb| { + cb.require_equal( + "block_table.value' == cum_num_txs' if block_table.tag == Nums", + meta.query_advice(block_table.value, Rotation::next()), + meta.query_advice(cum_num_txs, Rotation::next()), + ); + }); // NOTE: cum_num_txs is already enforced to start with 0 using copy constraint. @@ -688,11 +690,7 @@ impl PiCircuitConfig { { let is_rpi_padding = i >= block_values.ctxs.len(); let block_num = block.number.as_u64(); - let num_txs = num_txs_in_blocks - .get(&block_num) - .cloned() - .unwrap_or_else(|| panic!("get num_txs in block {block_num}")) - as u16; + let num_txs = num_txs_in_blocks.get(&block_num).cloned().unwrap_or(0) as u16; // Assign fields in pi columns and connect them to block table let fields = vec![ @@ -721,7 +719,8 @@ impl PiCircuitConfig { challenges, )?; // do not copy num_txs to block table as the meaning of num_txs - // in block table is len(block.txs), and this is different from num_l1_msgs + num_l2_txs + // in block table is len(block.txs), and this is different from num_l1_msgs + + // num_l2_txs if block_offset != NUM_TXS_OFFSET { block_copy_cells.push(( cells[RPI_CELL_IDX].clone(), From 4ea5cc995909035daa579ef2ecedf4dc4c4a2f08 Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Sat, 12 Aug 2023 19:59:50 +0800 Subject: [PATCH 04/10] export two api public --- .../src/circuit_input_builder/block.rs | 40 +++++++++++++++++++ zkevm-circuits/src/witness.rs | 5 ++- zkevm-circuits/src/witness/block.rs | 1 + 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/bus-mapping/src/circuit_input_builder/block.rs b/bus-mapping/src/circuit_input_builder/block.rs index b0fc8159f8..8256e70885 100644 --- a/bus-mapping/src/circuit_input_builder/block.rs +++ b/bus-mapping/src/circuit_input_builder/block.rs @@ -131,6 +131,46 @@ impl BlockHead { eth_block: eth_block.clone(), }) } + + /// Create a new block. + pub fn new_with_l1_queue_index( + chain_id: u64, + history_hashes: Vec, + eth_block: ð_types::Block, + ) -> Result { + if eth_block.base_fee_per_gas.is_none() { + // FIXME: resolve this once we have proper EIP-1559 support + log::debug!( + "This does not look like a EIP-1559 block - base_fee_per_gas defaults to zero" + ); + } + + Ok(Self { + chain_id, + history_hashes, + coinbase: eth_block + .author + .ok_or(Error::EthTypeError(eth_types::Error::IncompleteBlock))?, + gas_limit: eth_block.gas_limit.low_u64(), + number: eth_block + .number + .ok_or(Error::EthTypeError(eth_types::Error::IncompleteBlock))? + .low_u64() + .into(), + timestamp: eth_block.timestamp, + difficulty: if eth_block.difficulty.is_zero() { + eth_block + .mix_hash + .unwrap_or_default() + .to_fixed_bytes() + .into() + } else { + eth_block.difficulty + }, + base_fee: eth_block.base_fee_per_gas.unwrap_or_default(), + eth_block: eth_block.clone(), + }) + } } /// Circuit Input related to a block. diff --git a/zkevm-circuits/src/witness.rs b/zkevm-circuits/src/witness.rs index 3dfb446485..da94347026 100644 --- a/zkevm-circuits/src/witness.rs +++ b/zkevm-circuits/src/witness.rs @@ -3,7 +3,10 @@ //! used to generate witnesses for circuits. mod block; -pub use block::{block_apply_mpt_state, block_convert, Block, BlockContext, BlockContexts}; +pub use block::{ + block_apply_mpt_state, block_convert, block_convert_with_l1_queue_index, Block, BlockContext, + BlockContexts, +}; mod bytecode; pub use bytecode::Bytecode; diff --git a/zkevm-circuits/src/witness/block.rs b/zkevm-circuits/src/witness/block.rs index a7d6013680..f117384fb7 100644 --- a/zkevm-circuits/src/witness/block.rs +++ b/zkevm-circuits/src/witness/block.rs @@ -465,6 +465,7 @@ pub fn block_convert( }) } +/// Convert a block struct in bus-mapping to a witness block used in circuits pub fn block_convert_with_l1_queue_index( block: &circuit_input_builder::Block, code_db: &bus_mapping::state_db::CodeDB, From 90a781d10cd0f4fa6d88a9405d7cff1dfcc090c2 Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Sat, 12 Aug 2023 20:08:51 +0800 Subject: [PATCH 05/10] add log --- zkevm-circuits/src/pi_circuit.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zkevm-circuits/src/pi_circuit.rs b/zkevm-circuits/src/pi_circuit.rs index 7afde5e679..07688f080b 100644 --- a/zkevm-circuits/src/pi_circuit.rs +++ b/zkevm-circuits/src/pi_circuit.rs @@ -195,6 +195,8 @@ impl PublicData { fn get_pi(&self) -> H256 { let data_hash = H256(keccak256(self.data_bytes())); + log::debug!("data hash: {}", hex::encode(&data_hash.to_fixed_bytes())); + let pi_bytes = self.pi_bytes(data_hash); let pi_hash = keccak256(pi_bytes); From 629a12edec3ca58a6614909b63c5eec74a82ad12 Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Sat, 12 Aug 2023 20:29:31 +0800 Subject: [PATCH 06/10] add more log --- bus-mapping/src/circuit_input_builder.rs | 14 +++++++++++++- zkevm-circuits/src/pi_circuit.rs | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/bus-mapping/src/circuit_input_builder.rs b/bus-mapping/src/circuit_input_builder.rs index e4f4965c28..f790e608f9 100644 --- a/bus-mapping/src/circuit_input_builder.rs +++ b/bus-mapping/src/circuit_input_builder.rs @@ -744,6 +744,10 @@ fn keccak_inputs_pi_circuit( transactions: &[Transaction], ) -> Vec> { let mut total_l1_popped = start_l1_queue_index; + log::debug!( + "start_l1_queue_index in keccak_inputs: {}", + start_l1_queue_index + ); let data_bytes = iter::empty() .chain(block_headers.iter().flat_map(|(&block_num, block)| { let num_l2_txs = transactions @@ -759,7 +763,15 @@ fn keccak_inputs_pi_circuit( .map_or(0, |max_queue_index| max_queue_index - total_l1_popped + 1); total_l1_popped += num_l1_msgs; - let num_txs = num_l2_txs + num_l1_msgs; + let num_txs = (num_l2_txs + num_l1_msgs) as u16; + log::debug!( + "[block {}] total_l1_popped: {}, num_l1_msgs: {}, num_l2_txs: {}, num_txs: {}", + block_num, + total_l1_popped, + num_l1_msgs, + num_l2_txs, + num_txs, + ); iter::empty() // Block Values diff --git a/zkevm-circuits/src/pi_circuit.rs b/zkevm-circuits/src/pi_circuit.rs index 07688f080b..8783593a3d 100644 --- a/zkevm-circuits/src/pi_circuit.rs +++ b/zkevm-circuits/src/pi_circuit.rs @@ -103,6 +103,7 @@ impl PublicData { let mut num_txs_in_blocks = BTreeMap::new(); // short for total number of l1 msgs popped before let mut total_l1_popped = self.start_l1_queue_index; + log::debug!("start_l1_queue_index: {}", total_l1_popped); for &block_num in self.block_ctxs.ctxs.keys() { let num_l2_txs = self .transactions @@ -693,6 +694,7 @@ impl PiCircuitConfig { let is_rpi_padding = i >= block_values.ctxs.len(); let block_num = block.number.as_u64(); let num_txs = num_txs_in_blocks.get(&block_num).cloned().unwrap_or(0) as u16; + log::debug!("num_txs in block {}: {}", block_num, num_txs); // Assign fields in pi columns and connect them to block table let fields = vec![ From 11d5efa8e3722d77381ca393b8008f5dd5c63813 Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Sat, 12 Aug 2023 20:47:20 +0800 Subject: [PATCH 07/10] fix start_l1_queue_index import --- bus-mapping/src/circuit_input_builder.rs | 4 ++++ bus-mapping/src/circuit_input_builder/block.rs | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/bus-mapping/src/circuit_input_builder.rs b/bus-mapping/src/circuit_input_builder.rs index f790e608f9..f7010ac5be 100644 --- a/bus-mapping/src/circuit_input_builder.rs +++ b/bus-mapping/src/circuit_input_builder.rs @@ -785,6 +785,10 @@ fn keccak_inputs_pi_circuit( .chain(transactions.iter().flat_map(|tx| tx.hash.to_fixed_bytes())) .collect::>(); let data_hash = H256(keccak256(&data_bytes)); + log::debug!( + "chunk data hash: {}", + hex::encode(data_hash.to_fixed_bytes()) + ); let after_state_root = block_headers .last_key_value() .map(|(_, blk)| blk.eth_block.state_root) diff --git a/bus-mapping/src/circuit_input_builder/block.rs b/bus-mapping/src/circuit_input_builder/block.rs index 8256e70885..461b37b52e 100644 --- a/bus-mapping/src/circuit_input_builder/block.rs +++ b/bus-mapping/src/circuit_input_builder/block.rs @@ -88,6 +88,8 @@ pub struct BlockHead { pub difficulty: Word, /// base fee pub base_fee: Word, + /// start l1 queue index + pub start_l1_queue_index: u64, /// Original block from geth pub eth_block: eth_types::Block, } @@ -108,6 +110,7 @@ impl BlockHead { Ok(Self { chain_id, history_hashes, + start_l1_queue_index: 0, coinbase: eth_block .author .ok_or(Error::EthTypeError(eth_types::Error::IncompleteBlock))?, @@ -135,6 +138,7 @@ impl BlockHead { /// Create a new block. pub fn new_with_l1_queue_index( chain_id: u64, + start_l1_queue_index: u64, history_hashes: Vec, eth_block: ð_types::Block, ) -> Result { @@ -148,6 +152,7 @@ impl BlockHead { Ok(Self { chain_id, history_hashes, + start_l1_queue_index, coinbase: eth_block .author .ok_or(Error::EthTypeError(eth_types::Error::IncompleteBlock))?, From 857b519fa7ada52a557c02b99af40312b1187b56 Mon Sep 17 00:00:00 2001 From: Steven Gu Date: Sat, 12 Aug 2023 21:16:45 +0800 Subject: [PATCH 08/10] Update `ChunkHash::from_witness_block`. --- aggregator/src/chunk.rs | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/aggregator/src/chunk.rs b/aggregator/src/chunk.rs index 99899b3404..3f9d9260ba 100644 --- a/aggregator/src/chunk.rs +++ b/aggregator/src/chunk.rs @@ -35,13 +35,38 @@ impl ChunkHash { pub fn from_witness_block(block: &Block, is_padding: bool) -> Self { // + let mut total_l1_popped = block.start_l1_queue_index; + log::debug!( + "ChunkHash::from_witness_block: start_l1_queue_index = {}", + total_l1_popped + ); let data_bytes = iter::empty() + // .chain(block_headers.iter().flat_map(|(&block_num, block)| { .chain(block.context.ctxs.iter().flat_map(|(b_num, b_ctx)| { - let num_txs = block + let num_l2_txs = block + .txs + .iter() + .filter(|tx| !tx.tx_type.is_l1_msg() && tx.block_number == *b_num) + .count() as u64; + let num_l1_msgs = block .txs .iter() - .filter(|tx| tx.block_number == *b_num) - .count() as u16; + .filter(|tx| tx.tx_type.is_l1_msg() && tx.block_number == *b_num) + // tx.nonce alias for queue_index for l1 msg tx + .map(|tx| tx.nonce) + .max() + .map_or(0, |max_queue_index| max_queue_index - total_l1_popped + 1); + total_l1_popped += num_l1_msgs; + + let num_txs = (num_l2_txs + num_l1_msgs) as u16; + log::debug!( + "ChunkHash::from_witness_block: [block {}] total_l1_popped = {}, num_l1_msgs = {}, num_l2_txs = {}, num_txs = {}", + b_num, + total_l1_popped, + num_l1_msgs, + num_l2_txs, + num_txs, + ); iter::empty() // Block Values @@ -55,7 +80,7 @@ impl ChunkHash { .chain(block.txs.iter().flat_map(|tx| tx.hash.to_fixed_bytes())) .collect::>(); - let data_hash = H256(keccak256(data_bytes)); + let data_hash = H256(keccak256(&data_bytes)); let post_state_root = block .context From ce4151f82b22f34ac29775f2f30e3c29974ea7e2 Mon Sep 17 00:00:00 2001 From: Steven Gu Date: Sat, 12 Aug 2023 21:52:06 +0800 Subject: [PATCH 09/10] Fix to pass `start_l1_queue_index`. --- bus-mapping/src/circuit_input_builder/block.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bus-mapping/src/circuit_input_builder/block.rs b/bus-mapping/src/circuit_input_builder/block.rs index 461b37b52e..4f5caf5d42 100644 --- a/bus-mapping/src/circuit_input_builder/block.rs +++ b/bus-mapping/src/circuit_input_builder/block.rs @@ -289,7 +289,12 @@ impl Block { circuits_params, ..Default::default() }; - let info = BlockHead::new(chain_id, history_hashes, eth_block)?; + let info = BlockHead::new_with_l1_queue_index( + chain_id, + start_l1_queue_index, + history_hashes, + eth_block, + )?; block.headers.insert(info.number.as_u64(), info); Ok(block) } From fc91d64cd28abcc3fef4c0c3563cb4ed40839cbe Mon Sep 17 00:00:00 2001 From: Steven Gu Date: Sat, 12 Aug 2023 21:57:45 +0800 Subject: [PATCH 10/10] Update logs and fix lint. --- Cargo.lock | 1 + aggregator/Cargo.toml | 1 + aggregator/src/chunk.rs | 13 +++++++------ zkevm-circuits/src/pi_circuit.rs | 2 +- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c1b03daa7..66bc8de4c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,6 +38,7 @@ dependencies = [ "eth-types", "ethers-core", "halo2_proofs", + "hex", "itertools", "log", "rand", diff --git a/aggregator/Cargo.toml b/aggregator/Cargo.toml index b6cf215506..3af735fa22 100644 --- a/aggregator/Cargo.toml +++ b/aggregator/Cargo.toml @@ -13,6 +13,7 @@ zkevm-circuits = { path = "../zkevm-circuits" } ark-std = "0.3.0" env_logger = "0.10.0" ethers-core = "0.17.0" +hex = "0.4.3" log = "0.4" itertools = "0.10.3" serde = { version = "1.0", features = ["derive"] } diff --git a/aggregator/src/chunk.rs b/aggregator/src/chunk.rs index 3f9d9260ba..c22cd97db1 100644 --- a/aggregator/src/chunk.rs +++ b/aggregator/src/chunk.rs @@ -36,10 +36,7 @@ impl ChunkHash { // let mut total_l1_popped = block.start_l1_queue_index; - log::debug!( - "ChunkHash::from_witness_block: start_l1_queue_index = {}", - total_l1_popped - ); + log::debug!("chunk-hash: start_l1_queue_index = {}", total_l1_popped); let data_bytes = iter::empty() // .chain(block_headers.iter().flat_map(|(&block_num, block)| { .chain(block.context.ctxs.iter().flat_map(|(b_num, b_ctx)| { @@ -60,7 +57,7 @@ impl ChunkHash { let num_txs = (num_l2_txs + num_l1_msgs) as u16; log::debug!( - "ChunkHash::from_witness_block: [block {}] total_l1_popped = {}, num_l1_msgs = {}, num_l2_txs = {}, num_txs = {}", + "chunk-hash: [block {}] total_l1_popped = {}, num_l1_msgs = {}, num_l2_txs = {}, num_txs = {}", b_num, total_l1_popped, num_l1_msgs, @@ -80,7 +77,11 @@ impl ChunkHash { .chain(block.txs.iter().flat_map(|tx| tx.hash.to_fixed_bytes())) .collect::>(); - let data_hash = H256(keccak256(&data_bytes)); + let data_hash = H256(keccak256(data_bytes)); + log::debug!( + "chunk-hash: data hash = {}", + hex::encode(data_hash.to_fixed_bytes()) + ); let post_state_root = block .context diff --git a/zkevm-circuits/src/pi_circuit.rs b/zkevm-circuits/src/pi_circuit.rs index 8783593a3d..84c2b65153 100644 --- a/zkevm-circuits/src/pi_circuit.rs +++ b/zkevm-circuits/src/pi_circuit.rs @@ -196,7 +196,7 @@ impl PublicData { fn get_pi(&self) -> H256 { let data_hash = H256(keccak256(self.data_bytes())); - log::debug!("data hash: {}", hex::encode(&data_hash.to_fixed_bytes())); + log::debug!("data hash: {}", hex::encode(data_hash.to_fixed_bytes())); let pi_bytes = self.pi_bytes(data_hash); let pi_hash = keccak256(pi_bytes);