From 917d83672a06771bef0d21ce52041f1bcd7587fb Mon Sep 17 00:00:00 2001 From: johntaiko Date: Tue, 8 Aug 2023 08:59:29 +0000 Subject: [PATCH] fix: testcases --- bus-mapping/src/evm/opcodes/begin_end_tx.rs | 14 +-- eth-types/src/geth_types.rs | 8 +- taiko-mock/src/test_ctx.rs | 6 +- taiko-mock/src/transaction.rs | 4 + .../src/evm_circuit/execution/begin_tx.rs | 4 + .../src/evm_circuit/execution/end_tx.rs | 116 +++++++++--------- 6 files changed, 83 insertions(+), 69 deletions(-) diff --git a/bus-mapping/src/evm/opcodes/begin_end_tx.rs b/bus-mapping/src/evm/opcodes/begin_end_tx.rs index f69d0ed71b..9ab4217676 100644 --- a/bus-mapping/src/evm/opcodes/begin_end_tx.rs +++ b/bus-mapping/src/evm/opcodes/begin_end_tx.rs @@ -264,11 +264,13 @@ fn gen_end_tx_steps(state: &mut CircuitInputStateRef) -> Result caller_balance_prev, )?; - let effective_tip = if state.tx_ctx.is_anchor_tx() { + let base_fee = if state.tx_ctx.is_anchor_tx() { 0.into() } else { - state.tx.tx.gas_price - state.block.base_fee + state.block.base_fee }; + + let effective_tip = state.tx.tx.gas_price - base_fee; let (found, coinbase_account) = state.sdb.get_account(&state.block.coinbase); if !found { return Err(Error::AccountNotFound(state.block.coinbase)); @@ -294,12 +296,8 @@ fn gen_end_tx_steps(state: &mut CircuitInputStateRef) -> Result )); } let treasury_balance_prev = treasury_account.balance; - let treasury_balance = treasury_balance_prev - + if state.tx_ctx.is_anchor_tx() { - 0.into() - } else { - state.block.base_fee * (state.tx.gas() - exec_step.gas_left.0) - }; + let treasury_balance = + treasury_balance_prev + base_fee * (state.tx.gas() - exec_step.gas_left.0); state.account_write( &mut exec_step, state.block.protocol_instance.meta_hash.treasury, diff --git a/eth-types/src/geth_types.rs b/eth-types/src/geth_types.rs index e34111de4b..7178ff38cc 100644 --- a/eth-types/src/geth_types.rs +++ b/eth-types/src/geth_types.rs @@ -158,8 +158,8 @@ impl From<&Transaction> for crate::Transaction { gas: tx.gas_limit.to_word(), value: tx.value, gas_price: Some(tx.gas_price), - max_priority_fee_per_gas: Some(tx.gas_fee_cap), - max_fee_per_gas: Some(tx.gas_tip_cap), + max_priority_fee_per_gas: Some(tx.gas_tip_cap), + max_fee_per_gas: Some(tx.gas_fee_cap), input: tx.call_data.clone(), access_list: tx.access_list.clone(), v: tx.v.into(), @@ -179,8 +179,8 @@ impl From<&crate::Transaction> for Transaction { gas_limit: tx.gas.as_u64().into(), value: tx.value, gas_price: tx.gas_price.unwrap_or_default(), - gas_fee_cap: tx.max_priority_fee_per_gas.unwrap_or_default(), - gas_tip_cap: tx.max_fee_per_gas.unwrap_or_default(), + gas_tip_cap: tx.max_priority_fee_per_gas.unwrap_or_default(), + gas_fee_cap: tx.max_fee_per_gas.unwrap_or_default(), call_data: tx.input.clone(), access_list: tx.access_list.clone(), v: tx.v.as_u64(), diff --git a/taiko-mock/src/test_ctx.rs b/taiko-mock/src/test_ctx.rs index 5ba0b96276..03b76246dd 100644 --- a/taiko-mock/src/test_ctx.rs +++ b/taiko-mock/src/test_ctx.rs @@ -1,7 +1,7 @@ //! Mock types and functions to generate Test enviroments for ZKEVM tests use crate::{ - eth, MockAccount, MockBlock, MockTransaction, GOLDEN_TOUCH, MOCK_TAIKO_L2_ADDRESS, + eth, MockAccount, MockBlock, MockTransaction, GOLDEN_TOUCH, MOCK_CODES, MOCK_TAIKO_L2_ADDRESS, MOCK_TAIKO_TREASURY_ADDRESS, }; use eth_types::{ @@ -122,7 +122,9 @@ impl TestContext { // add the GOLDEN_TOUCH account in the first position accounts[0].address(*GOLDEN_TOUCH); // add the l2 contract account in the second position - accounts[1].address(*MOCK_TAIKO_L2_ADDRESS); + accounts[1] + .address(*MOCK_TAIKO_L2_ADDRESS) + .code(MOCK_CODES[0].clone()); // Build Accounts modifiers let account_refs = accounts .iter_mut() diff --git a/taiko-mock/src/transaction.rs b/taiko-mock/src/transaction.rs index 55613dc22a..effcd19aa3 100644 --- a/taiko-mock/src/transaction.rs +++ b/taiko-mock/src/transaction.rs @@ -1,5 +1,7 @@ //! Mock Transaction definition and builder related methods. +use crate::MOCK_BASEFEE; + use super::{ GOLDEN_TOUCH, MOCK_ACCOUNTS, MOCK_ANCHOR_GAS_LIMIT, MOCK_ANCHOR_GAS_PRICE, MOCK_ANCHOR_TX_VALUE, MOCK_CHAIN_ID, MOCK_GASFEECAP, MOCK_GASPRICE, MOCK_GASTIPCAP, @@ -211,6 +213,8 @@ impl MockTransaction { tx.to(*MOCK_TAIKO_L2_ADDRESS); tx.gas(*MOCK_ANCHOR_GAS_LIMIT) .gas_price(*MOCK_ANCHOR_GAS_PRICE) + .max_priority_fee_per_gas(Word::zero()) + .max_fee_per_gas(*MOCK_BASEFEE) .from(*GOLDEN_TOUCH) .to(*MOCK_TAIKO_L2_ADDRESS) .input(crate::anchor::anchor_call()) diff --git a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs index 0d98eddd0d..7a7f4bee7c 100644 --- a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs +++ b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs @@ -614,6 +614,8 @@ mod test { .to(tx.to.unwrap()) .from(tx.from) .gas_price(tx.gas_price.unwrap()) + .max_fee_per_gas(tx.max_fee_per_gas.unwrap()) + .max_priority_fee_per_gas(tx.max_priority_fee_per_gas.unwrap()) .gas(tx.gas) .input(tx.input) .value(tx.value); @@ -635,6 +637,8 @@ mod test { .value(value) .gas(gas(&calldata)) .gas_price(gas_price) + .max_priority_fee_per_gas(gas_price) + .max_fee_per_gas(gas_price) .input(calldata.into()) .build(); diff --git a/zkevm-circuits/src/evm_circuit/execution/end_tx.rs b/zkevm-circuits/src/evm_circuit/execution/end_tx.rs index 8f8cbb977a..6f4cf13145 100644 --- a/zkevm-circuits/src/evm_circuit/execution/end_tx.rs +++ b/zkevm-circuits/src/evm_circuit/execution/end_tx.rs @@ -13,7 +13,7 @@ use crate::{ AddWordsGadget, ConstantDivisionGadget, IsEqualGadget, MinMaxGadget, MinMaxWordGadget, MulWordByU64Gadget, }, - CachedRegion, Cell, + CachedRegion, Cell, Word, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -21,7 +21,7 @@ use crate::{ util::Expr, }; use bus_mapping::operation::Target; -use eth_types::{evm_types::MAX_REFUND_QUOTIENT_OF_GAS_USED, Field, ToScalar}; +use eth_types::{evm_types::MAX_REFUND_QUOTIENT_OF_GAS_USED, Field, ToLittleEndian, ToScalar}; use halo2_proofs::{circuit::Value, plonk::Error}; use strum::EnumCount; @@ -32,6 +32,7 @@ pub(crate) struct EndTxGadget { max_refund: ConstantDivisionGadget, refund: Cell, effective_refund: MinMaxGadget, + effective_gas_price: MinMaxWordGadget, mul_gas_price_by_refund: MulWordByU64Gadget, tx_caller_address: Cell, gas_fee_refund: UpdateBalanceGadget, @@ -46,6 +47,7 @@ pub(crate) struct EndTxGadget { current_cumulative_gas_used: Cell, is_first_tx: IsEqualGadget, is_persistent: Cell, + tx_gas_fee_cap: Word, } impl ExecutionGadget for EndTxGadget { @@ -67,8 +69,6 @@ impl ExecutionGadget for EndTxGadget { ] .map(|field_tag| cb.tx_context_as_word(tx_id.expr(), field_tag, None)); - let is_first_tx = IsEqualGadget::construct(cb, tx_id.expr(), 1.expr()); - // Calculate effective gas to refund let gas_used = tx_gas.expr() - cb.curr.state.gas_left.expr(); let max_refund = ConstantDivisionGadget::construct( @@ -93,24 +93,26 @@ impl ExecutionGadget for EndTxGadget { None, ); + let is_first_tx = IsEqualGadget::construct(cb, tx_id.expr(), 1.expr()); + // Add gas_used * effective_tip to coinbase's balance let coinbase = cb.query_cell(); + cb.block_lookup(BlockContextFieldTag::Coinbase.expr(), None, coinbase.expr()); let base_fee = cb.query_word_rlc(); - for (tag, value) in [ - (BlockContextFieldTag::Coinbase, coinbase.expr()), - (BlockContextFieldTag::BaseFee, base_fee.expr()), - ] { - cb.block_lookup(tag.expr(), None, value); - } - let effective_tip = cb.query_word_rlc(); - // in anchor, we let tx_gas_price equals to zero - let sub_gas_price_by_base_fee = cb.condition(1.expr() - is_first_tx.expr(), |cb| { - AddWordsGadget::construct( - cb, - [effective_tip.clone(), base_fee.clone()], - tx_gas_price.clone(), - ) + cb.condition(is_first_tx.expr(), |cb| { + cb.require_zero("base_fee is zero when tx is first tx", base_fee.expr()); + }); + cb.condition(1.expr() - is_first_tx.expr(), |cb| { + cb.block_lookup(BlockContextFieldTag::BaseFee.expr(), None, base_fee.expr()); }); + + let effective_tip = cb.query_word_rlc(); + // anchor's gas_price is 0, so gas_price != effective_tip + base_fee + let sub_gas_price_by_base_fee = AddWordsGadget::construct( + cb, + [effective_tip.clone(), base_fee.clone()], + tx_gas_price.clone(), + ); let mul_effective_tip_by_gas_used = MulWordByU64Gadget::construct(cb, effective_tip, gas_used.clone()); let mul_base_fee_by_gas_used = @@ -121,21 +123,12 @@ impl ExecutionGadget for EndTxGadget { let add_tip_cap_and_base_fee = AddWordsGadget::construct(cb, [tx_gas_tip_cap, base_fee], base_fee_plus_tip.clone()); let effective_gas_price = - MinMaxWordGadget::construct(cb, &base_fee_plus_tip, &tx_gas_fee_cap).min(); - cb.condition(is_first_tx.expr(), |cb| { - cb.require_equal( - "gas_price == 0 when tx is first tx", - tx_gas_price.expr(), - 0.expr(), - ); - }); - cb.condition(1.expr() - is_first_tx.expr(), |cb| { - cb.require_equal( - "gas_price == min(gas_tip_cap + base_fee, gas_fee_cap)", - tx_gas_price.expr(), - effective_gas_price, - ); - }); + MinMaxWordGadget::construct(cb, &base_fee_plus_tip, &tx_gas_fee_cap); + cb.require_equal( + "gas_price == min(gas_tip_cap + base_fee, gas_fee_cap)", + tx_gas_price.expr(), + effective_gas_price.min(), + ); // send base fee to treasury account let treasury = cb.query_cell(); @@ -203,7 +196,7 @@ impl ExecutionGadget for EndTxGadget { ); cb.require_step_state_transition(StepStateTransition { - rw_counter: Delta(10.expr() - is_first_tx.expr()), + rw_counter: Delta(11.expr() - is_first_tx.expr()), ..StepStateTransition::any() }); }, @@ -213,7 +206,7 @@ impl ExecutionGadget for EndTxGadget { cb.next.execution_state_selector([ExecutionState::EndBlock]), |cb| { cb.require_step_state_transition(StepStateTransition { - rw_counter: Delta(9.expr() - is_first_tx.expr()), + rw_counter: Delta(10.expr() - is_first_tx.expr()), // We propagate call_id so that EndBlock can get the last tx_id // in order to count processed txs. call_id: Same, @@ -228,6 +221,7 @@ impl ExecutionGadget for EndTxGadget { max_refund, refund, effective_refund, + effective_gas_price, mul_gas_price_by_refund, tx_caller_address, gas_fee_refund, @@ -242,6 +236,7 @@ impl ExecutionGadget for EndTxGadget { current_cumulative_gas_used, is_first_tx, is_persistent, + tx_gas_fee_cap, } } @@ -272,6 +267,25 @@ impl ExecutionGadget for EndTxGadget { F::from(refund), )?; + let base_fee = if tx.id == 1 { + 0.into() + } else { + block.context.base_fee + }; + self.tx_gas_fee_cap + .assign(region, offset, Some(tx.gas_fee_cap.to_le_bytes()))?; + self.add_tip_cap_and_base_fee.assign( + region, + offset, + [tx.gas_tip_cap, base_fee], + tx.gas_tip_cap + base_fee, + )?; + self.effective_gas_price.assign( + region, + offset, + base_fee + tx.gas_tip_cap, + tx.gas_fee_cap, + )?; let effective_refund = refund.min(max_refund as u64); let gas_fee_refund = tx.gas_price * (effective_refund + step.gas_left.0); self.mul_gas_price_by_refund.assign( @@ -297,24 +311,14 @@ impl ExecutionGadget for EndTxGadget { vec![gas_fee_refund], caller_balance, )?; - let is_anchor_tx = tx.id == 1; - let effective_tip = if is_anchor_tx { - 0.into() - } else { - tx.gas_price - block.context.base_fee - }; + let effective_tip = tx.gas_price - base_fee; self.sub_gas_price_by_base_fee.assign( region, offset, - [effective_tip, block.context.base_fee], - tx.gas_price, - )?; - self.add_tip_cap_and_base_fee.assign( - region, - offset, - [tx.gas_tip_cap, block.context.base_fee], - tx.gas_tip_cap + block.context.base_fee, + [effective_tip, base_fee], + effective_tip + base_fee, )?; + self.mul_effective_tip_by_gas_used.assign( region, offset, @@ -322,6 +326,13 @@ impl ExecutionGadget for EndTxGadget { gas_used, effective_tip * gas_used, )?; + self.mul_base_fee_by_gas_used.assign( + region, + offset, + base_fee, + gas_used, + base_fee * gas_used, + )?; self.coinbase.assign( region, offset, @@ -340,11 +351,6 @@ impl ExecutionGadget for EndTxGadget { vec![effective_tip * gas_used], coinbase_balance, )?; - let treasury_reward = if is_anchor_tx { - 0.into() - } else { - block.context.base_fee * gas_used - }; self.treasury.assign( region, offset, @@ -361,7 +367,7 @@ impl ExecutionGadget for EndTxGadget { region, offset, treasury_balance_prev, - vec![treasury_reward], + vec![base_fee * gas_used], treasury_balance, )?;