-
Notifications
You must be signed in to change notification settings - Fork 125
Integrate EVM circuit into TaikoSuperCircuit #112
Comments
EIP1559 in taiko's zkevm-circuits specMotivationEIP-1559 is a new transaction type in Ethereum, it is a big change in Ethereum, and it is a big change in zkevm too. We need to support it in zkevm-circuits. This document is about how to support EIP-1559 in zkevm-circuits for Taiko Layer2. We will divide the work into several stages, the first stage is about supporting EIP-1559 in evm-circuit and associated circuits, tables and etc. Like: anchor-circuit, tx-circuit, block-circuit, tx-table, block-table, etc. The remaining parts will be done in the next series of stages. We need to agree on some trade-offs. The first trade-off is that we only support dynamic fee transaction in Taiko Layer2. The second trade-off is that the implementation is not exactly the same as the EIP-1559, so, it is not Type-1 compatible. And there will be some differences with the implementation in tiako-geth, like: the base_fee in Anchor transaction must be zero in circuit, but it is not zero in taiko-geth. So, we can not add extra logics for Anchor transaction in evm-circuit, it's very important, because the codebase of evm-circuit is complex enough, we should not add more logics in it. I will explain the details in the following sections. Let's jump into the details. The goals and non-goalsAt the beginning, we need to define the goals and non-goals of this work. Goals:
Non-goals:
The changes between the components
Changes in evm-circuit1. BeginTx stepNow I can explain why we need to use zero base_fee in Anchor transaction. Because the Anchor transaction is a special case of BeginTx step, actually, the GOLDEN_TOUCH account doesn't pay any gas fee for Anchor transaction, but now in taiko-geth, we have a special logic to skip the check of balance, gas_fee_cap, gas_tip_cap, and base_fee. But it is not friendly to the evm-circuit, we need more constrains for Anchor transaction. But if we set Anchor's base_fee to zero, then we don't need to add more constrains any more. So, we have two kinds of base_fee(zero or non-zero) in transactions, we need some extra works in tx-circuit, and let it support two kinds of base_fee.
Inspired by @smtmfft 2. Opcode stepsThe EIP-1559 doesn't change the opcodes, and also doesn't add more opcodes, so i think we don't have any works in this steps. (Maybe need double check in the future) Update:
3. EndTx stepThis step is the most important step in taiko's EIP-1559, because we need to send the base_fee to a treasury account, instead of burning it. We don't need to add more logics for Anchor transaction, because we have set the base_fee and gas_tip to zero in BeginTx step, so, we can just ignore the base_fee and gas_tip in EndTx step. Demo code: fn gen_end_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep, Error> {
// ... balabala
// add tip to coinbase(miner)
let effective_tip = state.tx.tx.gas_price - state.block.base_fee;
let (found, coinbase_account) = state.sdb.get_account(&state.block.coinbase);
if !found {
return Err(Error::AccountNotFound(state.block.coinbase));
}
let coinbase_balance_prev = coinbase_account.balance;
let coinbase_balance =
coinbase_balance_prev + effective_tip * (state.tx.gas() - exec_step.gas_left.0);
state.account_write(
&mut exec_step,
state.block.coinbase,
AccountField::Balance,
coinbase_balance,
coinbase_balance_prev,
)?;
// add base_fee to treasury
let (found, treasury_account) = state.sdb.get_account(&treasury_account);
if !found {
return Err(Error::AccountNotFound(treasury_account));
}
let treasury_balance_prev = treasury_account.balance;
let treasury_balance =
treasury_balance_prev + effective_tip * (state.tx.gas() - exec_step.gas_left.0);
state.account_write(
&mut exec_step,
treasury_account,
AccountField::Balance,
treasury_balance,
treasury_balance_prev,
)?;
Ok(exec_step)
} 3.1. The treasury accountThis is an account from our L1 contract, it is a special account, all base_fee will be sent to this account. So there is no deflation on taiko's layer2. 4. EndBlock stepNow nothing has been done, but some works in the future:
Changes in tx-circuit and tx-tableAdd extra three fields in the tx-table for fixing the dynamic fee transaction:
For Anchor transaction, tx-circuit must constrain the base_fee to zero, and other transactions's base_fee must be non-zero. Another change is that the payload for signature hash adds more 3 fields: max_priority_fee_per_gas(gas_tip), max_fee_per_gas(gas_price), and access_list. Changes in anchor-circuitPrevious, in anchor-circuit we only check some constant fields, like: gas_price, from, to, etc. But now we need to check the base_fee. cb.require_equal(
"base_fee = 0",
base_fee,
0.expr(),
); Changes in block-circuit and block-tableFor EIP-1559, the block hash has one more field: base_fee_per_gas, so, we need care about the block hash calculation. Changes in rlp-circuitFor EIP-1559, the rlp-circuit need to update to handle the dynamic fee transaction(type-2). The tasks
|
Looks good! Let's certainly do the EVM changes first by just adding the necessary data to the lookup tables, and then worry about updating the other circuits to verify this additional data. Some small comments/questions:
The fee calculation uses
I think would work. I think the only place
I don't think we need to do this, I think just setting it to some deterministic value (like block.base_fee) is sufficient. But I could be missing something.
The basefee opcode was added, but it's already supported.
Will be done by @ggkitsas:
|
Missing access list fee change, Opcode fee varies according to access list settings. I am thinking if we can claim that one special L3 forbids access list, so that we can make 2 phases circuit dev for fast testnet deployment. |
Ah yes good point. Let's make the node ignore the access list which hopefully isn't that hard to do? Forbidding seems harder because people can just change the block creation code and still get these transactions included in a block and then these transactions would have to be marked as invalid which we would then also have to support on the circuits side. |
Updated |
So far we did not see any access list in our testnet, so I think it should be OK. But even not possible, still we can do that in our devnet, so all 1559 related circuit dev could be in 2 phases (1. w/o access list, 2. w/ access list) which means a fast testnet deployment, so that we can observe the circuit's behavior in real env more frequently. |
Or, use
Anchor transaction with zero basefee and gastip will eventually have zero gasfee. So at BeginTx and EndTx we don't need to treat the anchor transaction specially, before we have to ignore deductions. but GOLDEN_TOUCH has no balance. Everything minus zero gasfee*gaslimit equals zero. |
Also summarized my thinkings on 1559 supporting circuits: https://www.notion.so/taikoxyz/1559-Development-Thinkings-a84ac894fb984b71ad847913ae031378 |
But
It will still be a bit special because we'll still have to ignore the Reminds me that there is an additional invalid tx now: if |
Ok, for both of these two reasons, the above two approaches have the same workload. So, it's better for us to use block.basefee, and add if else at the BeginTx and EndTx for Anchor transaction. |
No description provided.
The text was updated successfully, but these errors were encountered: