From 8e0fd2e97a3c6dc8807d3b5f3312a0360d6b2304 Mon Sep 17 00:00:00 2001 From: Steven Date: Wed, 22 Nov 2023 12:04:51 +0800 Subject: [PATCH] Add `AccessListGasCost` to `TxContextFieldTag`. (#1041) --- bus-mapping/src/evm/opcodes/begin_end_tx.rs | 9 ++++++-- eth-types/src/evm_types.rs | 4 ++++ eth-types/src/evm_types/gas_utils.rs | 14 ++++++++++++- .../src/evm_circuit/execution/begin_tx.rs | 12 ++++++++++- zkevm-circuits/src/table.rs | 2 ++ zkevm-circuits/src/tx_circuit.rs | 21 +++++++++++++------ zkevm-circuits/src/witness/tx.rs | 12 ++++++++++- 7 files changed, 63 insertions(+), 11 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/begin_end_tx.rs b/bus-mapping/src/evm/opcodes/begin_end_tx.rs index da6012239e..85033db03d 100644 --- a/bus-mapping/src/evm/opcodes/begin_end_tx.rs +++ b/bus-mapping/src/evm/opcodes/begin_end_tx.rs @@ -12,7 +12,10 @@ use crate::{ }; use core::fmt::Debug; use eth_types::{ - evm_types::{gas_utils::tx_data_gas_cost, GasCost, MAX_REFUND_QUOTIENT_OF_GAS_USED}, + evm_types::{ + gas_utils::{tx_access_list_gas_cost, tx_data_gas_cost}, + GasCost, MAX_REFUND_QUOTIENT_OF_GAS_USED, + }, Bytecode, ToWord, Word, }; use ethers_core::utils::get_contract_address; @@ -186,13 +189,15 @@ pub fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result u64 { @@ -49,6 +49,18 @@ pub fn eip150_gas(gas_left: u64, gas_specified: Word) -> u64 { capped_gas } +/// Calculate gas cost for access list (EIP 2930). +pub fn tx_access_list_gas_cost(access_list: &Option) -> u64 { + access_list.as_ref().map_or(0, |access_list| { + access_list.0.len() as u64 * GasCost::ACCESS_LIST_PER_ADDRESS.as_u64() + + access_list + .0 + .iter() + .fold(0, |acc, item| acc + item.storage_keys.len() as u64) + * GasCost::ACCESS_LIST_PER_STORAGE_KEY.as_u64() + }) +} + /// Calculate gas cost for transaction data. pub fn tx_data_gas_cost(data: &[u8]) -> u64 { data.iter() diff --git a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs index d52a49f43c..b7f9883577 100644 --- a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs +++ b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs @@ -60,6 +60,8 @@ pub(crate) struct BeginTxGadget { is_call_data_empty: IsZeroGadget, tx_call_data_word_length: ConstantDivisionGadget, tx_call_data_gas_cost: Cell, + // The gas cost for access list (EIP 2930) + access_list_gas_cost: Cell, // The gas cost for rlp-encoded bytes of unsigned tx tx_data_gas_cost: Cell, reversion_info: ReversionInfo, @@ -104,7 +106,7 @@ impl ExecutionGadget for BeginTxGadget { let tx_id = cb.query_cell(); let sender_nonce = cb.query_cell(); - let [tx_nonce, tx_gas, tx_caller_address, tx_callee_address, tx_is_create, tx_call_data_length, tx_call_data_gas_cost, tx_data_gas_cost] = + let [tx_nonce, tx_gas, tx_caller_address, tx_callee_address, tx_is_create, tx_call_data_length, tx_call_data_gas_cost, access_list_gas_cost, tx_data_gas_cost] = [ TxContextFieldTag::Nonce, TxContextFieldTag::Gas, @@ -113,6 +115,7 @@ impl ExecutionGadget for BeginTxGadget { TxContextFieldTag::IsCreate, TxContextFieldTag::CallDataLength, TxContextFieldTag::CallDataGasCost, + TxContextFieldTag::AccessListGasCost, TxContextFieldTag::TxDataGasCost, ] .map(|field_tag| cb.tx_context(tx_id.expr(), field_tag, None)); @@ -255,6 +258,7 @@ impl ExecutionGadget for BeginTxGadget { eth_types::evm_types::GasCost::CREATION_TX.expr(), eth_types::evm_types::GasCost::TX.expr(), ) + tx_call_data_gas_cost.expr() + + access_list_gas_cost.expr() + init_code_gas_cost, ) }); @@ -689,6 +693,7 @@ impl ExecutionGadget for BeginTxGadget { is_call_data_empty, tx_call_data_word_length, tx_call_data_gas_cost, + access_list_gas_cost, tx_data_gas_cost, reversion_info, sufficient_gas_left, @@ -916,6 +921,11 @@ impl ExecutionGadget for BeginTxGadget { offset, Value::known(F::from(tx.call_data_gas_cost)), )?; + self.access_list_gas_cost.assign( + region, + offset, + Value::known(F::from(tx.access_list_gas_cost)), + )?; self.tx_data_gas_cost .assign(region, offset, Value::known(F::from(tx.tx_data_gas_cost)))?; self.reversion_info.assign( diff --git a/zkevm-circuits/src/table.rs b/zkevm-circuits/src/table.rs index 561fa90008..acce7d0711 100644 --- a/zkevm-circuits/src/table.rs +++ b/zkevm-circuits/src/table.rs @@ -146,6 +146,8 @@ pub enum TxFieldTag { CallDataLength, /// Gas cost for transaction call data (4 for byte == 0, 16 otherwise) CallDataGasCost, + /// Gas cost for access list (EIP 2930) + AccessListGasCost, /// Gas cost of the transaction data charged in L1 TxDataGasCost, /// Chain ID diff --git a/zkevm-circuits/src/tx_circuit.rs b/zkevm-circuits/src/tx_circuit.rs index a9fa3414ca..8d6f1d4875 100644 --- a/zkevm-circuits/src/tx_circuit.rs +++ b/zkevm-circuits/src/tx_circuit.rs @@ -19,9 +19,9 @@ use crate::{ BlockContextFieldTag::{CumNumTxs, NumAllTxs, NumTxs}, BlockTable, KeccakTable, LookupTable, RlpFsmRlpTable as RlpTable, SigTable, TxFieldTag, TxFieldTag::{ - BlockNumber, CallData, CallDataGasCost, CallDataLength, CallDataRLC, CalleeAddress, - CallerAddress, ChainID, Gas, GasPrice, IsCreate, Nonce, SigR, SigS, SigV, - TxDataGasCost, TxHashLength, TxHashRLC, TxSignHash, TxSignLength, TxSignRLC, + AccessListGasCost, BlockNumber, CallData, CallDataGasCost, CallDataLength, CallDataRLC, + CalleeAddress, CallerAddress, ChainID, Gas, GasPrice, IsCreate, Nonce, SigR, SigS, + SigV, TxDataGasCost, TxHashLength, TxHashRLC, TxSignHash, TxSignLength, TxSignRLC, }, TxTable, U16Table, U8Table, }, @@ -79,11 +79,11 @@ use halo2_proofs::plonk::SecondPhase; use itertools::Itertools; /// Number of rows of one tx occupies in the fixed part of tx table -pub const TX_LEN: usize = 23; +pub const TX_LEN: usize = 24; /// Offset of TxHash tag in the tx table -pub const TX_HASH_OFFSET: usize = 21; +pub const TX_HASH_OFFSET: usize = 22; /// Offset of ChainID tag in the tx table -pub const CHAIN_ID_OFFSET: usize = 12; +pub const CHAIN_ID_OFFSET: usize = 13; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] enum LookupCondition { @@ -331,6 +331,7 @@ impl SubCircuitConfig for TxCircuitConfig { is_tx_tag!(is_data, CallData); is_tx_tag!(is_data_length, CallDataLength); is_tx_tag!(is_data_gas_cost, CallDataGasCost); + is_tx_tag!(is_access_list_gas_cost, AccessListGasCost); is_tx_tag!(is_tx_gas_cost, TxDataGasCost); is_tx_tag!(is_data_rlc, CallDataRLC); is_tx_tag!(is_chain_id_expr, ChainID); @@ -466,6 +467,7 @@ impl SubCircuitConfig for TxCircuitConfig { (is_create(meta), Null), (is_data_length(meta), Null), (is_data_gas_cost(meta), Null), + (is_access_list_gas_cost(meta), Null), (is_sign_hash(meta), Null), (is_hash(meta), Null), (is_data(meta), Null), @@ -557,6 +559,8 @@ impl SubCircuitConfig for TxCircuitConfig { cb.gate(meta.query_fixed(q_enable, Rotation::cur())) }); + // TODO: add constraints for AccessListGasCost. + ////////////////////////////////////////////////////////// ///// Constraints for booleans that reducing degree ///// ////////////////////////////////////////////////////////// @@ -1835,6 +1839,11 @@ impl TxCircuitConfig { None, Value::known(F::from(tx.call_data_gas_cost)), ), + ( + AccessListGasCost, + None, + Value::known(F::from(tx.access_list_gas_cost)), + ), ( TxDataGasCost, Some(RlpTableInputValue { diff --git a/zkevm-circuits/src/witness/tx.rs b/zkevm-circuits/src/witness/tx.rs index f02359dbb5..74506c31f6 100644 --- a/zkevm-circuits/src/witness/tx.rs +++ b/zkevm-circuits/src/witness/tx.rs @@ -17,7 +17,7 @@ use crate::{ }; use bus_mapping::circuit_input_builder::{self, get_dummy_tx_hash, TxL1Fee}; use eth_types::{ - evm_types::gas_utils::tx_data_gas_cost, + evm_types::gas_utils::{tx_access_list_gas_cost, tx_data_gas_cost}, geth_types::{TxType, TxType::PreEip155}, sign_types::{ biguint_to_32bytes_le, ct_option_ok_or, get_dummy_tx, recover_pk2, SignData, SECP256K1_Q, @@ -67,6 +67,8 @@ pub struct Transaction { pub call_data_length: usize, /// The gas cost for transaction call data pub call_data_gas_cost: u64, + /// The gas cost for access list (EIP 2930) + pub access_list_gas_cost: u64, /// The gas cost for rlp-encoded bytes of unsigned tx pub tx_data_gas_cost: u64, /// Chain ID as per EIP-155. @@ -226,6 +228,12 @@ impl Transaction { Value::known(F::zero()), Value::known(F::from(self.call_data_gas_cost)), ], + [ + Value::known(F::from(self.id as u64)), + Value::known(F::from(TxContextFieldTag::AccessListGasCost as u64)), + Value::known(F::zero()), + Value::known(F::from(self.access_list_gas_cost)), + ], [ Value::known(F::from(self.id as u64)), Value::known(F::from(TxContextFieldTag::TxDataGasCost as u64)), @@ -858,6 +866,7 @@ impl From for Transaction { call_data: mock_tx.input.to_vec(), call_data_length: mock_tx.input.len(), call_data_gas_cost: tx_data_gas_cost(&mock_tx.input), + access_list_gas_cost: tx_access_list_gas_cost(&Some(mock_tx.access_list)), tx_data_gas_cost: tx_data_gas_cost(&rlp_signed), chain_id: mock_tx.chain_id, rlp_unsigned, @@ -909,6 +918,7 @@ pub(super) fn tx_convert( call_data: tx.input.clone(), call_data_length: tx.input.len(), call_data_gas_cost: tx_data_gas_cost(&tx.input), + access_list_gas_cost: tx_access_list_gas_cost(&tx.access_list), tx_data_gas_cost: tx_gas_cost, chain_id, rlp_unsigned: tx.rlp_unsigned_bytes.clone(),