Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.

feat: add AccessListGasCost to fix begin-tx gas cost (EIP 2930 optional-access-list) #1041

Merged
merged 2 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions bus-mapping/src/evm/opcodes/begin_end_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -186,13 +189,15 @@ pub fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep,

// Calculate intrinsic gas cost
let call_data_gas_cost = tx_data_gas_cost(&state.tx.input);
let access_list_gas_cost = tx_access_list_gas_cost(&state.tx.access_list);
let intrinsic_gas_cost = if state.tx.is_create() {
GasCost::CREATION_TX.as_u64()
} else {
GasCost::TX.as_u64()
} + call_data_gas_cost
+ access_list_gas_cost
+ init_code_gas_cost;
log::trace!("intrinsic_gas_cost {intrinsic_gas_cost}, call_data_gas_cost {call_data_gas_cost}, init_code_gas_cost {init_code_gas_cost}, exec_step.gas_cost {:?}", exec_step.gas_cost);
log::trace!("intrinsic_gas_cost {intrinsic_gas_cost}, call_data_gas_cost {call_data_gas_cost}, access_list_gas_cost {access_list_gas_cost}, init_code_gas_cost {init_code_gas_cost}, exec_step.gas_cost {:?}", exec_step.gas_cost);
exec_step.gas_cost = GasCost(intrinsic_gas_cost);

// Get code_hash of callee account
Expand Down
4 changes: 4 additions & 0 deletions eth-types/src/evm_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ impl GasCost {
pub const PRECOMPILE_MODEXP_MIN: Self = Self(200);
/// Base gas cost for precompile call: BLAKE2F
pub const PRECOMPILE_BLAKE2F: Self = Self(0);
/// Gas cost per address in tx access list (EIP 2930)
pub const ACCESS_LIST_PER_ADDRESS: Self = Self(2400);
/// Gas cost per storage key in tx access list (EIP 2930)
pub const ACCESS_LIST_PER_STORAGE_KEY: Self = Self(1900);
}

impl GasCost {
Expand Down
14 changes: 13 additions & 1 deletion eth-types/src/evm_types/gas_utils.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Utility functions to help calculate gas

use super::GasCost;
use crate::Word;
use crate::{AccessList, Word};

/// Calculate memory expansion gas cost by current and next memory word size.
pub fn memory_expansion_gas_cost(curr_memory_word_size: u64, next_memory_word_size: u64) -> u64 {
Expand Down Expand Up @@ -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<AccessList>) -> 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()
Expand Down
12 changes: 11 additions & 1 deletion zkevm-circuits/src/evm_circuit/execution/begin_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ pub(crate) struct BeginTxGadget<F> {
is_call_data_empty: IsZeroGadget<F>,
tx_call_data_word_length: ConstantDivisionGadget<F, N_BYTES_U64>,
tx_call_data_gas_cost: Cell<F>,
// The gas cost for access list (EIP 2930)
access_list_gas_cost: Cell<F>,
// The gas cost for rlp-encoded bytes of unsigned tx
tx_data_gas_cost: Cell<F>,
reversion_info: ReversionInfo<F>,
Expand Down Expand Up @@ -104,7 +106,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
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,
Expand All @@ -113,6 +115,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
TxContextFieldTag::IsCreate,
TxContextFieldTag::CallDataLength,
TxContextFieldTag::CallDataGasCost,
TxContextFieldTag::AccessListGasCost,
TxContextFieldTag::TxDataGasCost,
]
.map(|field_tag| cb.tx_context(tx_id.expr(), field_tag, None));
Expand Down Expand Up @@ -255,6 +258,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
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,
)
});
Expand Down Expand Up @@ -689,6 +693,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
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,
Expand Down Expand Up @@ -916,6 +921,11 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
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(
Expand Down
2 changes: 2 additions & 0 deletions zkevm-circuits/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 15 additions & 6 deletions zkevm-circuits/src/tx_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -331,6 +331,7 @@ impl<F: Field> SubCircuitConfig<F> for TxCircuitConfig<F> {
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);
Expand Down Expand Up @@ -466,6 +467,7 @@ impl<F: Field> SubCircuitConfig<F> for TxCircuitConfig<F> {
(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),
Expand Down Expand Up @@ -557,6 +559,8 @@ impl<F: Field> SubCircuitConfig<F> for TxCircuitConfig<F> {
cb.gate(meta.query_fixed(q_enable, Rotation::cur()))
});

// TODO: add constraints for AccessListGasCost.

//////////////////////////////////////////////////////////
///// Constraints for booleans that reducing degree /////
//////////////////////////////////////////////////////////
Expand Down Expand Up @@ -1835,6 +1839,11 @@ impl<F: Field> TxCircuitConfig<F> {
None,
Value::known(F::from(tx.call_data_gas_cost)),
),
(
AccessListGasCost,
None,
Value::known(F::from(tx.access_list_gas_cost)),
),
(
TxDataGasCost,
Some(RlpTableInputValue {
Expand Down
12 changes: 11 additions & 1 deletion zkevm-circuits/src/witness/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)),
Expand Down Expand Up @@ -858,6 +866,7 @@ impl From<MockTransaction> 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,
Expand Down Expand Up @@ -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(),
Expand Down