Skip to content

Commit

Permalink
feat: treat anchor's gas_price as zero
Browse files Browse the repository at this point in the history
  • Loading branch information
johntaiko committed Aug 8, 2023
1 parent 03c2047 commit aff5000
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 125 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bus-mapping/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ eth-types = { path = "../eth-types" }
gadgets = { path = "../gadgets" }
keccak256 = { path = "../keccak256" }
mock = { path = "../mock", optional = true }
taiko-mock = { path = "../taiko-mock", optional = true }

ethers-core = "=2.0.0"
ethers-providers = "=2.0.0"
Expand Down
9 changes: 5 additions & 4 deletions bus-mapping/src/circuit_input_builder/input_state_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,11 @@ impl<'a> CircuitInputStateRef<'a> {
&& (matches!(rw, RW::READ) || (op.value_prev.is_zero() && op.value.is_zero())))
&& account.is_empty()
{
panic!(
"RWTable Account field {:?} lookup to non-existing account rwc: {}, op: {:?}",
rw, self.block_ctx.rwc.0, op
);

// panic!(
// "RWTable Account field {:?} lookup to non-existing account rwc: {}, op: {:?}",
// rw, self.block_ctx.rwc.0, op
// );
}
// -- sanity check end --
// Perform the write to the account in the StateDB
Expand Down
31 changes: 10 additions & 21 deletions bus-mapping/src/evm/opcodes/begin_end_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,6 @@ fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep, Erro
);
}

// anchor tx does not pay fee
let fee = if state.tx_ctx.is_anchor_tx() {
0.into()
} else {
state.tx.tx.gas_price * state.tx.gas()
};

// Transfer with fee
state.transfer_with_fee(
&mut exec_step,
Expand All @@ -113,7 +106,7 @@ fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep, Erro
callee_exists,
call.is_create(),
call.value,
Some(fee),
Some(state.tx.tx.gas_price * state.tx.gas()),
)?;

// In case of contract creation we wish to verify the correctness of the
Expand Down Expand Up @@ -261,12 +254,8 @@ fn gen_end_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep, Error>
return Err(Error::AccountNotFound(call.caller_address));
}
let caller_balance_prev = caller_account.balance;
let caller_balance = caller_balance_prev
+ if state.tx_ctx.is_anchor_tx() {
0.into()
} else {
state.tx.tx.gas_price * (exec_step.gas_left.0 + effective_refund)
};
let caller_balance =
caller_balance_prev + state.tx.tx.gas_price * (exec_step.gas_left.0 + effective_refund);
state.account_write(
&mut exec_step,
call.caller_address,
Expand All @@ -275,18 +264,18 @@ fn gen_end_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep, Error>
caller_balance_prev,
)?;

let effective_tip = state.tx.tx.gas_price - state.block.base_fee;
let effective_tip = if state.tx_ctx.is_anchor_tx() {
0.into()
} else {
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
+ if state.tx_ctx.is_anchor_tx() {
0.into()
} else {
effective_tip * (state.tx.gas() - exec_step.gas_left.0)
};
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,
Expand Down
2 changes: 1 addition & 1 deletion taiko-mock/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ lazy_static! {
pub static ref MOCK_TAIKO_TREASURY_ADDRESS: Address = address!("0x000000000000000000000000000000000cafe777");
/// Mock anchor
pub static ref MOCK_ANCHOR_GAS_LIMIT: Word = Word::from(180000);
pub static ref MOCK_ANCHOR_GAS_PRICE: Word = *MOCK_BASEFEE;
pub static ref MOCK_ANCHOR_GAS_PRICE: Word = Word::zero();
pub static ref MOCK_ANCHOR_L1_HASH: Hash = Hash::from_slice(&[0u8; 32]);
pub static ref MOCK_ANCHOR_SIGNAL_ROOT: Hash = Hash::from_slice(&[0u8; 32]);
pub static ref MOCK_ANCHOR_L1_HIGHT: u64 = 0;
Expand Down
40 changes: 12 additions & 28 deletions zkevm-circuits/src/evm_circuit/execution/begin_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
const EXECUTION_STATE: ExecutionState = ExecutionState::BeginTx;

fn configure(cb: &mut EVMConstraintBuilder<F>) -> Self {
// additions for taiko's eip-1559
// 1. no need update GOLDEN_TOUCH account for Anchor

// Use rw_counter of the step which triggers next call as its call_id.
let call_id = cb.curr.state.rw_counter.clone();

Expand Down Expand Up @@ -180,29 +177,16 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
); // rwc_delta += 1
});

// Anchor is always the first tx of the list
let is_anchor_tx = IsEqualGadget::construct(cb, tx_id.expr(), 1.expr());
let not_anchor_tx = not::expr(is_anchor_tx.expr());

// Transfer value from caller to callee, creating account if necessary.
// only update caller and callee account when tx is not anchor
let transfer_with_gas_fee = cb.condition(not_anchor_tx.expr(), |cb| {
TransferWithGasFeeGadget::construct(
cb,
tx_caller_address.expr(),
tx_callee_address.expr(),
not::expr(callee_not_exists.expr()),
or::expr([tx_is_create.expr(), callee_not_exists.expr()]),
tx_value.clone(),
mul_gas_fee_by_gas.product().clone(),
&mut reversion_info,
)
});
// ignore anchor's transfer
let transfer_with_gas_fee_rw_delta = select::expr(
is_anchor_tx.expr(),
0.expr(),
transfer_with_gas_fee.rw_delta(),
let transfer_with_gas_fee = TransferWithGasFeeGadget::construct(
cb,
tx_caller_address.expr(),
tx_callee_address.expr(),
not::expr(callee_not_exists.expr()),
or::expr([tx_is_create.expr(), callee_not_exists.expr()]),
tx_value.clone(),
mul_gas_fee_by_gas.product().clone(),
&mut reversion_info,
);

let caller_nonce_hash_bytes = array_init::array_init(|_| cb.query_byte());
Expand Down Expand Up @@ -295,7 +279,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
// - Write CallContext IsRoot
// - Write CallContext IsCreate
// - Write CallContext CodeHash
rw_counter: Delta(21.expr() + transfer_with_gas_fee_rw_delta.expr()),
rw_counter: Delta(21.expr() + transfer_with_gas_fee.rw_delta()),
call_id: To(call_id.expr()),
is_root: To(true.expr()),
is_create: To(tx_is_create.expr()),
Expand Down Expand Up @@ -338,7 +322,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
// - Write TxAccessListAccount
// - Read Account CodeHash
// - a TransferWithGasFeeGadget
rw_counter: Delta(8.expr() + transfer_with_gas_fee_rw_delta.expr()),
rw_counter: Delta(8.expr() + transfer_with_gas_fee.rw_delta()),
call_id: To(call_id.expr()),
..StepStateTransition::any()
});
Expand Down Expand Up @@ -395,7 +379,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
// - Write CallContext IsRoot
// - Write CallContext IsCreate
// - Write CallContext CodeHash
rw_counter: Delta(21.expr() + transfer_with_gas_fee_rw_delta.expr()),
rw_counter: Delta(21.expr() + transfer_with_gas_fee.rw_delta()),
call_id: To(call_id.expr()),
is_root: To(true.expr()),
is_create: To(tx_is_create.expr()),
Expand Down
148 changes: 77 additions & 71 deletions zkevm-circuits/src/evm_circuit/execution/end_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,6 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
const EXECUTION_STATE: ExecutionState = ExecutionState::EndTx;

fn configure(cb: &mut EVMConstraintBuilder<F>) -> Self {
// additions for taiko's eip-1559:
// 1. effective_gas_price = min(gas_tip_cap + base_fee, gas_fee_cap)
// a. gas_price == effective_gas_price
// 2. no need update GOLDEN_TOUCH account in Anchor(-effective_gas_price, +refund)
// 3. Anchor's gas_tip_cap == 0
// 4. check gas_price == min(gas_tip_cap + base_fee, gas_fee_cap)

let tx_id = cb.call_context(None, CallContextFieldTag::TxId);
let is_persistent = cb.call_context(None, CallContextFieldTag::IsPersistent);

Expand Down Expand Up @@ -93,6 +86,12 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
tx_gas_price.clone(),
effective_refund.min() + cb.curr.state.gas_left.expr(),
);
let gas_fee_refund = UpdateBalanceGadget::construct(
cb,
tx_caller_address.expr(),
vec![mul_gas_price_by_refund.product().clone()],
None,
);

// Add gas_used * effective_tip to coinbase's balance
let coinbase = cb.query_cell();
Expand All @@ -104,11 +103,14 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
cb.block_lookup(tag.expr(), None, value);
}
let effective_tip = cb.query_word_rlc();
let sub_gas_price_by_base_fee = AddWordsGadget::construct(
cb,
[effective_tip.clone(), base_fee.clone()],
tx_gas_price.clone(),
);
// 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(),
)
});
let mul_effective_tip_by_gas_used =
MulWordByU64Gadget::construct(cb, effective_tip, gas_used.clone());
let mul_base_fee_by_gas_used =
Expand All @@ -120,37 +122,38 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
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.require_equal(
"gas_price == min(gas_tip_cap + base_fee, gas_fee_cap)",
tx_gas_price.expr(),
effective_gas_price,
);
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,
);
});

// send base fee to treasury account
let treasury = cb.query_cell();

let (gas_fee_refund, coinbase_reward, treasury_reward) =
cb.condition(1.expr() - is_first_tx.expr(), |cb| {
(
UpdateBalanceGadget::construct(
cb,
tx_caller_address.expr(),
vec![mul_gas_price_by_refund.product().clone()],
None,
),
UpdateBalanceGadget::construct(
cb,
coinbase.expr(),
vec![mul_effective_tip_by_gas_used.product().clone()],
None,
),
UpdateBalanceGadget::construct(
cb,
treasury.expr(),
vec![mul_base_fee_by_gas_used.product().clone()],
None,
),
)
});
let coinbase_reward = UpdateBalanceGadget::construct(
cb,
coinbase.expr(),
vec![mul_effective_tip_by_gas_used.product().clone()],
None,
);

let treasury_reward = UpdateBalanceGadget::construct(
cb,
treasury.expr(),
vec![mul_base_fee_by_gas_used.product().clone()],
None,
);

// constrain tx receipt fields
cb.tx_receipt_lookup(
1.expr(),
Expand Down Expand Up @@ -253,7 +256,8 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
) -> Result<(), Error> {
let gas_used = tx.gas - step.gas_left.0;
let (refund, _) = block.get_rws(step, 2).tx_refund_value_pair();

let [(caller_balance, caller_balance_prev), (coinbase_balance, coinbase_balance_prev), (treasury_balance, treasury_balance_prev)] =
[3, 4, 5].map(|index| block.get_rws(step, index).account_value_pair());
self.tx_id
.assign(region, offset, Value::known(F::from(tx.id as u64)))?;
self.tx_gas
Expand Down Expand Up @@ -286,7 +290,19 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
.expect("unexpected Address -> Scalar conversion failure"),
),
)?;
let effective_tip = tx.gas_price - block.context.base_fee;
self.gas_fee_refund.assign(
region,
offset,
caller_balance_prev,
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
};
self.sub_gas_price_by_base_fee.assign(
region,
offset,
Expand All @@ -306,7 +322,6 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
gas_used,
effective_tip * gas_used,
)?;

self.coinbase.assign(
region,
offset,
Expand All @@ -318,6 +333,18 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
.expect("unexpected Address -> Scalar conversion failure"),
),
)?;
self.coinbase_reward.assign(
region,
offset,
coinbase_balance_prev,
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,
Expand All @@ -330,34 +357,13 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
.expect("unexpected Address -> Scalar conversion failure"),
),
)?;

if tx.id != 1 {
let [(caller_balance, caller_balance_prev), (coinbase_balance, coinbase_balance_prev), (treasury_balance, treasury_balance_prev)] =
[3, 4, 5].map(|index| block.get_rws(step, index).account_value_pair());
self.gas_fee_refund.assign(
region,
offset,
caller_balance_prev,
vec![gas_fee_refund],
caller_balance,
)?;

self.coinbase_reward.assign(
region,
offset,
coinbase_balance_prev,
vec![effective_tip * gas_used],
coinbase_balance,
)?;

self.treasury_reward.assign(
region,
offset,
treasury_balance_prev,
vec![block.context.base_fee * gas_used],
treasury_balance,
)?;
}
self.treasury_reward.assign(
region,
offset,
treasury_balance_prev,
vec![treasury_reward],
treasury_balance,
)?;

let current_cumulative_gas_used: u64 = if tx.id == 1 {
0
Expand Down

0 comments on commit aff5000

Please sign in to comment.