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

[word-lo-hi] evm circuit #1411

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
53 changes: 32 additions & 21 deletions zkevm-circuits/src/evm_circuit/execution/balance.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
use crate::{
evm_circuit::{
execution::ExecutionGadget,
param::N_BYTES_ACCOUNT_ADDRESS,
step::ExecutionState,
util::{
common_gadget::SameContextGadget,
constraint_builder::{
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, ToLittleEndian, 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>,
hero78119 marked this conversation as resolved.
Show resolved Hide resolved
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 +41,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 +97,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 +119,15 @@ 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(
region,
offset,
Some(
address.to_le_bytes()[0..N_BYTES_ACCOUNT_ADDRESS]
.try_into()
.unwrap(),
),
)?;
hero78119 marked this conversation as resolved.
Show resolved Hide resolved

self.tx_id
.assign(region, offset, Value::known(F::from(tx.id as u64)))?;
Expand All @@ -133,16 +145,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