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

Commit

Permalink
[word-lo-hi] evm circuit (#1411)
Browse files Browse the repository at this point in the history
### Description

This PR is based on
#1394
Need to merge
#1394
first before review this.

### Issue Link


#1379

### Type of change
- [x] Breaking change (fix or feature that would cause existing
functionality to not work as expected)

### Contents

- [x] fixed most of op compiling errors other than `callop.rs` and
`begin_tx.rs`.
- [x] fixed `callop.rs` and `begin_tx.rs` 
- [x] remove all compatible workaround `construct_new` under evm circuit
- [x] unittest under evm circuit all pass `cargo test --features
warn-unimplemented --features test --package zkevm-circuits --lib --
evm_circuit::execution::`
- [x] fix few `word` gadgets generics to take `Word<T>` instead of `T`
to restrict it flexibility, since it's non sense to put type not related
to word
- [x] remove most of `deprecated` api under evm circuits
- [x] add IntDecomposition type as an alternative to
RandomLinearComposition, with base 256

### Cell utilization on main branch vs on word-lo-hi branch

#### Storage_1
```
Main:
+-----------------------------------+------------------------------+-------------------------+
| "storage_1" total_available_cells | "storage_1" total_used_cells | "storage_1" Utilization (%) |
+-----------------------------------+------------------------------+-------------------------+
| 25480                             | 6482                         | 25.4                    |
+-----------------------------------+------------------------------+-------------------------+

Word-lo-hi
+-----------------------------------+------------------------------+-----------------------------+
| "storage_1" total_available_cells | "storage_1" total_used_cells | "storage_1" Utilization (%) |
+-----------------------------------+------------------------------+-----------------------------+
| 24080                             | 7078                         | 29.4                        |
+-----------------------------------+------------------------------+-----------------------------+
```

#### Storage_2
```
Main
+-----------------------------------+------------------------------+-------------------------+
| "storage_2" total_available_cells | "storage_2" total_used_cells | "storage_2" Utilization |
+-----------------------------------+------------------------------+-------------------------+
| 1456                              | 467                          | 32.1                    |
+-----------------------------------+------------------------------+-------------------------+

Word-lo-hi
+-----------------------------------+------------------------------+-----------------------------+
| "storage_2" total_available_cells | "storage_2" total_used_cells | "storage_2" Utilization (%) |
+-----------------------------------+------------------------------+-----------------------------+
| 1376                              | 14                           | 1.0                         |
+-----------------------------------+------------------------------+-----------------------------+
```

#### Byte_lookup
```
Main

+-------------------------------------+--------------------------------+---------------------------+
| "byte_lookup" total_available_cells | "byte_lookup" total_used_cells | "byte_lookup" Utilization |
+-------------------------------------+--------------------------------+---------------------------+
| 8736                                | 6786                           | 77.7                      |
+-------------------------------------+--------------------------------+---------------------------+

Word-lo-hi
+-------------------------------------+--------------------------------+-------------------------------+
| "byte_lookup" total_available_cells | "byte_lookup" total_used_cells | "byte_lookup" Utilization (%) |
+-------------------------------------+--------------------------------+-------------------------------+
| 8256                                | 6566                           | 79.5                          |
+-------------------------------------+--------------------------------+-------------------------------+
```

---------

Co-authored-by: Wu Sung-Ming <[email protected]>
  • Loading branch information
hero78119 and Wu Sung-Ming authored Jun 20, 2023
1 parent fab8e2e commit 0a0d712
Show file tree
Hide file tree
Showing 103 changed files with 2,327 additions and 2,837 deletions.
10 changes: 4 additions & 6 deletions zkevm-circuits/src/copy_circuit/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ impl<F: Field> Circuit<F> for CopyCircuit<F> {
&self.external_data.txs,
self.external_data.max_txs,
self.external_data.max_calldata,
&challenge_values,
)?;

config.0.rw_table.load(
Expand All @@ -66,11 +65,10 @@ impl<F: Field> Circuit<F> for CopyCircuit<F> {
self.external_data.max_rws,
)?;

config.0.bytecode_table.load(
&mut layouter,
self.external_data.bytecodes.values(),
&challenge_values,
)?;
config
.0
.bytecode_table
.load(&mut layouter, self.external_data.bytecodes.values())?;
self.synthesize_sub(&config.0, &challenge_values, &mut layouter)
}
}
18 changes: 4 additions & 14 deletions zkevm-circuits/src/copy_circuit/util.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
use crate::evm_circuit::util::rlc;
use crate::util::word::Word;
use bus_mapping::circuit_input_builder::NumberOrHash;
use eth_types::Field;
use halo2_proofs::circuit::Value;

/// Encode the type `NumberOrHash` into a field element
pub fn number_or_hash_to_field<F: Field>(v: &NumberOrHash, challenge: Value<F>) -> Value<F> {
pub fn number_or_hash_to_word<F: Field>(v: &NumberOrHash) -> Word<Value<F>> {
match v {
NumberOrHash::Number(n) => Value::known(F::from(*n as u64)),
NumberOrHash::Hash(h) => {
// since code hash in the bytecode table is represented in
// the little-endian form, we reverse the big-endian bytes
// of H256.
let le_bytes = {
let mut b = h.to_fixed_bytes();
b.reverse();
b
};
challenge.map(|challenge| rlc::value(&le_bytes, challenge))
}
NumberOrHash::Number(n) => Word::from(*n as u64).into_value(),
NumberOrHash::Hash(h) => Word::from(*h).into_value(),
}
}
7 changes: 2 additions & 5 deletions zkevm-circuits/src/evm_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,6 @@ impl<F: Field> Circuit<F> for EvmCircuit<F> {
&block.txs,
block.circuits_params.max_txs,
block.circuits_params.max_calldata,
&challenges,
)?;
block.rws.check_rw_counter_sanity();
config.rw_table.load(
Expand All @@ -421,10 +420,8 @@ impl<F: Field> Circuit<F> for EvmCircuit<F> {
)?;
config
.bytecode_table
.load(&mut layouter, block.bytecodes.values(), &challenges)?;
config
.block_table
.load(&mut layouter, &block.context, challenges.evm_word())?;
.load(&mut layouter, block.bytecodes.values())?;
config.block_table.load(&mut layouter, &block.context)?;
config.copy_table.load(&mut layouter, block, &challenges)?;
config
.keccak_table
Expand Down
15 changes: 4 additions & 11 deletions zkevm-circuits/src/evm_circuit/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,13 @@ mod sstore;
mod stop;
mod swap;

use self::sha3::Sha3Gadget;
use self::{block_ctx::BlockCtxGadget, sha3::Sha3Gadget};
use add_sub::AddSubGadget;
use addmod::AddModGadget;
use address::AddressGadget;
use balance::BalanceGadget;
use begin_tx::BeginTxGadget;
use bitwise::BitwiseGadget;
use block_ctx::{BlockCtxU160Gadget, BlockCtxU256Gadget, BlockCtxU64Gadget};
use blockhash::BlockHashGadget;
use byte::ByteGadget;
use calldatacopy::CallDataCopyGadget;
Expand Down Expand Up @@ -281,9 +280,7 @@ pub struct ExecutionConfig<F> {
stop_gadget: Box<StopGadget<F>>,
swap_gadget: Box<SwapGadget<F>>,
blockhash_gadget: Box<BlockHashGadget<F>>,
block_ctx_u64_gadget: Box<BlockCtxU64Gadget<F>>,
block_ctx_u160_gadget: Box<BlockCtxU160Gadget<F>>,
block_ctx_u256_gadget: Box<BlockCtxU256Gadget<F>>,
block_ctx_gadget: Box<BlockCtxGadget<F>>,
// error gadgets
error_oog_call: Box<ErrorOOGCallGadget<F>>,
error_oog_constant: Box<ErrorOOGConstantGadget<F>>,
Expand Down Expand Up @@ -548,9 +545,7 @@ impl<F: Field> ExecutionConfig<F> {
sstore_gadget: configure_gadget!(),
stop_gadget: configure_gadget!(),
swap_gadget: configure_gadget!(),
block_ctx_u64_gadget: configure_gadget!(),
block_ctx_u160_gadget: configure_gadget!(),
block_ctx_u256_gadget: configure_gadget!(),
block_ctx_gadget: configure_gadget!(),
// error gadgets
error_oog_constant: configure_gadget!(),
error_oog_static_memory_gadget: configure_gadget!(),
Expand Down Expand Up @@ -1216,9 +1211,7 @@ impl<F: Field> ExecutionConfig<F> {
ExecutionState::SAR => assign_exec_step!(self.sar_gadget),
ExecutionState::SCMP => assign_exec_step!(self.signed_comparator_gadget),
ExecutionState::SDIV_SMOD => assign_exec_step!(self.sdiv_smod_gadget),
ExecutionState::BLOCKCTXU64 => assign_exec_step!(self.block_ctx_u64_gadget),
ExecutionState::BLOCKCTXU160 => assign_exec_step!(self.block_ctx_u160_gadget),
ExecutionState::BLOCKCTXU256 => assign_exec_step!(self.block_ctx_u256_gadget),
ExecutionState::BLOCKCTX => assign_exec_step!(self.block_ctx_gadget),
ExecutionState::BLOCKHASH => assign_exec_step!(self.blockhash_gadget),
ExecutionState::SELFBALANCE => assign_exec_step!(self.selfbalance_gadget),
// dummy gadgets
Expand Down
2 changes: 1 addition & 1 deletion zkevm-circuits/src/evm_circuit/execution/add_sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl<F: Field> ExecutionGadget<F> for AddSubGadget<F> {
let a = cb.query_word32();
let b = cb.query_word32();
let c = cb.query_word32();
let add_words = AddWordsGadget::construct_new(cb, [a.clone(), b.clone()], c.clone());
let add_words = AddWordsGadget::construct(cb, [a.clone(), b.clone()], c.clone());

// Swap a and c if opcode is SUB
let is_sub = PairSelectGadget::construct(
Expand Down
30 changes: 13 additions & 17 deletions zkevm-circuits/src/evm_circuit/execution/addmod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{
};

use bus_mapping::evm::OpcodeId;
use eth_types::{Field, ToLittleEndian, U256, U512};
use eth_types::{Field, U256, U512};
use halo2_proofs::{circuit::Value, plonk::Error};

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -69,11 +69,11 @@ 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.clone());
let n_is_zero = IsZeroWordGadget::construct(cb, &n);

// 1. check k * N + a_reduced == a without overflow
let muladd_k_n_areduced =
MulAddWordsGadget::construct_new(cb, [&k, &n.clone(), &a_reduced, &a]);
MulAddWordsGadget::construct(cb, [&k, &n.clone(), &a_reduced, &a]);
cb.require_zero(
"k * N + a_reduced does not overflow",
muladd_k_n_areduced.overflow(),
Expand All @@ -82,7 +82,7 @@ impl<F: Field> ExecutionGadget<F> for AddModGadget<F> {
// 2. check d * N + r == a_reduced + b, only checking carry if n != 0
let sum_areduced_b = {
let sum = cb.query_word32();
AddWordsGadget::construct_new(cb, [a_reduced.clone(), b.clone()], sum)
AddWordsGadget::construct(cb, [a_reduced.clone(), b.clone()], sum)
};
let sum_areduced_b_overflow = cb.query_word32();
let muladd_d_n_r = MulAddWords512Gadget::construct(
Expand Down Expand Up @@ -162,9 +162,9 @@ impl<F: Field> ExecutionGadget<F> for AddModGadget<F> {
let [mut r, n, b, a] = [3, 2, 1, 0].map(|index| block.get_rws(step, index).stack_value());

// assing a,b & n stack values
self.a.assign(region, offset, Some(a.to_le_bytes()))?;
self.b.assign(region, offset, Some(b.to_le_bytes()))?;
self.n.assign(region, offset, Some(n.to_le_bytes()))?;
self.a.assign_u256(region, offset, a)?;
self.b.assign_u256(region, offset, b)?;
self.n.assign_u256(region, offset, n)?;

// compute a_reduced,k,d,a_reduced_plus_b,a_reduced_plus_b_overflow,r values
let a_reduced;
Expand Down Expand Up @@ -196,23 +196,19 @@ impl<F: Field> ExecutionGadget<F> for AddModGadget<F> {

// rest of values and gadgets

self.r.assign(region, offset, Some(r.to_le_bytes()))?;
self.k.assign(region, offset, Some(k.to_le_bytes()))?;
self.d.assign(region, offset, Some(d.to_le_bytes()))?;
self.a_reduced
.assign(region, offset, Some(a_reduced.to_le_bytes()))?;
self.r.assign_u256(region, offset, r)?;
self.k.assign_u256(region, offset, k)?;
self.d.assign_u256(region, offset, d)?;
self.a_reduced.assign_u256(region, offset, a_reduced)?;

self.muladd_k_n_areduced
.assign(region, offset, [k, n, a_reduced, a])?;

self.sum_areduced_b
.assign(region, offset, [a_reduced, b], a_reduced_plus_b)?;

self.sum_areduced_b_overflow.assign(
region,
offset,
Some(a_reduced_plus_b_overflow.to_le_bytes()),
)?;
self.sum_areduced_b_overflow
.assign_u256(region, offset, a_reduced_plus_b_overflow)?;
self.muladd_d_n_r.assign(
region,
offset,
Expand Down
20 changes: 10 additions & 10 deletions zkevm-circuits/src/evm_circuit/execution/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@ use crate::{
util::{
common_gadget::SameContextGadget,
constraint_builder::{EVMConstraintBuilder, StepStateTransition, Transition::Delta},
AccountAddress, CachedRegion,
CachedRegion,
},
witness::{Block, Call, ExecStep, Transaction},
},
table::CallContextFieldTag,
util::{word::WordExpr, Expr},
util::{
word::{WordCell, WordExpr},
Expr,
},
};
use bus_mapping::evm::OpcodeId;
use eth_types::{Field, ToAddress, ToLittleEndian};
use eth_types::{Field, ToAddress};
use halo2_proofs::plonk::Error;

#[derive(Clone, Debug)]
pub(crate) struct AddressGadget<F> {
same_context: SameContextGadget<F>,
address: AccountAddress<F>,
address: WordCell<F>,
}

impl<F: Field> ExecutionGadget<F> for AddressGadget<F> {
Expand All @@ -28,7 +31,7 @@ impl<F: Field> ExecutionGadget<F> for AddressGadget<F> {
const EXECUTION_STATE: ExecutionState = ExecutionState::ADDRESS;

fn configure(cb: &mut EVMConstraintBuilder<F>) -> Self {
let address = cb.query_account_address();
let address = cb.query_word_unchecked();

// Lookup callee address in call context.
cb.call_context_lookup_read(None, CallContextFieldTag::CalleeAddress, address.to_word());
Expand Down Expand Up @@ -66,11 +69,8 @@ impl<F: Field> ExecutionGadget<F> for AddressGadget<F> {
let address = block.get_rws(step, 1).stack_value();
debug_assert_eq!(call.address, address.to_address());

self.address.assign(
region,
offset,
Some(address.to_le_bytes()[..20].try_into().unwrap()),
)?;
self.address
.assign_h160(region, offset, address.to_address())?;

Ok(())
}
Expand Down
44 changes: 23 additions & 21 deletions zkevm-circuits/src/evm_circuit/execution/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,29 @@ use crate::{
ConstrainBuilderCommon, EVMConstraintBuilder, ReversionInfo, StepStateTransition,
Transition::Delta,
},
math_gadget::IsZeroGadget,
not, select, CachedRegion, Cell, Word,
math_gadget::IsZeroWordGadget,
not, select, AccountAddress, CachedRegion, Cell,
},
witness::{Block, Call, ExecStep, Transaction},
},
table::{AccountFieldTag, CallContextFieldTag},
util::{
word::{Word32Cell, WordExpr},
word::{Word, Word32Cell, WordCell, WordExpr},
Expr,
},
};
use eth_types::{evm_types::GasCost, Field, ToLittleEndian};
use eth_types::{evm_types::GasCost, Field, ToWord};
use halo2_proofs::{circuit::Value, plonk::Error};

#[derive(Clone, Debug)]
pub(crate) struct BalanceGadget<F> {
same_context: SameContextGadget<F>,
address_word: Word<F>,
address: AccountAddress<F>,
reversion_info: ReversionInfo<F>,
tx_id: Cell<F>,
is_warm: Cell<F>,
code_hash: Word32Cell<F>,
not_exists: IsZeroGadget<F>,
code_hash: WordCell<F>,
not_exists: IsZeroWordGadget<F, WordCell<F>>,
balance: Word32Cell<F>,
}

Expand All @@ -40,31 +40,35 @@ impl<F: Field> ExecutionGadget<F> for BalanceGadget<F> {
const EXECUTION_STATE: ExecutionState = ExecutionState::BALANCE;

fn configure(cb: &mut EVMConstraintBuilder<F>) -> Self {
let address = cb.query_word_rlc();
let address = cb.query_account_address();
cb.stack_pop_word(address.to_word());

let tx_id = cb.call_context(None, CallContextFieldTag::TxId);
let mut reversion_info = cb.reversion_info_read(None);
let is_warm = cb.query_bool();
cb.account_access_list_write(
cb.account_access_list_write_unchecked(
tx_id.expr(),
address.expr(),
address.to_word(),
1.expr(),
is_warm.expr(),
Some(&mut reversion_info),
);
let code_hash = cb.query_word32();
let code_hash = cb.query_word_unchecked();
// For non-existing accounts the code_hash must be 0 in the rw_table.
cb.account_read_word(
address.expr(),
address.to_word(),
AccountFieldTag::CodeHash,
code_hash.to_word(),
);
let not_exists = IsZeroGadget::construct(cb, code_hash.expr());
let not_exists = IsZeroWordGadget::construct(cb, &code_hash);
let exists = not::expr(not_exists.expr());
let balance = cb.query_word32();
cb.condition(exists.expr(), |cb| {
cb.account_read_word(address.expr(), AccountFieldTag::Balance, balance.to_word());
cb.account_read_word(
address.to_word(),
AccountFieldTag::Balance,
balance.to_word(),
);
});
cb.condition(not_exists.expr(), |cb| {
cb.require_zero_word("balance is zero when non_exists", balance.to_word());
Expand Down Expand Up @@ -92,7 +96,7 @@ impl<F: Field> ExecutionGadget<F> for BalanceGadget<F> {

Self {
same_context,
address_word: address,
address,
reversion_info,
tx_id,
is_warm,
Expand All @@ -114,8 +118,7 @@ impl<F: Field> ExecutionGadget<F> for BalanceGadget<F> {
self.same_context.assign_exec_step(region, offset, step)?;

let address = block.get_rws(step, 0).stack_value();
self.address_word
.assign(region, offset, Some(address.to_le_bytes()))?;
self.address.assign_u256(region, offset, address)?;

self.tx_id
.assign(region, offset, Value::known(F::from(tx.id as u64)))?;
Expand All @@ -133,16 +136,15 @@ impl<F: Field> ExecutionGadget<F> for BalanceGadget<F> {

let code_hash = block.get_rws(step, 5).account_value_pair().0;
self.code_hash
.assign(region, offset, Some(code_hash.to_le_bytes()))?;
.assign_u256(region, offset, code_hash.to_word())?;
self.not_exists
.assign_value(region, offset, region.word_rlc(code_hash))?;
.assign_value(region, offset, Value::known(Word::from(code_hash)))?;
let balance = if code_hash.is_zero() {
eth_types::Word::zero()
} else {
block.get_rws(step, 6).account_value_pair().0
};
self.balance
.assign(region, offset, Some(balance.to_le_bytes()))?;
self.balance.assign_u256(region, offset, balance)?;

Ok(())
}
Expand Down
Loading

0 comments on commit 0a0d712

Please sign in to comment.