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

Commit 225db80

Browse files
authored
[Fix] Set l1fee to zero for l1msg (#714)
* induce tx_type to tx field * set l1fee to 0 for l1msg * depress sanity check warnings * adjust the order of tx field tag to ensure some constraint * lint * trigger ci * add log to mark l1msg info * some fix according to test
1 parent c4db809 commit 225db80

File tree

6 files changed

+74
-13
lines changed

6 files changed

+74
-13
lines changed

bus-mapping/src/circuit_input_builder.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,11 @@ impl<'a> CircuitInputBuilder {
478478
let mut tx = self.new_tx(eth_tx, !geth_trace.failed)?;
479479

480480
// Sanity check for transaction L1 fee.
481-
let tx_l1_fee = tx.l1_fee();
481+
let tx_l1_fee = if tx.tx_type.is_l1_msg() {
482+
0
483+
} else {
484+
tx.l1_fee()
485+
};
482486
if tx_l1_fee != geth_trace.l1_fee {
483487
log::error!(
484488
"Mismatch tx_l1_fee: calculated = {}, real = {}",

bus-mapping/src/evm/opcodes.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,11 @@ pub fn gen_end_tx_ops(state: &mut CircuitInputStateRef) -> Result<ExecStep, Erro
948948

949949
// Add 3 RW read operations for transaction L1 fee.
950950
fn gen_tx_l1_fee_ops(state: &mut CircuitInputStateRef, exec_step: &mut ExecStep) {
951+
// for l1 message, no need to add rw op
952+
if state.tx.tx_type.is_l1_msg() {
953+
return;
954+
}
955+
951956
let tx_id = state.tx_ctx.id();
952957

953958
let base_fee = Word::from(state.tx.l1_fee.base_fee);

zkevm-circuits/src/evm_circuit/execution/begin_tx.rs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::{
2424
},
2525
};
2626
use bus_mapping::circuit_input_builder::CopyDataType;
27-
use eth_types::{Address, Field, ToLittleEndian, ToScalar, U256};
27+
use eth_types::{geth_types::TxType::L1Msg, Address, Field, ToLittleEndian, ToScalar, U256};
2828
use ethers_core::utils::{get_contract_address, keccak256, rlp::RlpStream};
2929
use gadgets::util::{expr_from_bytes, not, or, Expr};
3030
use halo2_proofs::{circuit::Value, plonk::Error};
@@ -42,6 +42,8 @@ use gadgets::util::select;
4242
#[derive(Clone, Debug)]
4343
pub(crate) struct BeginTxGadget<F> {
4444
tx_id: Cell<F>,
45+
tx_type: Cell<F>,
46+
tx_is_l1msg: IsEqualGadget<F>,
4547
tx_nonce: Cell<F>,
4648
tx_gas: Cell<F>,
4749
tx_gas_price: Word<F>,
@@ -99,7 +101,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
99101

100102
let tx_id = cb.query_cell();
101103

102-
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] =
104+
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, tx_type] =
103105
[
104106
TxContextFieldTag::Nonce,
105107
TxContextFieldTag::Gas,
@@ -109,10 +111,18 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
109111
TxContextFieldTag::CallDataLength,
110112
TxContextFieldTag::CallDataGasCost,
111113
TxContextFieldTag::TxDataGasCost,
114+
TxContextFieldTag::TxType,
112115
]
113116
.map(|field_tag| cb.tx_context(tx_id.expr(), field_tag, None));
114117

115-
let tx_l1_fee = TxL1FeeGadget::construct(cb, tx_id.expr(), tx_data_gas_cost.expr());
118+
let tx_is_l1msg = IsEqualGadget::construct(cb, tx_type.expr(), (L1Msg as u64).expr());
119+
let tx_l1_fee = cb.condition(not::expr(tx_is_l1msg.expr()), |cb| {
120+
TxL1FeeGadget::construct(cb, tx_id.expr(), tx_data_gas_cost.expr())
121+
});
122+
cb.condition(tx_is_l1msg.expr(), |cb| {
123+
cb.require_zero("l1fee is 0 for l1msg", tx_data_gas_cost.expr());
124+
});
125+
let tx_l1_fee_rw_delta = select::expr(tx_is_l1msg.expr(), 0.expr(), tx_l1_fee.rw_delta());
116126

117127
cb.call_context_lookup(
118128
1.expr(),
@@ -179,8 +189,11 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
179189

180190
cb.require_equal(
181191
"tx_fee == l1_fee + l2_fee",
182-
from_bytes::expr(&tx_l1_fee.tx_l1_fee().cells[..])
183-
+ from_bytes::expr(&mul_gas_fee_by_gas.product().cells[..16]),
192+
select::expr(
193+
tx_is_l1msg.expr(),
194+
0.expr(),
195+
from_bytes::expr(&tx_l1_fee.tx_l1_fee().cells[..]),
196+
) + from_bytes::expr(&mul_gas_fee_by_gas.product().cells[..16]),
184197
from_bytes::expr(&tx_fee.cells[..16]),
185198
);
186199

@@ -438,7 +451,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
438451
// - Write CallContext CodeHash
439452
rw_counter: Delta(
440453
22.expr()
441-
+ tx_l1_fee.rw_delta()
454+
+ tx_l1_fee_rw_delta.expr()
442455
+ transfer_with_gas_fee.rw_delta()
443456
+ SHANGHAI_RW_DELTA.expr()
444457
+ PRECOMPILE_COUNT.expr(),
@@ -494,7 +507,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
494507
// - a TransferWithGasFeeGadget
495508
rw_counter: Delta(
496509
7.expr()
497-
+ tx_l1_fee.rw_delta()
510+
+ tx_l1_fee_rw_delta.expr()
498511
+ transfer_with_gas_fee.rw_delta()
499512
+ SHANGHAI_RW_DELTA.expr()
500513
+ PRECOMPILE_COUNT.expr()
@@ -547,7 +560,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
547560
// - a TransferWithGasFeeGadget
548561
rw_counter: Delta(
549562
8.expr()
550-
+ tx_l1_fee.rw_delta()
563+
+ tx_l1_fee_rw_delta.expr()
551564
+ transfer_with_gas_fee.rw_delta()
552565
+ SHANGHAI_RW_DELTA.expr()
553566
+ PRECOMPILE_COUNT.expr(),
@@ -619,7 +632,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
619632
// - Write CallContext CodeHash
620633
rw_counter: Delta(
621634
21.expr()
622-
+ tx_l1_fee.rw_delta()
635+
+ tx_l1_fee_rw_delta.expr()
623636
+ transfer_with_gas_fee.rw_delta()
624637
+ SHANGHAI_RW_DELTA.expr()
625638
+ PRECOMPILE_COUNT.expr(),
@@ -638,6 +651,8 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
638651

639652
Self {
640653
tx_id,
654+
tx_type,
655+
tx_is_l1msg,
641656
tx_nonce,
642657
tx_gas,
643658
tx_gas_price,
@@ -690,7 +705,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
690705
let zero = eth_types::Word::zero();
691706

692707
let mut rws = StepRws::new(block, step);
693-
rws.offset_add(10 + PRECOMPILE_COUNT);
708+
rws.offset_add(if tx.tx_type.is_l1_msg() { 7 } else { 10 } + PRECOMPILE_COUNT);
694709

695710
#[cfg(feature = "shanghai")]
696711
let is_coinbase_warm = rws.next().tx_access_list_value_pair().1;
@@ -727,6 +742,14 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
727742

728743
self.tx_id
729744
.assign(region, offset, Value::known(F::from(tx.id as u64)))?;
745+
self.tx_type
746+
.assign(region, offset, Value::known(F::from(tx.tx_type as u64)))?;
747+
self.tx_is_l1msg.assign(
748+
region,
749+
offset,
750+
F::from(tx.tx_type as u64),
751+
F::from(L1Msg as u64),
752+
)?;
730753
self.tx_nonce
731754
.assign(region, offset, Value::known(F::from(tx.nonce)))?;
732755
self.tx_gas
@@ -917,7 +940,12 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
917940
self.is_coinbase_warm
918941
.assign(region, offset, Value::known(F::from(is_coinbase_warm)))?;
919942

920-
let tx_l1_fee = tx.l1_fee.tx_l1_fee(tx.tx_data_gas_cost).0;
943+
let tx_l1_fee = if tx.tx_type.is_l1_msg() {
944+
log::trace!("tx is l1msg and l1 fee is 0");
945+
0
946+
} else {
947+
tx.l1_fee.tx_l1_fee(tx.tx_data_gas_cost).0
948+
};
921949
let tx_l2_fee = tx.gas_price * tx.gas;
922950
if tx_fee != tx_l2_fee + tx_l1_fee {
923951
log::error!(

zkevm-circuits/src/table.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ pub enum TxFieldTag {
175175
TxHashRLC,
176176
/// TxHash: Hash of the transaction with the signature
177177
TxHash,
178+
/// TxType: Type of the transaction
179+
TxType,
178180
/// The block number in which this tx is included.
179181
BlockNumber,
180182
}

zkevm-circuits/src/tx_circuit.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ use eth_types::geth_types::{
7373
use gadgets::comparator::{ComparatorChip, ComparatorConfig, ComparatorInstruction};
7474

7575
/// Number of rows of one tx occupies in the fixed part of tx table
76-
pub const TX_LEN: usize = 22;
76+
pub const TX_LEN: usize = 23;
7777
/// Offset of TxHash tag in the tx table
7878
pub const TX_HASH_OFFSET: usize = 21;
7979
/// Offset of ChainID tag in the tx table
@@ -272,6 +272,7 @@ impl<F: Field> SubCircuitConfig<F> for TxCircuitConfig<F> {
272272
is_tx_tag!(is_sign_hash, TxSignHash);
273273
is_tx_tag!(is_hash, TxHash);
274274
is_tx_tag!(is_block_num, BlockNumber);
275+
is_tx_tag!(is_tx_type, TxType);
275276

276277
// testing if value is zero for tags
277278
let value_is_zero = IsZeroChip::configure(
@@ -358,6 +359,7 @@ impl<F: Field> SubCircuitConfig<F> for TxCircuitConfig<F> {
358359
(is_data(meta), Null),
359360
(is_block_num(meta), Null),
360361
(is_chain_id_expr(meta), Null),
362+
(is_tx_type(meta), Null),
361363
];
362364

363365
cb.require_boolean(
@@ -375,6 +377,14 @@ impl<F: Field> SubCircuitConfig<F> for TxCircuitConfig<F> {
375377
],
376378
);
377379

380+
cb.condition(is_tx_type(meta), |cb| {
381+
cb.require_equal(
382+
"associated tx type to tag",
383+
meta.query_advice(tx_type, Rotation::cur()),
384+
meta.query_advice(tx_table.value, Rotation::cur()),
385+
);
386+
});
387+
378388
cb.require_equal(
379389
"associated rlp_tag",
380390
meta.query_advice(rlp_tag, Rotation::cur()),
@@ -1826,6 +1836,12 @@ impl<F: Field> TxCircuit<F> {
18261836
})
18271837
}),
18281838
),
1839+
(
1840+
TxFieldTag::TxType,
1841+
None,
1842+
None,
1843+
Value::known(F::from(tx.tx_type as u64)),
1844+
),
18291845
(
18301846
BlockNumber,
18311847
None,

zkevm-circuits/src/witness/tx.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,12 @@ impl Transaction {
299299
Value::known(F::zero()),
300300
rlc_be_bytes(&tx_hash_be_bytes, challenges.evm_word()),
301301
],
302+
[
303+
Value::known(F::from(self.id as u64)),
304+
Value::known(F::from(TxContextFieldTag::TxType as u64)),
305+
Value::known(F::zero()),
306+
Value::known(F::from(self.tx_type as u64)),
307+
],
302308
[
303309
Value::known(F::from(self.id as u64)),
304310
Value::known(F::from(TxContextFieldTag::BlockNumber as u64)),

0 commit comments

Comments
 (0)