Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Streamline the math gadget API #1765

Merged
merged 11 commits into from
Feb 15, 2024
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
2 changes: 1 addition & 1 deletion zkevm-circuits/src/evm_circuit/execution/addmod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl<F: Field> ExecutionGadget<F> for AddModGadget<F> {
let a_reduced = cb.query_word32();
let d = cb.query_word32();

let n_is_zero = IsZeroWordGadget::construct(cb, &n);
let n_is_zero = cb.is_zero_word(&n);

// 1. check k * N + a_reduced == a without overflow
let muladd_k_n_areduced =
Expand Down
2 changes: 1 addition & 1 deletion zkevm-circuits/src/evm_circuit/execution/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl<F: Field> ExecutionGadget<F> for BalanceGadget<F> {
AccountFieldTag::CodeHash,
code_hash.to_word(),
);
let not_exists = IsZeroWordGadget::construct(cb, &code_hash);
let not_exists = cb.is_zero_word(&code_hash);
let exists = not::expr(not_exists.expr());
let balance = cb.query_word32();
cb.condition(exists.expr(), |cb| {
Expand Down
7 changes: 3 additions & 4 deletions zkevm-circuits/src/evm_circuit/execution/begin_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
let gas_left = tx.gas.expr() - tx.intrinsic_gas();
let sufficient_gas_left = RangeCheckGadget::construct(cb, gas_left.clone());

let tx_caller_address_is_zero = IsZeroWordGadget::construct(cb, &tx.caller_address);
let tx_caller_address_is_zero = cb.is_zero_word(&tx.caller_address);
cb.require_equal(
"CallerAddress != 0 (not a padding tx)",
tx_caller_address_is_zero.expr(),
Expand Down Expand Up @@ -155,9 +155,8 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {

// Read code_hash of callee
let code_hash = cb.query_word_unchecked();
let is_empty_code_hash =
IsEqualWordGadget::construct(cb, &code_hash.to_word(), &cb.empty_code_hash());
let callee_not_exists = IsZeroWordGadget::construct(cb, &code_hash);
let is_empty_code_hash = cb.is_eq_word(&code_hash.to_word(), &cb.empty_code_hash());
let callee_not_exists = cb.is_zero_word(&code_hash);
// no_callee_code is true when the account exists and has empty
// code hash, or when the account doesn't exist (which we encode with
// code_hash = 0).
Expand Down
2 changes: 1 addition & 1 deletion zkevm-circuits/src/evm_circuit/execution/byte.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl<F: Field> ExecutionGadget<F> for ByteGadget<F> {
let is_byte_selected = array_init(|idx| {
// Check if this byte is selected looking only at the LSB of the
// index word
IsEqualGadget::construct(cb, index.limbs[0].expr(), (31 - idx).expr())
cb.is_eq(index.limbs[0].expr(), (31 - idx).expr())
});

// Sum all possible selected bytes
Expand Down
58 changes: 29 additions & 29 deletions zkevm-circuits/src/evm_circuit/execution/callop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ use crate::{
Transition::{Delta, To},
},
math_gadget::{
ConstantDivisionGadget, IsZeroGadget, LtGadget, LtWordGadget, MinMaxGadget,
ConstantDivisionGadget, IsEqualGadget, IsZeroGadget, LtGadget, LtWordGadget,
MinMaxGadget,
},
memory_gadget::{CommonMemoryAddressGadget, MemoryAddressGadget},
not, or,
Expand Down Expand Up @@ -44,10 +45,10 @@ use std::cmp::min;

pub(crate) struct CallOpGadget<F> {
opcode: Cell<F>,
is_call: IsZeroGadget<F>,
is_callcode: IsZeroGadget<F>,
is_delegatecall: IsZeroGadget<F>,
is_staticcall: IsZeroGadget<F>,
is_call: IsEqualGadget<F>,
is_callcode: IsEqualGadget<F>,
is_delegatecall: IsEqualGadget<F>,
is_staticcall: IsEqualGadget<F>,
tx_id: Cell<F>,
reversion_info: ReversionInfo<F>,
current_callee_address: WordLoHiCell<F>,
Expand Down Expand Up @@ -94,12 +95,10 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {
fn configure(cb: &mut EVMConstraintBuilder<F>) -> Self {
let opcode = cb.query_cell();
cb.opcode_lookup(opcode.expr(), 1.expr());
let is_call = IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::CALL.expr());
let is_callcode = IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::CALLCODE.expr());
let is_delegatecall =
IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::DELEGATECALL.expr());
let is_staticcall =
IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::STATICCALL.expr());
let is_call = cb.is_eq(opcode.expr(), OpcodeId::CALL.expr());
let is_callcode = cb.is_eq(opcode.expr(), OpcodeId::CALLCODE.expr());
let is_delegatecall = cb.is_eq(opcode.expr(), OpcodeId::DELEGATECALL.expr());
let is_staticcall = cb.is_eq(opcode.expr(), OpcodeId::STATICCALL.expr());

// Use rw_counter of the step which triggers next call as its call_id.
let callee_call_id = cb.curr.state.rw_counter.clone();
Expand Down Expand Up @@ -196,9 +195,9 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {
// rwc_delta = 8 + is_delegatecall * 2 + call_gadget.rw_delta() +
// callee_reversion_info.rw_delta()
let is_insufficient_balance =
LtWordGadget::construct(cb, &caller_balance.to_word(), &call_gadget.value.to_word());
cb.is_lt_word(&caller_balance.to_word(), &call_gadget.value.to_word());
// depth < 1025
let is_depth_ok = LtGadget::construct(cb, depth.expr(), 1025.expr());
let is_depth_ok = cb.is_lt(depth.expr(), 1025.expr());

let is_precheck_ok = and::expr([
is_depth_ok.expr(),
Expand All @@ -215,18 +214,15 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {

// whether the call is to a precompiled contract.
// precompile contracts are stored from address 0x01 to 0x09.
let is_code_address_zero = IsZeroGadget::construct(cb, call_gadget.callee_address.expr());
let is_precompile_lt =
LtGadget::construct(cb, call_gadget.callee_address.expr(), 0x0A.expr());
let is_code_address_zero = cb.is_zero(call_gadget.callee_address.expr());
let is_precompile_lt = cb.is_lt(call_gadget.callee_address.expr(), 0x0A.expr());
let is_precompile = and::expr([
not::expr(is_code_address_zero.expr()),
is_precompile_lt.expr(),
]);
let precompile_return_length = cb.query_cell();
let precompile_return_length_zero =
IsZeroGadget::construct(cb, precompile_return_length.expr());
let precompile_return_data_copy_size = MinMaxGadget::construct(
cb,
let precompile_return_length_zero = cb.is_zero(precompile_return_length.expr());
let precompile_return_data_copy_size = cb.min_max(
precompile_return_length.expr(),
call_gadget.rd_address.length(),
);
Expand Down Expand Up @@ -275,10 +271,10 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {
let gas_cost = call_gadget.gas_cost_expr(is_warm_prev.expr(), is_call.expr());
// Apply EIP 150
let gas_available = cb.curr.state.gas_left.expr() - gas_cost.clone();
let one_64th_gas = ConstantDivisionGadget::construct(cb, gas_available.clone(), 64);
let one_64th_gas = cb.div_by_const(gas_available.clone(), 64);
let all_but_one_64th_gas = gas_available - one_64th_gas.quotient();
let capped_callee_gas_left =
MinMaxGadget::construct(cb, call_gadget.gas_expr(), all_but_one_64th_gas.clone());
cb.min_max(call_gadget.gas_expr(), all_but_one_64th_gas.clone());
let callee_gas_left = select::expr(
call_gadget.gas_is_u64.expr(),
capped_callee_gas_left.min(),
Expand Down Expand Up @@ -480,10 +476,10 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {
let callee_gas_left = callee_gas_left.expr()
+ call_gadget.has_value.clone() * GAS_STIPEND_CALL_WITH_VALUE.expr();

let precompile_output_word_size_div: ConstantDivisionGadget<F, N_BYTES_U64> =
ConstantDivisionGadget::construct(cb, precompile_output_rws.expr(), 32);
let precompile_output_word_size_div =
cb.div_by_const(precompile_output_rws.expr(), 32);
let precompile_output_word_size_div_remainder_zero =
IsZeroGadget::construct(cb, precompile_output_word_size_div.remainder());
cb.is_zero(precompile_output_word_size_div.remainder());
let precompile_output_word_size = precompile_output_word_size_div.quotient()
+ 1.expr()
- precompile_output_word_size_div_remainder_zero.expr();
Expand Down Expand Up @@ -891,22 +887,26 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {
self.is_call.assign(
region,
offset,
F::from(opcode.as_u64()) - F::from(OpcodeId::CALL.as_u64()),
F::from(opcode.as_u64()),
F::from(OpcodeId::CALL.as_u64()),
)?;
self.is_callcode.assign(
region,
offset,
F::from(opcode.as_u64()) - F::from(OpcodeId::CALLCODE.as_u64()),
F::from(opcode.as_u64()),
F::from(OpcodeId::CALLCODE.as_u64()),
)?;
self.is_delegatecall.assign(
region,
offset,
F::from(opcode.as_u64()) - F::from(OpcodeId::DELEGATECALL.as_u64()),
F::from(opcode.as_u64()),
F::from(OpcodeId::DELEGATECALL.as_u64()),
)?;
self.is_staticcall.assign(
region,
offset,
F::from(opcode.as_u64()) - F::from(OpcodeId::STATICCALL.as_u64()),
F::from(opcode.as_u64()),
F::from(OpcodeId::STATICCALL.as_u64()),
)?;
self.tx_id
.assign(region, offset, Value::known(F::from(tx_id.low_u64())))?;
Expand Down
4 changes: 2 additions & 2 deletions zkevm-circuits/src/evm_circuit/execution/comparator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ impl<F: Field> ExecutionGadget<F> for ComparatorGadget<F> {
let b = cb.query_word_unchecked();

// Check if opcode is EQ
let is_eq = IsEqualGadget::construct(cb, opcode.expr(), OpcodeId::EQ.expr());
let is_eq = cb.is_eq(opcode.expr(), OpcodeId::EQ.expr());
// Check if opcode is GT. For GT we swap the stack inputs so that we
// actually do greater than instead of smaller than.
let is_gt = IsEqualGadget::construct(cb, opcode.expr(), OpcodeId::GT.expr());
let is_gt = cb.is_eq(opcode.expr(), OpcodeId::GT.expr());

let word_comparison = CmpWordsGadget::construct(cb, a.clone(), b.clone());

Expand Down
20 changes: 10 additions & 10 deletions zkevm-circuits/src/evm_circuit/execution/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
Transition::{Delta, To},
},
math_gadget::{
ConstantDivisionGadget, ContractCreateGadget, IsZeroGadget, IsZeroWordGadget,
ConstantDivisionGadget, ContractCreateGadget, IsEqualGadget, IsZeroWordGadget,
LtGadget, LtWordGadget,
},
memory_gadget::{
Expand Down Expand Up @@ -53,7 +53,7 @@ pub(crate) struct CreateGadget<F, const IS_CREATE2: bool, const S: ExecutionStat
reversion_info: ReversionInfo<F>,
depth: Cell<F>,

is_create2: IsZeroGadget<F>,
is_create2: IsEqualGadget<F>,
is_success: Cell<F>,
was_warm: Cell<F>,
value: Word32Cell<F>,
Expand Down Expand Up @@ -95,7 +95,7 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
opcode.expr(),
vec![OpcodeId::CREATE2.expr(), OpcodeId::CREATE.expr()],
);
let is_create2 = IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::CREATE2.expr());
let is_create2 = cb.is_eq(opcode.expr(), OpcodeId::CREATE2.expr());

// Use rw_counter of the step which triggers next call as its call_id.
let callee_call_id = cb.curr.state.rw_counter.clone();
Expand Down Expand Up @@ -143,10 +143,9 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
);

// Pre-check: call depth, user's nonce and user's balance
let is_depth_in_range = LtGadget::construct(cb, depth.expr(), 1025.expr());
let is_insufficient_balance =
LtWordGadget::construct(cb, &caller_balance.to_word(), &value.to_word());
let is_nonce_in_range = LtGadget::construct(cb, caller_nonce.expr(), u64::MAX.expr());
let is_depth_in_range = cb.is_lt(depth.expr(), 1025.expr());
let is_insufficient_balance = cb.is_lt_word(&caller_balance.to_word(), &value.to_word());
let is_nonce_in_range = cb.is_lt(caller_nonce.expr(), u64::MAX.expr());
let is_precheck_ok = and::expr([
is_depth_in_range.expr(),
not::expr(is_insufficient_balance.expr()),
Expand All @@ -169,7 +168,7 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
);
let gas_cost = GasCost::CREATE.expr() + memory_expansion.gas_cost() + keccak_gas_cost;
let gas_remaining = cb.curr.state.gas_left.expr() - gas_cost.clone();
let gas_left = ConstantDivisionGadget::construct(cb, gas_remaining.clone(), 64);
let gas_left = cb.div_by_const(gas_remaining.clone(), 64);
let callee_gas_left = gas_remaining - gas_left.quotient();

let was_warm = cb.query_bool();
Expand Down Expand Up @@ -209,7 +208,7 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
// empty_code_hash_word))` to represent `(callee_nonce == 0 && (prev_code_hash_word
// == 0 or prev_code_hash_word == empty_code_hash_word))`
let prev_code_hash_word = prev_code_hash.to_word();
let prev_code_hash_is_zero = IsZeroWordGadget::construct(cb, &prev_code_hash_word);
let prev_code_hash_is_zero = cb.is_zero_word(&prev_code_hash_word);
cb.condition(not::expr(prev_code_hash_is_zero.expr()), |cb| {
cb.account_read(
contract_addr.to_word(),
Expand Down Expand Up @@ -525,7 +524,8 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
self.is_create2.assign(
region,
offset,
F::from(opcode.as_u64()) - F::from(OpcodeId::CREATE2.as_u64()),
F::from(opcode.as_u64()),
F::from(OpcodeId::CREATE2.as_u64()),
)?;

self.tx_id
Expand Down
11 changes: 5 additions & 6 deletions zkevm-circuits/src/evm_circuit/execution/end_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
constraint_builder::{
ConstrainBuilderCommon, EVMConstraintBuilder, StepStateTransition, Transition::Same,
},
math_gadget::{IsEqualGadget, IsZeroGadget},
math_gadget::IsEqualGadget,
not, CachedRegion, Cell,
},
witness::{Block, Call, ExecStep, Transaction},
Expand All @@ -22,7 +22,7 @@ use halo2_proofs::{circuit::Value, plonk::Error};
pub(crate) struct EndBlockGadget<F> {
total_txs: Cell<F>,
total_txs_is_max_txs: IsEqualGadget<F>,
is_empty_block: IsZeroGadget<F>,
is_empty_block: IsEqualGadget<F>,
max_rws: Cell<F>,
max_txs: Cell<F>,
}
Expand All @@ -36,10 +36,9 @@ impl<F: Field> ExecutionGadget<F> for EndBlockGadget<F> {
let max_txs = cb.query_copy_cell();
let max_rws = cb.query_copy_cell();
let total_txs = cb.query_cell();
let total_txs_is_max_txs = IsEqualGadget::construct(cb, total_txs.expr(), max_txs.expr());
let total_txs_is_max_txs = cb.is_eq(total_txs.expr(), max_txs.expr());
// Note that rw_counter starts at 1
let is_empty_block =
IsZeroGadget::construct(cb, cb.curr.state.rw_counter.clone().expr() - 1.expr());
let is_empty_block = cb.is_eq(cb.curr.state.rw_counter.clone().expr(), 1.expr());

let total_rws_before_padding = cb.curr.state.rw_counter.clone().expr() - 1.expr()
+ select::expr(
Expand Down Expand Up @@ -126,7 +125,7 @@ impl<F: Field> ExecutionGadget<F> for EndBlockGadget<F> {
step: &ExecStep,
) -> Result<(), Error> {
self.is_empty_block
.assign(region, offset, F::from(u64::from(step.rwc) - 1))?;
.assign(region, offset, F::from(u64::from(step.rwc)), F::ONE)?;
let max_rws = F::from(block.circuits_params.max_rws as u64);
let max_rws_assigned = self.max_rws.assign(region, offset, Value::known(max_rws))?;

Expand Down
4 changes: 2 additions & 2 deletions zkevm-circuits/src/evm_circuit/execution/end_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
);
let refund = cb.query_cell();
cb.tx_refund_read(tx_id.expr(), WordLoHi::from_lo_unchecked(refund.expr()));
let effective_refund = MinMaxGadget::construct(cb, max_refund.quotient(), refund.expr());
let effective_refund = cb.min_max(max_refund.quotient(), refund.expr());

// Add effective_refund * tx_gas_price back to caller's balance
let mul_gas_price_by_refund = MulWordByU64Gadget::construct(
Expand All @@ -85,7 +85,7 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
// Add gas_used * effective_tip to coinbase's balance
let coinbase = cb.query_word_unchecked();
let coinbase_code_hash = cb.query_word_unchecked();
let coinbase_code_hash_is_zero = IsZeroWordGadget::construct(cb, &coinbase_code_hash);
let coinbase_code_hash_is_zero = cb.is_zero_word(&coinbase_code_hash);
cb.account_read(
coinbase.to_word(),
AccountFieldTag::CodeHash,
Expand Down
3 changes: 1 addition & 2 deletions zkevm-circuits/src/evm_circuit/execution/error_code_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ impl<F: Field> ExecutionGadget<F> for ErrorCodeStoreGadget<F> {
);

// constrain code size > MAXCODESIZE
let max_code_size_exceed =
LtGadget::construct(cb, MAXCODESIZE.expr(), memory_address.length());
let max_code_size_exceed = cb.is_lt(MAXCODESIZE.expr(), memory_address.length());

// check must be one of CodeStoreOutOfGas or MaxCodeSizeExceeded
cb.require_in_set(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidCreationCodeGadget<F> {
cb.memory_lookup(0.expr(), memory_address.offset(), first_byte.expr(), None);

let is_first_byte_invalid =
IsEqualGadget::construct(cb, first_byte.expr(), INVALID_INIT_CODE_FIRST_BYTE.expr());
cb.is_eq(first_byte.expr(), INVALID_INIT_CODE_FIRST_BYTE.expr());
cb.require_true(
"is_first_byte_invalid is true",
is_first_byte_invalid.expr(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
vec![OpcodeId::JUMP.expr(), OpcodeId::JUMPI.expr()],
);

let is_jumpi = IsEqualGadget::construct(cb, opcode.expr(), OpcodeId::JUMPI.expr());
let is_jumpi = cb.is_eq(opcode.expr(), OpcodeId::JUMPI.expr());

// initialize is_jump_dest
let is_jump_dest = IsEqualGadget::construct(cb, value.expr(), OpcodeId::JUMPDEST.expr());
let is_jump_dest = cb.is_eq(value.expr(), OpcodeId::JUMPDEST.expr());

// first default this condition, if use will re-construct with real condition
// value
let is_condition_zero = IsZeroWordGadget::construct(cb, &condition);
let is_condition_zero = cb.is_zero_word(&condition);

// Pop the value from the stack
cb.stack_pop(dest.original_word().to_word());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ impl<F: Field> ExecutionGadget<F> for ErrorOOGAccountAccessGadget<F> {
GasCost::COLD_ACCOUNT_ACCESS.expr(),
);

let insufficient_gas_cost =
LtGadget::construct(cb, cb.curr.state.gas_left.expr(), gas_cost);
let insufficient_gas_cost = cb.is_lt(cb.curr.state.gas_left.expr(), gas_cost);

cb.require_equal(
"Gas left is less than gas cost",
Expand Down
2 changes: 1 addition & 1 deletion zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl<F: Field> ExecutionGadget<F> for ErrorOOGCallGadget<F> {
let gas_cost = call_gadget.gas_cost_expr(is_warm.expr(), is_call.expr());

// Check if the amount of gas available is less than the amount of gas required
let insufficient_gas = LtGadget::construct(cb, cb.curr.state.gas_left.expr(), gas_cost);
let insufficient_gas = cb.is_lt(cb.curr.state.gas_left.expr(), gas_cost);

cb.require_equal(
"Either Memory address is overflow or gas left is less than cost",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ impl<F: Field> ExecutionGadget<F> for ErrorOOGConstantGadget<F> {
cb.constant_gas_lookup(opcode.expr(), gas_required.expr());
// Check if the amount of gas available is less than the amount of gas
// required
let insufficient_gas =
LtGadget::construct(cb, cb.curr.state.gas_left.expr(), gas_required.expr());
let insufficient_gas = cb.is_lt(cb.curr.state.gas_left.expr(), gas_required.expr());
cb.require_equal(
"constant gas left is less than gas required ",
insufficient_gas.expr(),
Expand Down
Loading
Loading