From 6d1b2589d25ee6ad44a0cf057a539447c3da19ea Mon Sep 17 00:00:00 2001 From: adria0 Date: Tue, 13 Dec 2022 12:48:13 +0100 Subject: [PATCH 01/18] Challange in EVM circuit WIP --- Cargo.lock | 6 - Cargo.toml | 2 +- bus-mapping/Cargo.toml | 2 +- circuit-benchmarks/Cargo.toml | 2 +- eth-types/Cargo.toml | 2 +- gadgets/Cargo.toml | 2 +- integration-tests/Cargo.toml | 2 +- testool/Cargo.toml | 2 +- zkevm-circuits/Cargo.toml | 10 +- zkevm-circuits/src/evm_circuit.rs | 72 +++--- zkevm-circuits/src/evm_circuit/execution.rs | 92 +++++--- .../src/evm_circuit/execution/add_sub.rs | 6 +- .../src/evm_circuit/execution/addmod.rs | 25 +-- .../src/evm_circuit/execution/address.rs | 2 +- .../src/evm_circuit/execution/begin_tx.rs | 39 ++-- .../src/evm_circuit/execution/bitwise.rs | 6 +- .../src/evm_circuit/execution/block_ctx.rs | 2 +- .../src/evm_circuit/execution/blockhash.rs | 4 +- .../src/evm_circuit/execution/byte.rs | 4 +- .../src/evm_circuit/execution/calldatacopy.rs | 10 +- .../src/evm_circuit/execution/calldataload.rs | 9 +- .../src/evm_circuit/execution/calldatasize.rs | 2 +- .../src/evm_circuit/execution/caller.rs | 2 +- .../src/evm_circuit/execution/callop.rs | 98 +++++---- .../src/evm_circuit/execution/callvalue.rs | 16 +- .../src/evm_circuit/execution/chainid.rs | 16 +- .../src/evm_circuit/execution/codecopy.rs | 10 +- .../src/evm_circuit/execution/codesize.rs | 7 +- .../src/evm_circuit/execution/comparator.rs | 4 +- .../src/evm_circuit/execution/dummy.rs | 4 +- .../src/evm_circuit/execution/dup.rs | 17 +- .../src/evm_circuit/execution/end_tx.rs | 4 +- .../execution/error_invalid_jump.rs | 24 +- .../evm_circuit/execution/error_oog_call.rs | 100 ++++----- .../execution/error_oog_static_memory.rs | 2 +- .../src/evm_circuit/execution/exp.rs | 10 +- .../src/evm_circuit/execution/extcodehash.rs | 24 +- .../src/evm_circuit/execution/gas.rs | 2 +- .../src/evm_circuit/execution/gasprice.rs | 14 +- .../src/evm_circuit/execution/is_zero.rs | 12 +- .../src/evm_circuit/execution/jump.rs | 2 +- .../src/evm_circuit/execution/jumpi.rs | 24 +- .../src/evm_circuit/execution/logs.rs | 31 ++- .../src/evm_circuit/execution/memory.rs | 4 +- .../src/evm_circuit/execution/msize.rs | 2 +- .../src/evm_circuit/execution/mul_div_mod.rs | 8 +- .../src/evm_circuit/execution/mulmod.rs | 19 +- .../src/evm_circuit/execution/not.rs | 4 +- .../src/evm_circuit/execution/origin.rs | 2 +- .../src/evm_circuit/execution/pc.rs | 2 +- .../src/evm_circuit/execution/pop.rs | 24 +- .../src/evm_circuit/execution/push.rs | 2 +- .../evm_circuit/execution/return_revert.rs | 20 +- .../evm_circuit/execution/returndatacopy.rs | 10 +- .../evm_circuit/execution/returndatasize.rs | 2 +- .../src/evm_circuit/execution/selfbalance.rs | 24 +- .../src/evm_circuit/execution/sha3.rs | 20 +- .../src/evm_circuit/execution/shl_shr.rs | 10 +- .../execution/signed_comparator.rs | 4 +- .../src/evm_circuit/execution/signextend.rs | 13 +- .../src/evm_circuit/execution/sload.rs | 64 ++---- .../src/evm_circuit/execution/sstore.rs | 205 ++++++------------ .../src/evm_circuit/execution/swap.rs | 34 ++- zkevm-circuits/src/evm_circuit/param.rs | 6 + zkevm-circuits/src/evm_circuit/step.rs | 42 ++-- zkevm-circuits/src/evm_circuit/util.rs | 121 ++++++++--- .../src/evm_circuit/util/common_gadget.rs | 16 +- .../evm_circuit/util/constraint_builder.rs | 71 ++++-- .../src/evm_circuit/util/math_gadget.rs | 109 ++++++++-- .../src/evm_circuit/util/memory_gadget.rs | 7 +- zkevm-circuits/src/state_circuit.rs | 9 +- zkevm-circuits/src/super_circuit.rs | 17 +- zkevm-circuits/src/table.rs | 9 +- zkevm-circuits/src/witness/block.rs | 93 ++++---- zkevm-circuits/src/witness/rw.rs | 4 + 75 files changed, 882 insertions(+), 821 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a881ed913e..a1580c1b39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1166,7 +1166,6 @@ dependencies = [ [[package]] name = "ecc" version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2022_09_09#2d708b4453387f03059aad68d6d87441db112a2f" dependencies = [ "group", "integer", @@ -1180,7 +1179,6 @@ dependencies = [ [[package]] name = "ecdsa" version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2022_09_09#2d708b4453387f03059aad68d6d87441db112a2f" dependencies = [ "ecc", "group", @@ -1983,7 +1981,6 @@ dependencies = [ [[package]] name = "halo2_proofs" version = "0.2.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2022_09_10#a9e99a72a65d7c98e8a4258c2c94269c834d1c10" dependencies = [ "blake2b_simd", "ff", @@ -2014,7 +2011,6 @@ dependencies = [ [[package]] name = "halo2wrong" version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2022_09_09#2d708b4453387f03059aad68d6d87441db112a2f" dependencies = [ "group", "halo2_proofs 0.2.0", @@ -2319,7 +2315,6 @@ dependencies = [ [[package]] name = "integer" version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2022_09_09#2d708b4453387f03059aad68d6d87441db112a2f" dependencies = [ "group", "maingate", @@ -2569,7 +2564,6 @@ dependencies = [ [[package]] name = "maingate" version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2022_09_09#2d708b4453387f03059aad68d6d87441db112a2f" dependencies = [ "group", "halo2wrong", diff --git a/Cargo.toml b/Cargo.toml index 830e7f7119..d28a358ecb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ members = [ ] [patch.crates-io] -halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } +halo2_proofs = { path = "../halo2/halo2_proofs" } # Definition of benchmarks profile to use. [profile.bench] diff --git a/bus-mapping/Cargo.toml b/bus-mapping/Cargo.toml index 740ce57505..eb74761172 100644 --- a/bus-mapping/Cargo.toml +++ b/bus-mapping/Cargo.toml @@ -13,7 +13,7 @@ mock = { path = "../mock", optional = true } ethers-core = "0.17.0" ethers-providers = "0.17.0" -halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } +halo2_proofs = { path = "../../halo2/halo2_proofs" } itertools = "0.10" lazy_static = "1.4" log = "0.4.14" diff --git a/circuit-benchmarks/Cargo.toml b/circuit-benchmarks/Cargo.toml index f81a7c4a18..f02b6e7da6 100644 --- a/circuit-benchmarks/Cargo.toml +++ b/circuit-benchmarks/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } +halo2_proofs = { path = "../../halo2/halo2_proofs" } ark-std = { version = "0.3", features = ["print-trace"] } zkevm-circuits = { path = "../zkevm-circuits", features = ["test"]} keccak256 = { path = "../keccak256" } diff --git a/eth-types/Cargo.toml b/eth-types/Cargo.toml index 56a5abf922..ca6905d30d 100644 --- a/eth-types/Cargo.toml +++ b/eth-types/Cargo.toml @@ -10,7 +10,7 @@ ethers-core = "0.17.0" ethers-signers = "0.17.0" hex = "0.4" lazy_static = "1.4" -halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } +halo2_proofs = { path = "../../halo2/halo2_proofs" } regex = "1.5.4" serde = {version = "1.0.130", features = ["derive"] } serde_json = "1.0.66" diff --git a/gadgets/Cargo.toml b/gadgets/Cargo.toml index 3e72f464c5..ea844fa2c7 100644 --- a/gadgets/Cargo.toml +++ b/gadgets/Cargo.toml @@ -6,7 +6,7 @@ authors = ["The appliedzkp team"] license = "MIT OR Apache-2.0" [dependencies] -halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } +halo2_proofs = { path = "../../halo2/halo2_proofs" } sha3 = "0.7.2" eth-types = { path = "../eth-types" } digest = "0.7.6" diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index c2c84b8004..84815e2313 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -19,7 +19,7 @@ url = "2.2.2" pretty_assertions = "1.0.0" log = "0.4.14" env_logger = "0.9" -halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } +halo2_proofs = { path = "../../halo2/halo2_proofs" } rand_chacha = "0.3" paste = "1.0" diff --git a/testool/Cargo.toml b/testool/Cargo.toml index dccaad037d..5dff220027 100644 --- a/testool/Cargo.toml +++ b/testool/Cargo.toml @@ -33,7 +33,7 @@ yaml-rust = "0.4.5" zkevm-circuits = { path="../zkevm-circuits", features=["test"] } rand_chacha = "0.3" rand = "0.8" -halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } +halo2_proofs = { path = "../../halo2/halo2_proofs" } [features] diff --git a/zkevm-circuits/Cargo.toml b/zkevm-circuits/Cargo.toml index c56005a6d5..be426b6d8b 100644 --- a/zkevm-circuits/Cargo.toml +++ b/zkevm-circuits/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } +halo2_proofs = { path = "../../halo2/halo2_proofs" } num = "0.4" sha3 = "0.10" array-init = "2.0.0" @@ -27,10 +27,10 @@ lazy_static = "1.4" keccak256 = { path = "../keccak256"} log = "0.4" env_logger = "0.9" -ecdsa = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2022_09_09" } -ecc = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2022_09_09" } -maingate = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2022_09_09" } -integer = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2022_09_09" } +ecdsa = { path = "../../halo2wrong/ecdsa" } +ecc = { path = "../../halo2wrong/ecc" } +maingate = { path = "../../halo2wrong/maingate" } +integer = { path = "../../halo2wrong/integer" } libsecp256k1 = "0.7" num-bigint = { version = "0.4" } subtle = "2.4" diff --git a/zkevm-circuits/src/evm_circuit.rs b/zkevm-circuits/src/evm_circuit.rs index 9934047284..ff535922ef 100644 --- a/zkevm-circuits/src/evm_circuit.rs +++ b/zkevm-circuits/src/evm_circuit.rs @@ -41,8 +41,8 @@ pub struct EvmCircuitConfig { /// Circuit configuration arguments pub struct EvmCircuitConfigArgs { - /// Power of randomness - pub power_of_randomness: [Expression; 31], + /// Challenge + pub challenges: Challenges>, /// TxTable pub tx_table: TxTable, /// RwTable @@ -67,7 +67,7 @@ impl SubCircuitConfig for EvmCircuitConfig { fn new( meta: &mut ConstraintSystem, Self::ConfigArgs { - power_of_randomness, + challenges, tx_table, rw_table, bytecode_table, @@ -81,7 +81,7 @@ impl SubCircuitConfig for EvmCircuitConfig { let byte_table = [(); 1].map(|_| meta.fixed_column()); let execution = Box::new(ExecutionConfig::configure( meta, - power_of_randomness, + challenges, &fixed_table, &byte_table, &tx_table, @@ -215,14 +215,14 @@ impl SubCircuit for EvmCircuit { fn synthesize_sub( &self, config: &Self::Config, - _challenges: &Challenges>, + challenges: &Challenges>, layouter: &mut impl Layouter, ) -> Result<(), Error> { let block = self.block.as_ref().unwrap(); config.load_fixed_table(layouter, self.fixed_table_tags.clone())?; config.load_byte_table(layouter)?; - config.execution.assign_block(layouter, block) + config.execution.assign_block(layouter, block, challenges) } } @@ -232,13 +232,13 @@ pub mod test { use crate::{ evm_circuit::{table::FixedTableTag, witness::Block, EvmCircuitConfig}, table::{BlockTable, BytecodeTable, CopyTable, ExpTable, KeccakTable, RwTable, TxTable}, - util::{power_of_randomness_from_instance, Challenges}, + util::Challenges, witness::block_convert, }; use bus_mapping::{circuit_input_builder::CircuitsParams, evm::OpcodeId, mock::BlockData}; use eth_types::{geth_types::GethData, Field, Word}; use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, + circuit::{Layouter, SimpleFloorPlanner}, dev::{MockProver, VerifyFailure}, plonk::{Circuit, ConstraintSystem, Error}, }; @@ -294,7 +294,7 @@ pub mod test { } impl Circuit for EvmCircuit { - type Config = EvmCircuitConfig; + type Config = (EvmCircuitConfig, Challenges); type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -310,20 +310,24 @@ pub mod test { let copy_table = CopyTable::construct(meta, q_copy_table); let keccak_table = KeccakTable::construct(meta); let exp_table = ExpTable::construct(meta); - - let power_of_randomness = power_of_randomness_from_instance(meta); - EvmCircuitConfig::new( - meta, - EvmCircuitConfigArgs { - power_of_randomness, - tx_table, - rw_table, - bytecode_table, - block_table, - copy_table, - keccak_table, - exp_table, - }, + let challenges = Challenges::construct(meta); + let challenges_expr = challenges.exprs(meta); + + ( + EvmCircuitConfig::new( + meta, + EvmCircuitConfigArgs { + challenges: challenges_expr, + tx_table, + rw_table, + bytecode_table, + block_table, + copy_table, + keccak_table, + exp_table, + }, + ), + challenges, ) } @@ -333,10 +337,9 @@ pub mod test { mut layouter: impl Layouter, ) -> Result<(), Error> { let block = self.block.as_ref().unwrap(); - let challenges = Challenges::mock( - Value::known(block.randomness), - Value::known(block.randomness), - ); + + let (config, challenges) = config; + let challenges = challenges.values(&mut layouter); config.tx_table.load( &mut layouter, @@ -349,14 +352,14 @@ pub mod test { &mut layouter, &block.rws.table_assignments(), block.circuits_params.max_rws, - Value::known(block.randomness), + challenges.evm_word(), )?; config .bytecode_table .load(&mut layouter, block.bytecodes.values(), &challenges)?; config .block_table - .load(&mut layouter, &block.context, block.randomness)?; + .load(&mut layouter, &block.context, challenges.evm_word())?; config.copy_table.load(&mut layouter, block, &challenges)?; config .keccak_table @@ -371,13 +374,13 @@ pub mod test { pub fn get_num_rows_required(block: &Block) -> usize { let mut cs = ConstraintSystem::default(); let config = EvmCircuit::::configure(&mut cs); - config.get_num_rows_required(block) + config.0.get_num_rows_required(block) } pub fn get_active_rows(block: &Block) -> (Vec, Vec) { let mut cs = ConstraintSystem::default(); let config = EvmCircuit::::configure(&mut cs); - config.get_active_rows(block) + config.0.get_active_rows(block) } } @@ -432,12 +435,9 @@ pub mod test { let k = k.max(log2_ceil(NUM_BLINDING_ROWS + block.circuits_params.max_rws)); log::debug!("evm circuit uses k = {}", k); - let power_of_randomness = (1..32) - .map(|exp| vec![block.randomness.pow(&[exp, 0, 0, 0]); (1 << k) - 64]) - .collect(); let (active_gate_rows, active_lookup_rows) = EvmCircuit::::get_active_rows(&block); let circuit = EvmCircuit::::new_dev(block, fixed_table_tags); - let prover = MockProver::::run(k, &circuit, power_of_randomness).unwrap(); + let prover = MockProver::::run(k, &circuit, vec![]).unwrap(); prover.verify_at_rows_par(active_gate_rows.into_iter(), active_lookup_rows.into_iter()) } } @@ -478,7 +478,7 @@ mod evm_circuit_stats { let mut implemented_states = Vec::new(); for state in ExecutionState::iter() { - let height = circuit.execution.get_step_height_option(state); + let height = circuit.0.execution.get_step_height_option(state); if let Some(h) = height { implemented_states.push((state, h)); } diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 99b7c85013..e25ad501a0 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -1,7 +1,7 @@ use super::util::{CachedRegion, CellManager, StoredExpression}; use crate::{ evm_circuit::{ - param::{MAX_STEP_HEIGHT, STEP_WIDTH}, + param::{MAX_STEP_HEIGHT, N_PHASE2_COLUMNS, N_PHASE3_COLUMNS, STEP_WIDTH}, step::{ExecutionState, Step}, table::Table, util::{ @@ -11,14 +11,17 @@ use crate::{ witness::{Block, Call, ExecStep, Transaction}, }, table::LookupTable, - util::{query_expression, Expr}, + util::{query_expression, Challenges, Expr}, }; use eth_types::Field; use gadgets::util::not; use halo2_proofs::{ arithmetic::FieldExt, circuit::{Layouter, Region, Value}, - plonk::{Advice, Column, ConstraintSystem, Error, Expression, Fixed, Selector, VirtualCells}, + plonk::{ + Advice, Column, ConstraintSystem, Error, Expression, FirstPhase, Fixed, SecondPhase, + Selector, ThirdPhase, VirtualCells, + }, poly::Rotation, }; use std::{ @@ -284,7 +287,7 @@ impl ExecutionConfig { #[allow(clippy::too_many_arguments)] pub(crate) fn configure( meta: &mut ConstraintSystem, - power_of_randomness: [Expression; 31], + challenges: Challenges>, fixed_table: &dyn LookupTable, byte_table: &dyn LookupTable, tx_table: &dyn LookupTable, @@ -303,7 +306,22 @@ impl ExecutionConfig { let num_rows_inv = meta.advice_column(); let q_step_first = meta.complex_selector(); let q_step_last = meta.complex_selector(); - let advices = [(); STEP_WIDTH].map(|_| meta.advice_column()); + let advices = [(); STEP_WIDTH] + .iter() + .enumerate() + .map(|(n, _)| { + if n < N_PHASE3_COLUMNS { + meta.advice_column_in(ThirdPhase) + } else if n < N_PHASE3_COLUMNS + N_PHASE2_COLUMNS { + meta.advice_column_in(SecondPhase) + } else { + meta.advice_column_in(FirstPhase) + } + }) + .collect::>() + .try_into() + .unwrap(); + let step_curr = Step::new(meta, advices, 0, false); let mut height_map = HashMap::new(); @@ -390,10 +408,12 @@ impl ExecutionConfig { }); let mut stored_expressions_map = HashMap::new(); + let step_next = Step::new(meta, advices, MAX_STEP_HEIGHT, true); + let word_powers_of_randomness : [Expression;31] = challenges.evm_word_powers_of_randomness(); macro_rules! configure_gadget { () => { - Self::configure_gadget( + Self::configure_gadget( meta, advices, q_usable, @@ -401,7 +421,8 @@ impl ExecutionConfig { num_rows_until_next_step, q_step_first, q_step_last, - &power_of_randomness, + &challenges, + &word_powers_of_randomness, &step_curr, &step_next, &mut height_map, @@ -411,6 +432,7 @@ impl ExecutionConfig { } let cell_manager = step_curr.cell_manager.clone(); + let config = Self { q_usable, q_step, @@ -529,10 +551,9 @@ impl ExecutionConfig { copy_table, keccak_table, exp_table, - &power_of_randomness, + &challenges, &cell_manager, ); - config } @@ -554,19 +575,21 @@ impl ExecutionConfig { num_rows_until_next_step: Column, q_step_first: Selector, q_step_last: Selector, - power_of_randomness: &[Expression; 31], + challenges: &Challenges>, + word_power_of_randomness: &[Expression;31], step_curr: &Step, step_next: &Step, height_map: &mut HashMap, stored_expressions_map: &mut HashMap>>, ) -> G { // Configure the gadget with the max height first so we can find out the actual - // height + // heightn let height = { let mut cb = ConstraintBuilder::new( step_curr.clone(), step_next.clone(), - power_of_randomness, + challenges, + word_power_of_randomness, G::EXECUTION_STATE, ); G::configure(&mut cb); @@ -579,7 +602,8 @@ impl ExecutionConfig { let mut cb = ConstraintBuilder::new( step_curr.clone(), step_next.clone(), - power_of_randomness, + &challenges, + word_power_of_randomness, G::EXECUTION_STATE, ); @@ -600,6 +624,7 @@ impl ExecutionConfig { !height_map.contains_key(&G::EXECUTION_STATE), "execution state already configured" ); + height_map.insert(G::EXECUTION_STATE, height); debug_assert!( !stored_expressions_map.contains_key(&G::EXECUTION_STATE), @@ -617,6 +642,7 @@ impl ExecutionConfig { let sel_not_step_last: &dyn Fn(&mut VirtualCells) -> Expression = &|meta| { meta.query_advice(q_step, Rotation::cur()) * not::expr(meta.query_selector(q_step_last)) }; + for (selector, constraints) in [ (sel_step, constraints.step), (sel_step_first, constraints.step_first), @@ -709,9 +735,10 @@ impl ExecutionConfig { copy_table: &dyn LookupTable, keccak_table: &dyn LookupTable, exp_table: &dyn LookupTable, - power_of_randomness: &[Expression; 31], + challenges: &Challenges>, cell_manager: &CellManager, ) { + let powers_of_randomness: [Expression; 31] = challenges.evm_word_powers_of_randomness(); for column in cell_manager.columns().iter() { if let CellType::Lookup(table) = column.cell_type { let name = format!("{:?}", table); @@ -730,7 +757,7 @@ impl ExecutionConfig { .table_exprs(meta); vec![( column.expr(), - rlc::expr(&table_expressions, power_of_randomness), + rlc::expr(&table_expressions, &powers_of_randomness), )] }); } @@ -744,13 +771,8 @@ impl ExecutionConfig { &self, layouter: &mut impl Layouter, block: &Block, + challenges: &Challenges>, ) -> Result<(), Error> { - let power_of_randomness = (1..32) - .map(|exp| block.randomness.pow(&[exp, 0, 0, 0])) - .collect::>() - .try_into() - .unwrap(); - layouter.assign_region( || "Execution step", |mut region| { @@ -822,7 +844,7 @@ impl ExecutionConfig { step, height, next, - power_of_randomness, + challenges, )?; // q_step logic @@ -904,7 +926,7 @@ impl ExecutionConfig { step: &ExecStep, height: usize, next: Option<(&Transaction, &Call, &ExecStep)>, - power_of_randomness: [F; 31], + challenges: &Challenges>, ) -> Result<(), Error> { if !matches!(step.execution_state, ExecutionState::EndBlock) { log::trace!( @@ -920,7 +942,7 @@ impl ExecutionConfig { // enough for 3 steps. let region = &mut CachedRegion::<'_, '_, F>::new( region, - power_of_randomness, + challenges, STEP_WIDTH, MAX_STEP_HEIGHT * 3, self.advices[0].index(), @@ -1126,7 +1148,12 @@ impl ExecutionConfig { // enable with `RUST_LOG=debug` if log::log_enabled!(log::Level::Debug) { // expensive function call - Self::check_rw_lookup(&assigned_stored_expressions, step, block); + Self::check_rw_lookup( + &assigned_stored_expressions, + step, + block, + region.challenges(), + ); } Ok(()) } @@ -1156,6 +1183,7 @@ impl ExecutionConfig { assigned_stored_expressions: &[(String, F)], step: &ExecStep, block: &Block, + challenges: &Challenges>, ) { let mut assigned_rw_values = Vec::new(); // Reversion lookup expressions have different ordering compared to rw table, @@ -1176,21 +1204,24 @@ impl ExecutionConfig { .table_assignments() .iter() .map(|rw| { - rw.table_assignment_aux(block.randomness) - .rlc(block.randomness) + challenges + .evm_word() + .map(|randomness| rw.table_assignment_aux(randomness).rlc(randomness)) }) .collect(); + // [TODO] Check this for (name, value) in assigned_rw_values.iter() { - if !rlc_assignments.contains(value) { + if !rlc_assignments.contains(&Value::known(*value)) { log::error!("rw lookup error: name: {}, step: {:?}", *name, step); } } + challenges.evm_word().map(|randomness| { for (idx, assigned_rw_value) in assigned_rw_values.iter().enumerate() { let rw_idx = step.rw_indices[idx]; let rw = block.rws[rw_idx]; - let table_assignments = rw.table_assignment_aux(block.randomness); - let rlc = table_assignments.rlc(block.randomness); + let table_assignments = rw.table_assignment_aux(randomness); + let rlc = table_assignments.rlc(randomness); if rlc != assigned_rw_value.1 { log::error!( "incorrect rw witness. lookup input name: \"{}\"\n{:?}\nrw: {:?}, rw index: {:?}, {}th rw of step {:?}", @@ -1202,5 +1233,6 @@ impl ExecutionConfig { step.execution_state); } } + }); } } diff --git a/zkevm-circuits/src/evm_circuit/execution/add_sub.rs b/zkevm-circuits/src/evm_circuit/execution/add_sub.rs index 47e68c7074..fed97020e3 100644 --- a/zkevm-circuits/src/evm_circuit/execution/add_sub.rs +++ b/zkevm-circuits/src/evm_circuit/execution/add_sub.rs @@ -35,9 +35,9 @@ impl ExecutionGadget for AddSubGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let opcode = cb.query_cell(); - let a = cb.query_word(); - let b = cb.query_word(); - let c = cb.query_word(); + let a = cb.query_word_rlc(); + let b = cb.query_word_rlc(); + let c = cb.query_word_rlc(); let add_words = AddWordsGadget::construct(cb, [a.clone(), b.clone()], c.clone()); // Swap a and c if opcode is SUB diff --git a/zkevm-circuits/src/evm_circuit/execution/addmod.rs b/zkevm-circuits/src/evm_circuit/execution/addmod.rs index 449d6172c6..eee053570c 100644 --- a/zkevm-circuits/src/evm_circuit/execution/addmod.rs +++ b/zkevm-circuits/src/evm_circuit/execution/addmod.rs @@ -53,15 +53,15 @@ impl ExecutionGadget for AddModGadget { let opcode = cb.query_cell(); // values got from stack (original r is modified if n==0) - let a = cb.query_word(); - let b = cb.query_word(); - let n = cb.query_word(); - let r = cb.query_word(); + let a = cb.query_word_rlc(); + let b = cb.query_word_rlc(); + let n = cb.query_word_rlc(); + let r = cb.query_word_rlc(); // auxiliar witness - let k = cb.query_word(); - let a_reduced = cb.query_word(); - let d = cb.query_word(); + let k = cb.query_word_rlc(); + let a_reduced = cb.query_word_rlc(); + let d = cb.query_word_rlc(); let n_is_zero = IsZeroGadget::construct(cb, n.clone().expr()); @@ -74,10 +74,10 @@ impl ExecutionGadget for AddModGadget { // 2. check d * N + r == a_reduced + b, only checking carry if n != 0 let sum_areduced_b = { - let sum = cb.query_word(); + let sum = cb.query_word_rlc(); AddWordsGadget::construct(cb, [a_reduced.clone(), b.clone()], sum) }; - let sum_areduced_b_overflow = cb.query_word(); + let sum_areduced_b_overflow = cb.query_word_rlc(); let muladd_d_n_r = MulAddWords512Gadget::construct( cb, [&d, &n, &sum_areduced_b_overflow, sum_areduced_b.sum()], @@ -213,11 +213,8 @@ impl ExecutionGadget for AddModGadget { self.cmp_r_n.assign(region, offset, r, n)?; self.cmp_areduced_n.assign(region, offset, a_reduced, n)?; - self.n_is_zero.assign( - region, - offset, - Word::random_linear_combine(n.to_le_bytes(), block.randomness), - )?; + self.n_is_zero + .assign_value(region, offset, region.word_rlc(n))?; Ok(()) } diff --git a/zkevm-circuits/src/evm_circuit/execution/address.rs b/zkevm-circuits/src/evm_circuit/execution/address.rs index 14e97f7ac0..63729e3e9d 100644 --- a/zkevm-circuits/src/evm_circuit/execution/address.rs +++ b/zkevm-circuits/src/evm_circuit/execution/address.rs @@ -30,7 +30,7 @@ impl ExecutionGadget for AddressGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::ADDRESS; fn configure(cb: &mut ConstraintBuilder) -> Self { - let address = cb.query_rlc(); + let address = cb.query_word_rlc(); // Lookup callee address in call context. cb.call_context_lookup( diff --git a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs index 1892f2e372..0de08ce061 100644 --- a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs +++ b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs @@ -10,14 +10,14 @@ use crate::{ Transition::{Delta, To}, }, math_gadget::{IsEqualGadget, IsZeroGadget, MulWordByU64Gadget, RangeCheckGadget}, - select, CachedRegion, Cell, RandomLinearCombination, Word, + select, CachedRegion, Cell, CellType, Word, }, witness::{Block, Call, ExecStep, Transaction}, }, table::{AccountFieldTag, CallContextFieldTag, TxFieldTag as TxContextFieldTag}, util::Expr, }; -use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar}; +use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar, U256}; use halo2_proofs::circuit::Value; use halo2_proofs::plonk::Error; use keccak256::EMPTY_HASH_LE; @@ -39,7 +39,7 @@ pub(crate) struct BeginTxGadget { reversion_info: ReversionInfo, sufficient_gas_left: RangeCheckGadget, transfer_with_gas_fee: TransferWithGasFeeGadget, - code_hash: Cell, + phase2_code_hash: Cell, is_empty_code_hash: IsEqualGadget, } @@ -150,20 +150,17 @@ impl ExecutionGadget for BeginTxGadget { // TODO: Handle precompiled // Read code_hash of callee - let code_hash = cb.query_cell(); + let phase2_code_hash = cb.query_cell_with_type(CellType::StoragePhase2); cb.account_read( tx_callee_address.expr(), AccountFieldTag::CodeHash, - code_hash.expr(), + phase2_code_hash.expr(), ); let is_empty_code_hash = IsEqualGadget::construct( cb, - code_hash.expr(), - Word::random_linear_combine_expr( - (*EMPTY_HASH_LE).map(|byte| byte.expr()), - cb.power_of_randomness(), - ), + phase2_code_hash.expr(), + cb.word_rlc((*EMPTY_HASH_LE).map(|byte| byte.expr())), ); cb.condition(is_empty_code_hash.expr(), |cb| { @@ -214,7 +211,7 @@ impl ExecutionGadget for BeginTxGadget { (CallContextFieldTag::LastCalleeReturnDataLength, 0.expr()), (CallContextFieldTag::IsRoot, 1.expr()), (CallContextFieldTag::IsCreate, tx_is_create.expr()), - (CallContextFieldTag::CodeHash, code_hash.expr()), + (CallContextFieldTag::CodeHash, phase2_code_hash.expr()), ] { cb.call_context_lookup(true.expr(), Some(call_id.expr()), field_tag, value); } @@ -248,7 +245,7 @@ impl ExecutionGadget for BeginTxGadget { call_id: To(call_id.expr()), is_root: To(true.expr()), is_create: To(tx_is_create.expr()), - code_hash: To(code_hash.expr()), + code_hash: To(phase2_code_hash.expr()), gas_left: To(gas_left), reversible_write_counter: To(2.expr()), log_id: To(0.expr()), @@ -272,7 +269,7 @@ impl ExecutionGadget for BeginTxGadget { reversion_info, sufficient_gas_left, transfer_with_gas_fee, - code_hash, + phase2_code_hash, is_empty_code_hash, } } @@ -346,19 +343,13 @@ impl ExecutionGadget for BeginTxGadget { tx.value, gas_fee, )?; - self.code_hash.assign( - region, - offset, - Value::known(RandomLinearCombination::random_linear_combine( - callee_code_hash.to_le_bytes(), - block.randomness, - )), - )?; - self.is_empty_code_hash.assign( + self.phase2_code_hash + .assign(region, offset, region.word_rlc(callee_code_hash))?; + self.is_empty_code_hash.assign_value( region, offset, - Word::random_linear_combine(callee_code_hash.to_le_bytes(), block.randomness), - Word::random_linear_combine(*EMPTY_HASH_LE, block.randomness), + region.word_rlc(callee_code_hash), + region.word_rlc(U256::from_little_endian(&*EMPTY_HASH_LE)), )?; Ok(()) } diff --git a/zkevm-circuits/src/evm_circuit/execution/bitwise.rs b/zkevm-circuits/src/evm_circuit/execution/bitwise.rs index 476c4aef63..f6ca8fed4d 100644 --- a/zkevm-circuits/src/evm_circuit/execution/bitwise.rs +++ b/zkevm-circuits/src/evm_circuit/execution/bitwise.rs @@ -33,9 +33,9 @@ impl ExecutionGadget for BitwiseGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let opcode = cb.query_cell(); - let a = cb.query_word(); - let b = cb.query_word(); - let c = cb.query_word(); + let a = cb.query_word_rlc(); + let b = cb.query_word_rlc(); + let c = cb.query_word_rlc(); cb.stack_pop(a.expr()); cb.stack_pop(b.expr()); diff --git a/zkevm-circuits/src/evm_circuit/execution/block_ctx.rs b/zkevm-circuits/src/evm_circuit/execution/block_ctx.rs index 86f62ef30b..a580fe4557 100644 --- a/zkevm-circuits/src/evm_circuit/execution/block_ctx.rs +++ b/zkevm-circuits/src/evm_circuit/execution/block_ctx.rs @@ -26,7 +26,7 @@ pub(crate) struct BlockCtxGadget { impl BlockCtxGadget { fn construct(cb: &mut ConstraintBuilder) -> Self { - let value = cb.query_rlc(); + let value = cb.query_word_rlc(); // Push the const generic parameter N_BYTES value to the stack cb.stack_push(value.expr()); diff --git a/zkevm-circuits/src/evm_circuit/execution/blockhash.rs b/zkevm-circuits/src/evm_circuit/execution/blockhash.rs index 14e34d2ccc..df512e7442 100644 --- a/zkevm-circuits/src/evm_circuit/execution/blockhash.rs +++ b/zkevm-circuits/src/evm_circuit/execution/blockhash.rs @@ -36,7 +36,7 @@ impl ExecutionGadget for BlockHashGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::BLOCKHASH; fn configure(cb: &mut ConstraintBuilder) -> Self { - let block_number = cb.query_rlc(); + let block_number = cb.query_word_rlc(); cb.stack_pop(block_number.expr()); let current_block_number = cb.query_cell(); @@ -58,7 +58,7 @@ impl ExecutionGadget for BlockHashGadget { 257.expr() + from_bytes::expr(&block_number.cells), ); - let block_hash = cb.query_rlc(); + let block_hash = cb.query_word_rlc(); cb.condition(block_lt.expr() * diff_lt.expr(), |cb| { cb.block_lookup( BlockContextFieldTag::BlockHash.expr(), diff --git a/zkevm-circuits/src/evm_circuit/execution/byte.rs b/zkevm-circuits/src/evm_circuit/execution/byte.rs index 0336d3a6a0..085f39abe2 100644 --- a/zkevm-circuits/src/evm_circuit/execution/byte.rs +++ b/zkevm-circuits/src/evm_circuit/execution/byte.rs @@ -33,8 +33,8 @@ impl ExecutionGadget for ByteGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::BYTE; fn configure(cb: &mut ConstraintBuilder) -> Self { - let index = cb.query_word(); - let value = cb.query_word(); + let index = cb.query_word_rlc(); + let value = cb.query_word_rlc(); // If any of the non-LSB bytes of the index word are non-zero we never // need to copy any bytes. So just sum all the non-LSB byte diff --git a/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs b/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs index 7046b7ad02..08b42ec188 100644 --- a/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs @@ -46,8 +46,8 @@ impl ExecutionGadget for CallDataCopyGadget { let opcode = cb.query_cell(); let memory_offset = cb.query_cell(); - let data_offset = cb.query_rlc(); - let length = cb.query_rlc(); + let data_offset = cb.query_word_rlc(); + let length = cb.query_word_rlc(); // Pop memory_offset, data_offset, length from stack cb.stack_pop(memory_offset.expr()); @@ -172,9 +172,9 @@ impl ExecutionGadget for CallDataCopyGadget { let [memory_offset, data_offset, length] = [step.rw_indices[0], step.rw_indices[1], step.rw_indices[2]] .map(|idx| block.rws[idx].stack_value()); - let memory_address = - self.memory_address - .assign(region, offset, memory_offset, length, block.randomness)?; + let memory_address = self + .memory_address + .assign(region, offset, memory_offset, length)?; self.data_offset.assign( region, offset, diff --git a/zkevm-circuits/src/evm_circuit/execution/calldataload.rs b/zkevm-circuits/src/evm_circuit/execution/calldataload.rs index 600a190aa9..d35fe5fc57 100644 --- a/zkevm-circuits/src/evm_circuit/execution/calldataload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/calldataload.rs @@ -14,7 +14,7 @@ use crate::{ constraint_builder::{ConstraintBuilder, StepStateTransition, Transition::Delta}, from_bytes, memory_gadget::BufferReaderGadget, - not, CachedRegion, Cell, MemoryAddress, RandomLinearCombination, + not, CachedRegion, Cell, MemoryAddress, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -56,7 +56,7 @@ impl ExecutionGadget for CallDataLoadGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let opcode = cb.query_cell(); - let offset = cb.query_rlc(); + let offset = cb.query_word_rlc(); // Pop the offset value from stack. cb.stack_pop(offset.expr()); @@ -143,10 +143,7 @@ impl ExecutionGadget for CallDataLoadGadget { // Add a lookup constraint for the 32-bytes that should have been pushed // to the stack. let calldata_word: [Expression; N_BYTES_WORD] = calldata_word.try_into().unwrap(); - cb.stack_push(RandomLinearCombination::random_linear_combine_expr( - calldata_word, - cb.power_of_randomness(), - )); + cb.stack_push(cb.word_rlc(calldata_word)); let step_state_transition = StepStateTransition { rw_counter: Delta(cb.rw_counter_offset()), diff --git a/zkevm-circuits/src/evm_circuit/execution/calldatasize.rs b/zkevm-circuits/src/evm_circuit/execution/calldatasize.rs index 315a862ef5..135974da62 100644 --- a/zkevm-circuits/src/evm_circuit/execution/calldatasize.rs +++ b/zkevm-circuits/src/evm_circuit/execution/calldatasize.rs @@ -32,7 +32,7 @@ impl ExecutionGadget for CallDataSizeGadget { let opcode = cb.query_cell(); // Add lookup constraint in the call context for the calldatasize field. - let call_data_size = cb.query_rlc(); + let call_data_size = cb.query_word_rlc(); cb.call_context_lookup( false.expr(), None, diff --git a/zkevm-circuits/src/evm_circuit/execution/caller.rs b/zkevm-circuits/src/evm_circuit/execution/caller.rs index 1ce018d30a..8648d58c47 100644 --- a/zkevm-circuits/src/evm_circuit/execution/caller.rs +++ b/zkevm-circuits/src/evm_circuit/execution/caller.rs @@ -30,7 +30,7 @@ impl ExecutionGadget for CallerGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::CALLER; fn configure(cb: &mut ConstraintBuilder) -> Self { - let caller_address = cb.query_rlc(); + let caller_address = cb.query_word_rlc(); // Lookup rw_table -> call_context with caller address cb.call_context_lookup( diff --git a/zkevm-circuits/src/evm_circuit/execution/callop.rs b/zkevm-circuits/src/evm_circuit/execution/callop.rs index 75fac49efa..b93f16450c 100644 --- a/zkevm-circuits/src/evm_circuit/execution/callop.rs +++ b/zkevm-circuits/src/evm_circuit/execution/callop.rs @@ -10,7 +10,7 @@ use crate::evm_circuit::util::math_gadget::{ BatchedIsZeroGadget, ConstantDivisionGadget, IsEqualGadget, IsZeroGadget, MinMaxGadget, }; use crate::evm_circuit::util::memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}; -use crate::evm_circuit::util::{from_bytes, select, sum, CachedRegion, Cell, Word}; +use crate::evm_circuit::util::{from_bytes, select, sum, CachedRegion, Cell, CellType, Word}; use crate::evm_circuit::witness::{Block, Call, ExecStep, Transaction}; use crate::table::{AccountFieldTag, CallContextFieldTag}; use crate::util::Expr; @@ -51,7 +51,7 @@ pub(crate) struct CallOpGadget { memory_expansion: MemoryExpansionGadget, transfer: TransferGadget, callee_nonce: Cell, - callee_code_hash: Cell, + phase2_callee_code_hash: Cell, is_empty_nonce_and_balance: BatchedIsZeroGadget, is_empty_code_hash: IsEqualGadget, one_64th_gas: ConstantDivisionGadget, @@ -64,6 +64,7 @@ impl ExecutionGadget for CallOpGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::CALL_OP; fn configure(cb: &mut ConstraintBuilder) -> Self { + let opcode = cb.query_cell(); cb.opcode_lookup(opcode.expr(), 1.expr()); let is_call = IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::CALL.expr()); @@ -82,13 +83,13 @@ impl ExecutionGadget for CallOpGadget { 1.expr(), ); - let gas_word = cb.query_word(); - let code_address_word = cb.query_word(); - let value = cb.query_word(); + let gas_word = cb.query_word_rlc(); + let code_address_word = cb.query_word_rlc(); + let value = cb.query_word_rlc(); let cd_offset = cb.query_cell(); - let cd_length = cb.query_rlc(); + let cd_length = cb.query_word_rlc(); let rd_offset = cb.query_cell(); - let rd_length = cb.query_rlc(); + let rd_length = cb.query_word_rlc(); let is_success = cb.query_bool(); // Use rw_counter of the step which triggers next call as its call_id. @@ -210,11 +211,11 @@ impl ExecutionGadget for CallOpGadget { AccountFieldTag::Nonce, callee_nonce.expr(), ); - let callee_code_hash = cb.query_cell(); + let phase2_callee_code_hash = cb.query_cell_with_type(CellType::StoragePhase2); cb.account_read( code_address, AccountFieldTag::CodeHash, - callee_code_hash.expr(), + phase2_callee_code_hash.expr(), ); let is_empty_nonce_and_balance = BatchedIsZeroGadget::construct( cb, @@ -225,12 +226,10 @@ impl ExecutionGadget for CallOpGadget { ); let is_empty_code_hash = IsEqualGadget::construct( cb, - callee_code_hash.expr(), - Word::random_linear_combine_expr( - (*EMPTY_HASH_LE).map(|byte| byte.expr()), - cb.power_of_randomness(), - ), + phase2_callee_code_hash.expr(), + cb.word_rlc((*EMPTY_HASH_LE).map(|byte| byte.expr())), ); + let is_empty_account = is_empty_nonce_and_balance.expr() * is_empty_code_hash.expr(); // Sum up gas cost let gas_cost = select::expr( @@ -333,7 +332,10 @@ impl ExecutionGadget for CallOpGadget { (CallContextFieldTag::LastCalleeReturnDataLength, 0.expr()), (CallContextFieldTag::IsRoot, 0.expr()), (CallContextFieldTag::IsCreate, 0.expr()), - (CallContextFieldTag::CodeHash, callee_code_hash.expr()), + ( + CallContextFieldTag::CodeHash, + phase2_callee_code_hash.expr(), + ), ] { cb.call_context_lookup(true.expr(), Some(callee_call_id.expr()), field_tag, value); } @@ -351,13 +353,13 @@ impl ExecutionGadget for CallOpGadget { call_id: To(callee_call_id.expr()), is_root: To(false.expr()), is_create: To(false.expr()), - code_hash: To(callee_code_hash.expr()), + code_hash: To(phase2_callee_code_hash.expr()), gas_left: To(callee_gas_left), reversible_write_counter: To(2.expr()), ..StepStateTransition::new_context() }); }); - + Self { opcode, is_call, @@ -385,7 +387,7 @@ impl ExecutionGadget for CallOpGadget { memory_expansion, transfer, callee_nonce, - callee_code_hash, + phase2_callee_code_hash, is_empty_nonce_and_balance, is_empty_code_hash, one_64th_gas, @@ -542,12 +544,12 @@ impl ExecutionGadget for CallOpGadget { )?; self.value_is_zero .assign(region, offset, sum::value(&value.to_le_bytes()))?; - let cd_address = - self.cd_address - .assign(region, offset, cd_offset, cd_length, block.randomness)?; - let rd_address = - self.rd_address - .assign(region, offset, rd_offset, rd_length, block.randomness)?; + let cd_address = self + .cd_address + .assign(region, offset, cd_offset, cd_length)?; + let rd_address = self + .rd_address + .assign(region, offset, rd_offset, rd_length)?; let (_, memory_expansion_gas_cost) = self.memory_expansion.assign( region, offset, @@ -570,31 +572,25 @@ impl ExecutionGadget for CallOpGadget { .expect("unexpected U256 -> Scalar conversion failure"), ), )?; - self.callee_code_hash.assign( - region, - offset, - Value::known(Word::random_linear_combine( - callee_code_hash.to_le_bytes(), - block.randomness, - )), - )?; - let is_empty_nonce_and_balance = self.is_empty_nonce_and_balance.assign( + self.phase2_callee_code_hash + .assign(region, offset, region.word_rlc(callee_code_hash))?; + let is_empty_nonce_and_balance = self.is_empty_nonce_and_balance.assign_value( region, offset, [ - F::from(callee_nonce.low_u64()), - Word::random_linear_combine(callee_balance_pair.1.to_le_bytes(), block.randomness), + Value::known(F::from(callee_nonce.low_u64())), + region.word_rlc(callee_balance_pair.1), ], )?; - let is_empty_code_hash = self.is_empty_code_hash.assign( + let is_empty_code_hash = self.is_empty_code_hash.assign_value( region, offset, - Word::random_linear_combine(callee_code_hash.to_le_bytes(), block.randomness), - Word::random_linear_combine(*EMPTY_HASH_LE, block.randomness), + region.word_rlc(callee_code_hash), + region.word_rlc(U256::from_little_endian(&*EMPTY_HASH_LE)), )?; let is_empty_account = is_empty_nonce_and_balance * is_empty_code_hash; let has_value = !value.is_zero(); - let gas_cost = if is_warm_prev { + let gas_cost = is_empty_account.map(|is_empty_account| if is_warm_prev { GasCost::WARM_ACCESS.as_u64() } else { GasCost::COLD_ACCOUNT_ACCESS.as_u64() @@ -607,15 +603,18 @@ impl ExecutionGadget for CallOpGadget { } } else { 0 - } + memory_expansion_gas_cost; - let gas_available = step.gas_left - gas_cost; - self.one_64th_gas - .assign(region, offset, gas_available as u128)?; - self.capped_callee_gas_left.assign( + } + memory_expansion_gas_cost); + let gas_available = Value::known(step.gas_left) - gas_cost; + self.one_64th_gas.assign_value( + region, + offset, + gas_available.map(|gas_available| F::from(gas_available)), + )?; + self.capped_callee_gas_left.assign_value( region, offset, - F::from(gas.low_u64()), - F::from(gas_available - gas_available / 64), + Value::known(F::from(gas.low_u64())), + gas_available.map(|gas_available| F::from(gas_available - gas_available / 64)), )?; Ok(()) } @@ -855,6 +854,13 @@ mod test { } } + #[test] + fn callop_base() { + test_ok(caller(&OpcodeId::CALL, Stack::default(), true), callee(bytecode!{})); + // use crate::evm_circuit::util::print_op_count; + // print_op_count(); + } + fn test_ok(caller: Account, callee: Account) { let block: GethData = TestContext::<3, 1>::new( None, diff --git a/zkevm-circuits/src/evm_circuit/execution/callvalue.rs b/zkevm-circuits/src/evm_circuit/execution/callvalue.rs index 9e4d1a6c0a..25343998fa 100644 --- a/zkevm-circuits/src/evm_circuit/execution/callvalue.rs +++ b/zkevm-circuits/src/evm_circuit/execution/callvalue.rs @@ -5,7 +5,7 @@ use crate::{ util::{ common_gadget::SameContextGadget, constraint_builder::{ConstraintBuilder, StepStateTransition, Transition::Delta}, - CachedRegion, Cell, Word, + CachedRegion, Cell, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -13,8 +13,8 @@ use crate::{ util::Expr, }; use bus_mapping::evm::OpcodeId; -use eth_types::{Field, ToLittleEndian}; -use halo2_proofs::{circuit::Value, plonk::Error}; +use eth_types::Field; +use halo2_proofs::plonk::Error; #[derive(Clone, Debug)] pub(crate) struct CallValueGadget { @@ -73,14 +73,8 @@ impl ExecutionGadget for CallValueGadget { let call_value = block.rws[step.rw_indices[1]].stack_value(); - self.call_value.assign( - region, - offset, - Value::known(Word::random_linear_combine( - call_value.to_le_bytes(), - block.randomness, - )), - )?; + self.call_value + .assign(region, offset, region.word_rlc(call_value))?; Ok(()) } diff --git a/zkevm-circuits/src/evm_circuit/execution/chainid.rs b/zkevm-circuits/src/evm_circuit/execution/chainid.rs index 50523a92ee..6b48f31b3b 100644 --- a/zkevm-circuits/src/evm_circuit/execution/chainid.rs +++ b/zkevm-circuits/src/evm_circuit/execution/chainid.rs @@ -5,7 +5,7 @@ use crate::{ util::{ common_gadget::SameContextGadget, constraint_builder::{ConstraintBuilder, StepStateTransition, Transition::Delta}, - CachedRegion, Cell, Word, + CachedRegion, Cell, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -13,8 +13,8 @@ use crate::{ util::Expr, }; use bus_mapping::evm::OpcodeId; -use eth_types::{Field, ToLittleEndian}; -use halo2_proofs::{circuit::Value, plonk::Error}; +use eth_types::Field; +use halo2_proofs::plonk::Error; #[derive(Clone, Debug)] pub(crate) struct ChainIdGadget { @@ -65,14 +65,8 @@ impl ExecutionGadget for ChainIdGadget { self.same_context.assign_exec_step(region, offset, step)?; let chain_id = block.rws[step.rw_indices[0]].stack_value(); - self.chain_id.assign( - region, - offset, - Value::known(Word::random_linear_combine( - chain_id.to_le_bytes(), - block.randomness, - )), - )?; + self.chain_id + .assign(region, offset, region.word_rlc(chain_id))?; Ok(()) } } diff --git a/zkevm-circuits/src/evm_circuit/execution/codecopy.rs b/zkevm-circuits/src/evm_circuit/execution/codecopy.rs index b877706a15..00059aff4a 100644 --- a/zkevm-circuits/src/evm_circuit/execution/codecopy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/codecopy.rs @@ -51,8 +51,8 @@ impl ExecutionGadget for CodeCopyGadget { // Query elements to be popped from the stack. let dst_memory_offset = cb.query_cell(); - let code_offset = cb.query_rlc(); - let size = cb.query_rlc(); + let code_offset = cb.query_word_rlc(); + let size = cb.query_word_rlc(); // Pop items from stack. cb.stack_pop(dst_memory_offset.expr()); @@ -166,9 +166,9 @@ impl ExecutionGadget for CodeCopyGadget { )?; // assign the destination memory offset. - let memory_address = - self.dst_memory_addr - .assign(region, offset, dest_offset, size, block.randomness)?; + let memory_address = self + .dst_memory_addr + .assign(region, offset, dest_offset, size)?; // assign to gadgets handling memory expansion cost and copying cost. let (_, memory_expansion_cost) = self.memory_expansion.assign( diff --git a/zkevm-circuits/src/evm_circuit/execution/codesize.rs b/zkevm-circuits/src/evm_circuit/execution/codesize.rs index 31fe295452..9e264187fb 100644 --- a/zkevm-circuits/src/evm_circuit/execution/codesize.rs +++ b/zkevm-circuits/src/evm_circuit/execution/codesize.rs @@ -9,7 +9,7 @@ use crate::{ util::{ common_gadget::SameContextGadget, constraint_builder::{ConstraintBuilder, StepStateTransition, Transition}, - from_bytes, CachedRegion, Cell, RandomLinearCombination, + from_bytes, CachedRegion, Cell, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -44,10 +44,7 @@ impl ExecutionGadget for CodesizeGadget { codesize.expr(), ); - cb.stack_push(RandomLinearCombination::random_linear_combine_expr( - codesize_bytes.clone().map(|c| c.expr()), - cb.power_of_randomness(), - )); + cb.stack_push(cb.word_rlc(codesize_bytes.clone().map(|c| c.expr()))); let step_state_transition = StepStateTransition { gas_left: Transition::Delta(-OpcodeId::CODESIZE.constant_gas_cost().expr()), diff --git a/zkevm-circuits/src/evm_circuit/execution/comparator.rs b/zkevm-circuits/src/evm_circuit/execution/comparator.rs index 7358c43a25..148be4cb49 100644 --- a/zkevm-circuits/src/evm_circuit/execution/comparator.rs +++ b/zkevm-circuits/src/evm_circuit/execution/comparator.rs @@ -36,8 +36,8 @@ impl ExecutionGadget for ComparatorGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let opcode = cb.query_cell(); - let a = cb.query_word(); - let b = cb.query_word(); + let a = cb.query_word_rlc(); + let b = cb.query_word_rlc(); // Check if opcode is EQ let is_eq = IsEqualGadget::construct(cb, opcode.expr(), OpcodeId::EQ.expr()); diff --git a/zkevm-circuits/src/evm_circuit/execution/dummy.rs b/zkevm-circuits/src/evm_circuit/execution/dummy.rs index decf6917b8..55a5f13b65 100644 --- a/zkevm-circuits/src/evm_circuit/execution/dummy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/dummy.rs @@ -26,8 +26,8 @@ impl const EXECUTION_STATE: ExecutionState = S; fn configure(cb: &mut ConstraintBuilder) -> Self { - let pops: [Word; N_POP] = [(); N_POP].map(|_| cb.query_word()); - let pushes: [Word; N_PUSH] = [(); N_PUSH].map(|_| cb.query_word()); + let pops: [Word; N_POP] = [(); N_POP].map(|_| cb.query_word_rlc()); + let pushes: [Word; N_PUSH] = [(); N_PUSH].map(|_| cb.query_word_rlc()); for pop in pops.iter() { cb.stack_pop(pop.expr()); } diff --git a/zkevm-circuits/src/evm_circuit/execution/dup.rs b/zkevm-circuits/src/evm_circuit/execution/dup.rs index 6dfe2911cb..6ac47e2cb0 100644 --- a/zkevm-circuits/src/evm_circuit/execution/dup.rs +++ b/zkevm-circuits/src/evm_circuit/execution/dup.rs @@ -5,14 +5,14 @@ use crate::{ util::{ common_gadget::SameContextGadget, constraint_builder::{ConstraintBuilder, StepStateTransition, Transition::Delta}, - CachedRegion, Cell, Word, + CachedRegion, Cell, CellType, }, witness::{Block, Call, ExecStep, Transaction}, }, util::Expr, }; -use eth_types::{evm_types::OpcodeId, Field, ToLittleEndian}; -use halo2_proofs::{circuit::Value, plonk::Error}; +use eth_types::{evm_types::OpcodeId, Field}; +use halo2_proofs::plonk::Error; #[derive(Clone, Debug)] pub(crate) struct DupGadget { @@ -28,7 +28,7 @@ impl ExecutionGadget for DupGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let opcode = cb.query_cell(); - let value = cb.query_cell(); + let value = cb.query_cell_with_type(CellType::StoragePhase2); // The stack index we have to peek, deduced from the 'x' value of 'dupx' // The offset starts at 0 for DUP1 @@ -66,14 +66,7 @@ impl ExecutionGadget for DupGadget { self.same_context.assign_exec_step(region, offset, step)?; let value = block.rws[step.rw_indices[0]].stack_value(); - self.value.assign( - region, - offset, - Value::known(Word::random_linear_combine( - value.to_le_bytes(), - block.randomness, - )), - )?; + self.value.assign(region, offset, region.word_rlc(value))?; Ok(()) } diff --git a/zkevm-circuits/src/evm_circuit/execution/end_tx.rs b/zkevm-circuits/src/evm_circuit/execution/end_tx.rs index 12dcff9d7c..cb4fff6f30 100644 --- a/zkevm-circuits/src/evm_circuit/execution/end_tx.rs +++ b/zkevm-circuits/src/evm_circuit/execution/end_tx.rs @@ -85,14 +85,14 @@ impl ExecutionGadget for EndTxGadget { // Add gas_used * effective_tip to coinbase's balance let coinbase = cb.query_cell(); - let base_fee = cb.query_word(); + let base_fee = cb.query_word_rlc(); for (tag, value) in [ (BlockContextFieldTag::Coinbase, coinbase.expr()), (BlockContextFieldTag::BaseFee, base_fee.expr()), ] { cb.block_lookup(tag.expr(), None, value); } - let effective_tip = cb.query_word(); + let effective_tip = cb.query_word_rlc(); let sub_gas_price_by_base_fee = AddWordsGadget::construct(cb, [effective_tip.clone(), base_fee], tx_gas_price); let mul_effective_tip_by_gas_used = diff --git a/zkevm-circuits/src/evm_circuit/execution/error_invalid_jump.rs b/zkevm-circuits/src/evm_circuit/execution/error_invalid_jump.rs index 3695fb6822..a8082af6ef 100644 --- a/zkevm-circuits/src/evm_circuit/execution/error_invalid_jump.rs +++ b/zkevm-circuits/src/evm_circuit/execution/error_invalid_jump.rs @@ -11,7 +11,7 @@ use crate::{ }, from_bytes, math_gadget::{IsEqualGadget, IsZeroGadget, LtGadget}, - CachedRegion, Cell, RandomLinearCombination, Word as RLCWord, + CachedRegion, Cell, CellType, RandomLinearCombination, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -32,7 +32,7 @@ pub(crate) struct ErrorInvalidJumpGadget { within_range: LtGadget, is_jump_dest: IsEqualGadget, is_jumpi: IsEqualGadget, - condition: Cell, + phase2_condition: Cell, is_condition_zero: IsZeroGadget, restore_context: RestoreContextGadget, } @@ -43,11 +43,11 @@ impl ExecutionGadget for ErrorInvalidJumpGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::ErrorInvalidJump; fn configure(cb: &mut ConstraintBuilder) -> Self { - let destination = cb.query_rlc(); + let destination = cb.query_word_rlc(); let opcode = cb.query_cell(); let value = cb.query_cell(); let is_code = cb.query_cell(); - let condition = cb.query_cell(); + let phase2_condition = cb.query_cell_with_type(CellType::StoragePhase2); cb.require_in_set( "ErrorInvalidJump only happend in JUMP or JUMPI", @@ -62,13 +62,13 @@ impl ExecutionGadget for ErrorInvalidJumpGadget { // first default this condition, if use will re-construct with real condition // value - let is_condition_zero = IsZeroGadget::construct(cb, condition.expr()); + let is_condition_zero = IsZeroGadget::construct(cb, phase2_condition.expr()); // Pop the value from the stack cb.stack_pop(destination.expr()); cb.condition(is_jumpi.expr(), |cb| { - cb.stack_pop(condition.expr()); + cb.stack_pop(phase2_condition.expr()); // if condition is zero, jump will not happen, so constrain condition not zero cb.require_zero("condition is not zero", is_condition_zero.expr()); }); @@ -139,7 +139,7 @@ impl ExecutionGadget for ErrorInvalidJumpGadget { within_range, is_jump_dest, is_jumpi, - condition, + phase2_condition, is_condition_zero, restore_context, } @@ -165,9 +165,7 @@ impl ExecutionGadget for ErrorInvalidJumpGadget { } else { Word::zero() }; - let condition_rlc = - RLCWord::random_linear_combine(condition.to_le_bytes(), block.randomness); - + let condition_rlc = region.word_rlc(condition); self.destination.assign( region, offset, @@ -218,10 +216,10 @@ impl ExecutionGadget for ErrorInvalidJumpGadget { F::from(OpcodeId::JUMPI.as_u64()), )?; - self.condition - .assign(region, offset, Value::known(condition_rlc))?; - self.is_condition_zero + self.phase2_condition .assign(region, offset, condition_rlc)?; + self.is_condition_zero + .assign_value(region, offset, condition_rlc)?; self.restore_context .assign(region, offset, block, call, step, 2)?; diff --git a/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs b/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs index 3c73d629ab..2ed451b4b7 100644 --- a/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs +++ b/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs @@ -11,14 +11,14 @@ use crate::evm_circuit::{ from_bytes, math_gadget::{BatchedIsZeroGadget, IsEqualGadget, IsZeroGadget, LtGadget}, memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}, - select, sum, CachedRegion, Cell, Word, + select, sum, CachedRegion, Cell, CellType, Word, }, witness::{Block, Call, ExecStep, Transaction}, }; use crate::table::{AccountFieldTag, CallContextFieldTag}; use crate::util::Expr; use bus_mapping::evm::OpcodeId; -use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar}; +use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar, U256}; use halo2_proofs::{circuit::Value, plonk::Error}; use keccak256::EMPTY_HASH_LE; @@ -37,7 +37,7 @@ pub(crate) struct ErrorOOGCallGadget { memory_expansion: MemoryExpansionGadget, balance: Word, callee_nonce: Cell, - callee_code_hash: Cell, + phase2_callee_code_hash: Cell, is_empty_nonce_and_balance: BatchedIsZeroGadget, is_empty_code_hash: IsEqualGadget, insufficient_gas: LtGadget, @@ -60,14 +60,14 @@ impl ExecutionGadget for ErrorOOGCallGadget { OpcodeId::CALL.expr(), ); - let gas_word = cb.query_word(); - let callee_address_word = cb.query_word(); - let value = cb.query_word(); + let gas_word = cb.query_word_rlc(); + let callee_address_word = cb.query_word_rlc(); + let value = cb.query_word_rlc(); let cd_offset = cb.query_cell(); - let cd_length = cb.query_rlc(); + let cd_length = cb.query_word_rlc(); let rd_offset = cb.query_cell(); - let rd_length = cb.query_rlc(); - let balance = cb.query_word(); + let rd_length = cb.query_word_rlc(); + let balance = cb.query_word_rlc(); let tx_id = cb.call_context(None, CallContextFieldTag::TxId); @@ -104,21 +104,21 @@ impl ExecutionGadget for ErrorOOGCallGadget { ); // Verify gas cost - let [callee_nonce, callee_code_hash] = [AccountFieldTag::Nonce, AccountFieldTag::CodeHash] - .map(|field_tag| { - let value = cb.query_cell(); - cb.account_read(callee_address.clone(), field_tag, value.expr()); - value - }); + let [callee_nonce, phase2_callee_code_hash] = [ + (AccountFieldTag::Nonce, CellType::StoragePhase1), + (AccountFieldTag::CodeHash, CellType::StoragePhase2), + ] + .map(|(field_tag, cell_type)| { + let value = cb.query_cell_with_type(cell_type); + cb.account_read(callee_address.clone(), field_tag, value.expr()); + value + }); let is_empty_nonce_and_balance = BatchedIsZeroGadget::construct(cb, [callee_nonce.expr(), balance.expr()]); let is_empty_code_hash = IsEqualGadget::construct( cb, - callee_code_hash.expr(), - Word::random_linear_combine_expr( - (*EMPTY_HASH_LE).map(|byte| byte.expr()), - cb.power_of_randomness(), - ), + phase2_callee_code_hash.expr(), + cb.word_rlc((*EMPTY_HASH_LE).map(|byte| byte.expr())), ); let is_empty_account = is_empty_nonce_and_balance.expr() * is_empty_code_hash.expr(); // Sum up gas cost @@ -189,7 +189,7 @@ impl ExecutionGadget for ErrorOOGCallGadget { memory_expansion, balance, callee_nonce, - callee_code_hash, + phase2_callee_code_hash, is_empty_nonce_and_balance, is_empty_code_hash, insufficient_gas, @@ -250,12 +250,12 @@ impl ExecutionGadget for ErrorOOGCallGadget { self.value_is_zero .assign(region, offset, sum::value(&value.to_le_bytes()))?; - let cd_address = - self.cd_address - .assign(region, offset, cd_offset, cd_length, block.randomness)?; - let rd_address = - self.rd_address - .assign(region, offset, rd_offset, rd_length, block.randomness)?; + let cd_address = self + .cd_address + .assign(region, offset, cd_offset, cd_length)?; + let rd_address = self + .rd_address + .assign(region, offset, rd_offset, rd_length)?; let (_, memory_expansion_gas_cost) = self.memory_expansion.assign( region, offset, @@ -276,47 +276,41 @@ impl ExecutionGadget for ErrorOOGCallGadget { .expect("unexpected U256 -> Scalar conversion failure"), ), )?; - self.callee_code_hash.assign( - region, - offset, - Value::known(Word::random_linear_combine( - callee_code_hash.to_le_bytes(), - block.randomness, - )), - )?; - let is_empty_nonce_and_balance = self.is_empty_nonce_and_balance.assign( + self.phase2_callee_code_hash + .assign(region, offset, region.word_rlc(callee_code_hash))?; + let is_empty_nonce_and_balance = self.is_empty_nonce_and_balance.assign_value( region, offset, [ - F::from(callee_nonce.low_u64()), - Word::random_linear_combine(callee_balance_pair.1.to_le_bytes(), block.randomness), + Value::known(F::from(callee_nonce.low_u64())), + region.word_rlc(callee_balance_pair.1), ], )?; - let is_empty_code_hash = self.is_empty_code_hash.assign( + let is_empty_code_hash = self.is_empty_code_hash.assign_value( region, offset, - Word::random_linear_combine(callee_code_hash.to_le_bytes(), block.randomness), - Word::random_linear_combine(*EMPTY_HASH_LE, block.randomness), + region.word_rlc(callee_code_hash), + region.word_rlc(U256::from_little_endian(&*EMPTY_HASH_LE)), )?; let is_empty_account = is_empty_nonce_and_balance * is_empty_code_hash; let has_value = !value.is_zero(); let gas_cost = if is_warm_prev { - GasCost::WARM_ACCESS.as_u64() + Value::known(F::from(GasCost::WARM_ACCESS.as_u64())) } else { - GasCost::COLD_ACCOUNT_ACCESS.as_u64() + Value::known(F::from(GasCost::COLD_ACCOUNT_ACCESS.as_u64())) } + if has_value { - GasCost::CALL_WITH_VALUE.as_u64() - + if is_empty_account == F::one() { - GasCost::NEW_ACCOUNT.as_u64() - } else { - 0 - } + Value::known(F::from(GasCost::CALL_WITH_VALUE.as_u64())) + + is_empty_account * Value::known(F::from(GasCost::NEW_ACCOUNT.as_u64())) } else { - 0 - } + memory_expansion_gas_cost; + Value::known(F::from(0)) + } + Value::known(F::from(memory_expansion_gas_cost)); - self.insufficient_gas - .assign(region, offset, F::from(step.gas_left), F::from(gas_cost))?; + self.insufficient_gas.assign_value( + region, + offset, + Value::known(F::from(step.gas_left)), + gas_cost, + )?; self.restore_context .assign(region, offset, block, call, step, 15)?; diff --git a/zkevm-circuits/src/evm_circuit/execution/error_oog_static_memory.rs b/zkevm-circuits/src/evm_circuit/execution/error_oog_static_memory.rs index ac8f93456d..596885b855 100644 --- a/zkevm-circuits/src/evm_circuit/execution/error_oog_static_memory.rs +++ b/zkevm-circuits/src/evm_circuit/execution/error_oog_static_memory.rs @@ -45,7 +45,7 @@ impl ExecutionGadget for ErrorOOGStaticMemoryGadget { let opcode = cb.query_cell(); // Query address by a full word - let address = cb.query_word(); + let address = cb.query_word_rlc(); // Check if this is an MSTORE8 let is_mstore8 = IsEqualGadget::construct(cb, opcode.expr(), OpcodeId::MSTORE8.expr()); diff --git a/zkevm-circuits/src/evm_circuit/execution/exp.rs b/zkevm-circuits/src/evm_circuit/execution/exp.rs index 7da87a7e97..91089295a0 100644 --- a/zkevm-circuits/src/evm_circuit/execution/exp.rs +++ b/zkevm-circuits/src/evm_circuit/execution/exp.rs @@ -53,9 +53,9 @@ impl ExecutionGadget for ExponentiationGadget { // Query RLC-encoded values for base, exponent and exponentiation, where: // base^exponent == exponentiation (mod 2^256). - let base_rlc = cb.query_rlc(); - let exponent_rlc = cb.query_rlc(); - let exponentiation_rlc = cb.query_rlc(); + let base_rlc = cb.query_word_rlc(); + let exponent_rlc = cb.query_word_rlc(); + let exponentiation_rlc = cb.query_word_rlc(); // Pop RLC-encoded base and exponent from the stack. cb.stack_pop(base_rlc.expr()); @@ -90,12 +90,12 @@ impl ExecutionGadget for ExponentiationGadget { let exponent_is_one_expr = and::expr([exponent_lo_is_one.expr(), exponent_hi_is_zero.expr()]); - let zero_rlc = cb.query_word(); + let zero_rlc = cb.query_word_rlc(); cb.require_zero( "base * base + c == base^2 (c == 0)", sum::expr(&zero_rlc.cells), ); - let base_sq = cb.query_word(); + let base_sq = cb.query_word_rlc(); // If exponent == 0, base^exponent == 1, which implies: // 1. Low bytes of exponentiation == 1 diff --git a/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs b/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs index d3bbbb3bd6..6a11300973 100644 --- a/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs +++ b/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs @@ -10,14 +10,14 @@ use crate::{ }, from_bytes, math_gadget::BatchedIsZeroGadget, - CachedRegion, Cell, RandomLinearCombination, Word, + CachedRegion, Cell, RandomLinearCombination, }, witness::{Block, Call, ExecStep, Transaction}, }, table::{AccountFieldTag, CallContextFieldTag}, util::Expr, }; -use eth_types::{evm_types::GasCost, Field, ToAddress}; +use eth_types::{evm_types::GasCost, Field, ToAddress, U256}; use halo2_proofs::{circuit::Value, plonk::Error}; use keccak256::EMPTY_HASH_LE; @@ -40,7 +40,7 @@ impl ExecutionGadget for ExtcodehashGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::EXTCODEHASH; fn configure(cb: &mut ConstraintBuilder) -> Self { - let external_address = cb.query_rlc(); + let external_address = cb.query_word_rlc(); cb.stack_pop(external_address.expr()); let tx_id = cb.call_context(None, CallContextFieldTag::TxId); @@ -74,10 +74,7 @@ impl ExecutionGadget for ExtcodehashGadget { code_hash.expr(), ); - let empty_code_hash_rlc = Word::random_linear_combine_expr( - (*EMPTY_HASH_LE).map(|byte| byte.expr()), - cb.power_of_randomness(), - ); + let empty_code_hash_rlc = cb.word_rlc((*EMPTY_HASH_LE).map(|byte| byte.expr())); // Note that balance is RLC encoded, but RLC(x) = 0 iff x = 0, so we don't need // go to the work of writing out the RLC expression let is_empty = BatchedIsZeroGadget::construct( @@ -156,17 +153,16 @@ impl ExecutionGadget for ExtcodehashGadget { let [nonce, balance, code_hash] = [5, 6, 7].map(|i| { block.rws[step.rw_indices[i]] - .table_assignment_aux(block.randomness) + .table_assignment(region.challenges().evm_word()) .value }); - self.nonce.assign(region, offset, Value::known(nonce))?; - self.balance.assign(region, offset, Value::known(balance))?; - self.code_hash - .assign(region, offset, Value::known(code_hash))?; + self.nonce.assign(region, offset, nonce)?; + self.balance.assign(region, offset, balance)?; + self.code_hash.assign(region, offset, code_hash)?; - let empty_code_hash_rlc = Word::random_linear_combine(*EMPTY_HASH_LE, block.randomness); - self.is_empty.assign( + let empty_code_hash_rlc = region.word_rlc(U256::from_little_endian(&*EMPTY_HASH_LE)); + self.is_empty.assign_value( region, offset, [nonce, balance, code_hash - empty_code_hash_rlc], diff --git a/zkevm-circuits/src/evm_circuit/execution/gas.rs b/zkevm-circuits/src/evm_circuit/execution/gas.rs index 0567e50a03..14b5101165 100644 --- a/zkevm-circuits/src/evm_circuit/execution/gas.rs +++ b/zkevm-circuits/src/evm_circuit/execution/gas.rs @@ -28,7 +28,7 @@ impl ExecutionGadget for GasGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { // The gas passed to a transaction is a 64-bit number. - let gas_left = cb.query_rlc(); + let gas_left = cb.query_word_rlc(); // The `gas_left` in the current state has to be deducted by the gas // used by the `GAS` opcode itself. diff --git a/zkevm-circuits/src/evm_circuit/execution/gasprice.rs b/zkevm-circuits/src/evm_circuit/execution/gasprice.rs index db44d07781..95f5e44dd8 100644 --- a/zkevm-circuits/src/evm_circuit/execution/gasprice.rs +++ b/zkevm-circuits/src/evm_circuit/execution/gasprice.rs @@ -5,7 +5,7 @@ use crate::{ util::{ common_gadget::SameContextGadget, constraint_builder::{ConstraintBuilder, StepStateTransition, Transition::Delta}, - CachedRegion, Cell, Word, + CachedRegion, Cell, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -13,7 +13,7 @@ use crate::{ util::Expr, }; use bus_mapping::evm::OpcodeId; -use eth_types::{Field, ToLittleEndian}; +use eth_types::Field; use halo2_proofs::{circuit::Value, plonk::Error}; #[derive(Clone, Debug)] @@ -77,14 +77,8 @@ impl ExecutionGadget for GasPriceGadget { self.tx_id .assign(region, offset, Value::known(F::from(tx.id as u64)))?; - self.gas_price.assign( - region, - offset, - Value::known(Word::random_linear_combine( - gas_price.to_le_bytes(), - block.randomness, - )), - )?; + self.gas_price + .assign(region, offset, region.word_rlc(gas_price))?; self.same_context.assign_exec_step(region, offset, step)?; diff --git a/zkevm-circuits/src/evm_circuit/execution/is_zero.rs b/zkevm-circuits/src/evm_circuit/execution/is_zero.rs index bbc1efc2fc..b07f02cb07 100644 --- a/zkevm-circuits/src/evm_circuit/execution/is_zero.rs +++ b/zkevm-circuits/src/evm_circuit/execution/is_zero.rs @@ -5,15 +5,15 @@ use crate::{ util::{ common_gadget::SameContextGadget, constraint_builder::{ConstraintBuilder, StepStateTransition, Transition::Delta}, - math_gadget, CachedRegion, Cell, Word, + math_gadget, CachedRegion, Cell, }, witness::{Block, Call, ExecStep, Transaction}, }, util::Expr, }; use bus_mapping::evm::OpcodeId; -use eth_types::{Field, ToLittleEndian}; -use halo2_proofs::{circuit::Value, plonk::Error}; +use eth_types::Field; +use halo2_proofs::plonk::Error; #[derive(Clone, Debug)] pub(crate) struct IsZeroGadget { @@ -65,9 +65,9 @@ impl ExecutionGadget for IsZeroGadget { self.same_context.assign_exec_step(region, offset, step)?; let value = block.rws[step.rw_indices[0]].stack_value(); - let value = Word::random_linear_combine(value.to_le_bytes(), block.randomness); - self.value.assign(region, offset, Value::known(value))?; - self.is_zero.assign(region, offset, value)?; + let value = region.word_rlc(value); + self.value.assign(region, offset, value)?; + self.is_zero.assign_value(region, offset, value)?; Ok(()) } diff --git a/zkevm-circuits/src/evm_circuit/execution/jump.rs b/zkevm-circuits/src/evm_circuit/execution/jump.rs index 7e95adb79b..9d60f47fc4 100644 --- a/zkevm-circuits/src/evm_circuit/execution/jump.rs +++ b/zkevm-circuits/src/evm_circuit/execution/jump.rs @@ -30,7 +30,7 @@ impl ExecutionGadget for JumpGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::JUMP; fn configure(cb: &mut ConstraintBuilder) -> Self { - let destination = cb.query_rlc(); + let destination = cb.query_word_rlc(); // Pop the value from the stack cb.stack_pop(destination.expr()); diff --git a/zkevm-circuits/src/evm_circuit/execution/jumpi.rs b/zkevm-circuits/src/evm_circuit/execution/jumpi.rs index 56145e66f5..7e4a8cbb36 100644 --- a/zkevm-circuits/src/evm_circuit/execution/jumpi.rs +++ b/zkevm-circuits/src/evm_circuit/execution/jumpi.rs @@ -11,20 +11,20 @@ use crate::{ }, from_bytes, math_gadget::IsZeroGadget, - select, CachedRegion, Cell, RandomLinearCombination, Word, + select, CachedRegion, Cell, CellType, RandomLinearCombination, }, witness::{Block, Call, ExecStep, Transaction}, }, util::Expr, }; use eth_types::{evm_types::OpcodeId, Field, ToLittleEndian}; -use halo2_proofs::{circuit::Value, plonk::Error}; +use halo2_proofs::plonk::Error; #[derive(Clone, Debug)] pub(crate) struct JumpiGadget { same_context: SameContextGadget, destination: RandomLinearCombination, - condition: Cell, + phase2_condition: Cell, is_condition_zero: IsZeroGadget, } @@ -34,15 +34,15 @@ impl ExecutionGadget for JumpiGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::JUMPI; fn configure(cb: &mut ConstraintBuilder) -> Self { - let destination = cb.query_rlc(); - let condition = cb.query_cell(); + let destination = cb.query_word_rlc(); + let phase2_condition = cb.query_cell_with_type(CellType::StoragePhase2); // Pop the value from the stack cb.stack_pop(destination.expr()); - cb.stack_pop(condition.expr()); + cb.stack_pop(phase2_condition.expr()); // Determine if the jump condition is met - let is_condition_zero = IsZeroGadget::construct(cb, condition.expr()); + let is_condition_zero = IsZeroGadget::construct(cb, phase2_condition.expr()); let should_jump = 1.expr() - is_condition_zero.expr(); // Lookup opcode at destination when should_jump @@ -76,7 +76,7 @@ impl ExecutionGadget for JumpiGadget { Self { same_context, destination, - condition, + phase2_condition, is_condition_zero, } } @@ -94,7 +94,7 @@ impl ExecutionGadget for JumpiGadget { let [destination, condition] = [step.rw_indices[0], step.rw_indices[1]].map(|idx| block.rws[idx].stack_value()); - let condition = Word::random_linear_combine(condition.to_le_bytes(), block.randomness); + let condition = region.word_rlc(condition); self.destination.assign( region, @@ -105,9 +105,9 @@ impl ExecutionGadget for JumpiGadget { .unwrap(), ), )?; - self.condition - .assign(region, offset, Value::known(condition))?; - self.is_condition_zero.assign(region, offset, condition)?; + self.phase2_condition.assign(region, offset, condition)?; + self.is_condition_zero + .assign_value(region, offset, condition)?; Ok(()) } diff --git a/zkevm-circuits/src/evm_circuit/execution/logs.rs b/zkevm-circuits/src/evm_circuit/execution/logs.rs index 544c5e9096..2f18bc5427 100644 --- a/zkevm-circuits/src/evm_circuit/execution/logs.rs +++ b/zkevm-circuits/src/evm_circuit/execution/logs.rs @@ -10,7 +10,7 @@ use crate::{ Transition::{Delta, To}, }, memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}, - not, sum, CachedRegion, Cell, Word, + not, sum, CachedRegion, Cell, CellType, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -19,8 +19,8 @@ use crate::{ }; use array_init::array_init; use bus_mapping::circuit_input_builder::CopyDataType; -use eth_types::Field; -use eth_types::{evm_types::GasCost, evm_types::OpcodeId, ToLittleEndian, ToScalar}; +use eth_types::{evm_types::GasCost, evm_types::OpcodeId, ToScalar}; +use eth_types::{Field, U256}; use halo2_proofs::{circuit::Value, plonk::Error}; #[derive(Clone, Debug)] @@ -28,7 +28,7 @@ pub(crate) struct LogGadget { same_context: SameContextGadget, // memory address memory_address: MemoryAddressGadget, - topics: [Cell; 4], + phase2_topics: [Cell; 4], topic_selectors: [Cell; 4], contract_address: Cell, @@ -46,7 +46,7 @@ impl ExecutionGadget for LogGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let mstart = cb.query_cell(); - let msize = cb.query_rlc(); + let msize = cb.query_word_rlc(); // Pop mstart_address, msize from stack cb.stack_pop(mstart.expr()); @@ -74,9 +74,9 @@ impl ExecutionGadget for LogGadget { }); // constrain topics in logs - let topics = array_init(|_| cb.query_cell()); + let phase2_topics = array_init(|_| cb.query_cell_with_type(CellType::StoragePhase2)); let topic_selectors: [Cell; 4] = array_init(|_| cb.query_cell()); - for (idx, topic) in topics.iter().enumerate() { + for (idx, topic) in phase2_topics.iter().enumerate() { cb.condition(topic_selectors[idx].expr(), |cb| { cb.stack_pop(topic.expr()); }); @@ -170,7 +170,7 @@ impl ExecutionGadget for LogGadget { Self { same_context, memory_address, - topics, + phase2_topics, topic_selectors, contract_address, is_static_call, @@ -195,9 +195,9 @@ impl ExecutionGadget for LogGadget { let [memory_start, msize] = [step.rw_indices[0], step.rw_indices[1]].map(|idx| block.rws[idx].stack_value()); - let memory_address = - self.memory_address - .assign(region, offset, memory_start, msize, block.randomness)?; + let memory_address = self + .memory_address + .assign(region, offset, memory_start, msize)?; // Memory expansion self.memory_expansion @@ -216,18 +216,15 @@ impl ExecutionGadget for LogGadget { }; for i in 0..4 { - let mut topic = Word::random_linear_combine([0; 32], block.randomness); + let mut topic = region.word_rlc(U256::zero()); if i < topic_count { - topic = Word::random_linear_combine( - block.rws[topic_stack_entry].stack_value().to_le_bytes(), - block.randomness, - ); + topic = region.word_rlc(block.rws[topic_stack_entry].stack_value()); self.topic_selectors[i].assign(region, offset, Value::known(F::one()))?; topic_stack_entry.1 += 1; } else { self.topic_selectors[i].assign(region, offset, Value::known(F::zero()))?; } - self.topics[i].assign(region, offset, Value::known(topic))?; + self.phase2_topics[i].assign(region, offset, topic)?; } self.contract_address.assign( diff --git a/zkevm-circuits/src/evm_circuit/execution/memory.rs b/zkevm-circuits/src/evm_circuit/execution/memory.rs index b1e8d65ec6..24b32f3aa6 100644 --- a/zkevm-circuits/src/evm_circuit/execution/memory.rs +++ b/zkevm-circuits/src/evm_circuit/execution/memory.rs @@ -40,8 +40,8 @@ impl ExecutionGadget for MemoryGadget { let opcode = cb.query_cell(); // In successful case the address must be in 5 bytes - let address = cb.query_rlc(); - let value = cb.query_word(); + let address = cb.query_word_rlc(); + let value = cb.query_word_rlc(); // Check if this is an MLOAD let is_mload = IsEqualGadget::construct(cb, opcode.expr(), OpcodeId::MLOAD.expr()); diff --git a/zkevm-circuits/src/evm_circuit/execution/msize.rs b/zkevm-circuits/src/evm_circuit/execution/msize.rs index ebbe8450d4..b587d9791b 100644 --- a/zkevm-circuits/src/evm_circuit/execution/msize.rs +++ b/zkevm-circuits/src/evm_circuit/execution/msize.rs @@ -28,7 +28,7 @@ impl ExecutionGadget for MsizeGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::MSIZE; fn configure(cb: &mut ConstraintBuilder) -> Self { - let value = cb.query_rlc(); + let value = cb.query_word_rlc(); // memory_size is limited to 64 bits so we only consider 8 bytes cb.require_equal( diff --git a/zkevm-circuits/src/evm_circuit/execution/mul_div_mod.rs b/zkevm-circuits/src/evm_circuit/execution/mul_div_mod.rs index 4b2384a624..404c6acd16 100644 --- a/zkevm-circuits/src/evm_circuit/execution/mul_div_mod.rs +++ b/zkevm-circuits/src/evm_circuit/execution/mul_div_mod.rs @@ -52,10 +52,10 @@ impl ExecutionGadget for MulDivModGadget { let is_mod = (opcode.expr() - OpcodeId::MUL.expr()) * (opcode.expr() - OpcodeId::DIV.expr()) * F::from(8).invert().unwrap(); - let a = cb.query_word(); - let b = cb.query_word(); - let c = cb.query_word(); - let d = cb.query_word(); + let a = cb.query_word_rlc(); + let b = cb.query_word_rlc(); + let c = cb.query_word_rlc(); + let d = cb.query_word_rlc(); let mul_add_words = MulAddWordsGadget::construct(cb, [&a, &b, &c, &d]); let divisor_is_zero = IsZeroGadget::construct(cb, sum::expr(&b.cells)); diff --git a/zkevm-circuits/src/evm_circuit/execution/mulmod.rs b/zkevm-circuits/src/evm_circuit/execution/mulmod.rs index c92ff0f606..569775c15f 100644 --- a/zkevm-circuits/src/evm_circuit/execution/mulmod.rs +++ b/zkevm-circuits/src/evm_circuit/execution/mulmod.rs @@ -44,16 +44,16 @@ impl ExecutionGadget for MulModGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let opcode = cb.query_cell(); - let a = cb.query_word(); - let b = cb.query_word(); - let n = cb.query_word(); - let r = cb.query_word(); + let a = cb.query_word_rlc(); + let b = cb.query_word_rlc(); + let n = cb.query_word_rlc(); + let r = cb.query_word_rlc(); - let k = cb.query_word(); + let k = cb.query_word_rlc(); - let a_reduced = cb.query_word(); - let d = cb.query_word(); - let e = cb.query_word(); + let a_reduced = cb.query_word_rlc(); + let d = cb.query_word_rlc(); + let e = cb.query_word_rlc(); // 1. k1 * n + a_reduced == a let modword = ModGadget::construct(cb, [&a, &n, &a_reduced]); @@ -143,8 +143,7 @@ impl ExecutionGadget for MulModGadget { self.d.assign(region, offset, Some(d.to_le_bytes()))?; self.e.assign(region, offset, Some(e.to_le_bytes()))?; - self.modword - .assign(region, offset, a, n, a_reduced, block.randomness)?; + self.modword.assign(region, offset, a, n, a_reduced)?; self.mul512_left .assign(region, offset, [a_reduced, b, d, e], None)?; self.mul512_right diff --git a/zkevm-circuits/src/evm_circuit/execution/not.rs b/zkevm-circuits/src/evm_circuit/execution/not.rs index c90d0f5130..1d12c42820 100644 --- a/zkevm-circuits/src/evm_circuit/execution/not.rs +++ b/zkevm-circuits/src/evm_circuit/execution/not.rs @@ -31,8 +31,8 @@ impl ExecutionGadget for NotGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let opcode = cb.query_cell(); - let input = cb.query_word(); - let output = cb.query_word(); + let input = cb.query_word_rlc(); + let output = cb.query_word_rlc(); cb.stack_pop(input.expr()); cb.stack_push(output.expr()); diff --git a/zkevm-circuits/src/evm_circuit/execution/origin.rs b/zkevm-circuits/src/evm_circuit/execution/origin.rs index 9fb45b00b0..8694dda9f0 100644 --- a/zkevm-circuits/src/evm_circuit/execution/origin.rs +++ b/zkevm-circuits/src/evm_circuit/execution/origin.rs @@ -30,7 +30,7 @@ impl ExecutionGadget for OriginGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::ORIGIN; fn configure(cb: &mut ConstraintBuilder) -> Self { - let origin = cb.query_rlc::(); + let origin = cb.query_word_rlc::(); // Lookup in call_ctx the TxId let tx_id = cb.call_context(None, CallContextFieldTag::TxId); diff --git a/zkevm-circuits/src/evm_circuit/execution/pc.rs b/zkevm-circuits/src/evm_circuit/execution/pc.rs index 27b16e2e02..c52083ed1b 100644 --- a/zkevm-circuits/src/evm_circuit/execution/pc.rs +++ b/zkevm-circuits/src/evm_circuit/execution/pc.rs @@ -28,7 +28,7 @@ impl ExecutionGadget for PcGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::PC; fn configure(cb: &mut ConstraintBuilder) -> Self { - let value = cb.query_rlc(); + let value = cb.query_word_rlc(); // program_counter is limited to 64 bits so we only consider 8 bytes cb.require_equal( diff --git a/zkevm-circuits/src/evm_circuit/execution/pop.rs b/zkevm-circuits/src/evm_circuit/execution/pop.rs index 8fe37f4f71..22f997f20e 100644 --- a/zkevm-circuits/src/evm_circuit/execution/pop.rs +++ b/zkevm-circuits/src/evm_circuit/execution/pop.rs @@ -5,20 +5,20 @@ use crate::{ util::{ common_gadget::SameContextGadget, constraint_builder::{ConstraintBuilder, StepStateTransition, Transition::Delta}, - CachedRegion, Cell, Word, + CachedRegion, Cell, CellType, }, witness::{Block, Call, ExecStep, Transaction}, }, util::Expr, }; use bus_mapping::evm::OpcodeId; -use eth_types::{Field, ToLittleEndian}; -use halo2_proofs::{circuit::Value, plonk::Error}; +use eth_types::Field; +use halo2_proofs::plonk::Error; #[derive(Clone, Debug)] pub(crate) struct PopGadget { same_context: SameContextGadget, - value: Cell, + phase2_value: Cell, } impl ExecutionGadget for PopGadget { @@ -27,10 +27,10 @@ impl ExecutionGadget for PopGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::POP; fn configure(cb: &mut ConstraintBuilder) -> Self { - let value = cb.query_cell(); + let phase2_value = cb.query_cell_with_type(CellType::StoragePhase2); // Pop the value from the stack - cb.stack_pop(value.expr()); + cb.stack_pop(phase2_value.expr()); // State transition let step_state_transition = StepStateTransition { @@ -45,7 +45,7 @@ impl ExecutionGadget for PopGadget { Self { same_context, - value, + phase2_value, } } @@ -61,14 +61,8 @@ impl ExecutionGadget for PopGadget { self.same_context.assign_exec_step(region, offset, step)?; let value = block.rws[step.rw_indices[0]].stack_value(); - self.value.assign( - region, - offset, - Value::known(Word::random_linear_combine( - value.to_le_bytes(), - block.randomness, - )), - )?; + self.phase2_value + .assign(region, offset, region.word_rlc(value))?; Ok(()) } diff --git a/zkevm-circuits/src/evm_circuit/execution/push.rs b/zkevm-circuits/src/evm_circuit/execution/push.rs index b37065c911..dc64a2814e 100644 --- a/zkevm-circuits/src/evm_circuit/execution/push.rs +++ b/zkevm-circuits/src/evm_circuit/execution/push.rs @@ -30,7 +30,7 @@ impl ExecutionGadget for PushGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let opcode = cb.query_cell(); - let value = cb.query_rlc(); + let value = cb.query_word_rlc(); // Query selectors for each opcode_lookup let selectors = array_init(|_| cb.query_bool()); diff --git a/zkevm-circuits/src/evm_circuit/execution/return_revert.rs b/zkevm-circuits/src/evm_circuit/execution/return_revert.rs index d123c338a1..445caf96fe 100644 --- a/zkevm-circuits/src/evm_circuit/execution/return_revert.rs +++ b/zkevm-circuits/src/evm_circuit/execution/return_revert.rs @@ -11,7 +11,7 @@ use crate::{ }, math_gadget::{IsZeroGadget, MinMaxGadget}, memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}, - not, CachedRegion, Cell, RandomLinearCombination, Word, + not, CachedRegion, Cell, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -19,7 +19,7 @@ use crate::{ util::Expr, }; use bus_mapping::{circuit_input_builder::CopyDataType, evm::OpcodeId}; -use eth_types::{Field, ToScalar}; +use eth_types::{Field, ToScalar, U256}; use ethers_core::utils::keccak256; use halo2_proofs::{circuit::Value, plonk::Error}; use keccak256::EMPTY_HASH_LE; @@ -58,7 +58,7 @@ impl ExecutionGadget for ReturnRevertGadget { cb.opcode_lookup(opcode.expr(), 1.expr()); let offset = cb.query_cell(); - let length = cb.query_rlc(); + let length = cb.query_word_rlc(); cb.stack_pop(offset.expr()); cb.stack_pop(length.expr()); let range = MemoryAddressGadget::construct(cb, offset, length); @@ -121,10 +121,7 @@ impl ExecutionGadget for ReturnRevertGadget { .map(|tag| cb.call_context(None, tag)); let mut reversion_info = cb.reversion_info_read(None); - let empty_code_hash_rlc = Word::random_linear_combine_expr( - (*EMPTY_HASH_LE).map(|byte| byte.expr()), - cb.power_of_randomness(), - ); + let empty_code_hash_rlc = cb.word_rlc((*EMPTY_HASH_LE).map(|byte| byte.expr())); cb.account_write( address.expr(), @@ -256,9 +253,7 @@ impl ExecutionGadget for ReturnRevertGadget { )?; let [memory_offset, length] = [0, 1].map(|i| block.rws[step.rw_indices[i]].stack_value()); - let range = self - .range - .assign(region, offset, memory_offset, length, block.randomness)?; + let range = self.range.assign(region, offset, memory_offset, length)?; self.memory_expansion .assign(region, offset, step.memory_word_size(), [range])?; @@ -290,10 +285,7 @@ impl ExecutionGadget for ReturnRevertGadget { self.code_hash.assign( region, offset, - Value::known(RandomLinearCombination::random_linear_combine( - code_hash, - block.randomness, - )), + region.word_rlc(U256::from_little_endian(&code_hash)), )?; } diff --git a/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs b/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs index 274e0f0bfa..e046796b39 100644 --- a/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs @@ -61,8 +61,8 @@ impl ExecutionGadget for ReturnDataCopyGadget { let opcode = cb.query_cell(); let dest_offset = cb.query_cell(); - let data_offset = cb.query_rlc(); - let size = cb.query_rlc(); + let data_offset = cb.query_word_rlc(); + let size = cb.query_word_rlc(); // 1. Pop dest_offset, offset, length from stack cb.stack_pop(dest_offset.expr()); @@ -227,9 +227,9 @@ impl ExecutionGadget for ReturnDataCopyGadget { )?; // assign the destination memory offset. - let memory_address = - self.dst_memory_addr - .assign(region, offset, dest_offset, size, block.randomness)?; + let memory_address = self + .dst_memory_addr + .assign(region, offset, dest_offset, size)?; // assign to gadgets handling memory expansion cost and copying cost. let (_, memory_expansion_cost) = self.memory_expansion.assign( diff --git a/zkevm-circuits/src/evm_circuit/execution/returndatasize.rs b/zkevm-circuits/src/evm_circuit/execution/returndatasize.rs index 9d0732a23f..24a1ceb967 100644 --- a/zkevm-circuits/src/evm_circuit/execution/returndatasize.rs +++ b/zkevm-circuits/src/evm_circuit/execution/returndatasize.rs @@ -32,7 +32,7 @@ impl ExecutionGadget for ReturnDataSizeGadget { let opcode = cb.query_cell(); // Add lookup constraint in the call context for the returndatasize field. - let return_data_size = cb.query_rlc(); + let return_data_size = cb.query_word_rlc(); cb.call_context_lookup( false.expr(), None, diff --git a/zkevm-circuits/src/evm_circuit/execution/selfbalance.rs b/zkevm-circuits/src/evm_circuit/execution/selfbalance.rs index f8ea807303..2d366afd27 100644 --- a/zkevm-circuits/src/evm_circuit/execution/selfbalance.rs +++ b/zkevm-circuits/src/evm_circuit/execution/selfbalance.rs @@ -5,7 +5,7 @@ use crate::{ util::{ common_gadget::SameContextGadget, constraint_builder::{ConstraintBuilder, StepStateTransition, Transition::Delta}, - CachedRegion, Cell, Word, + CachedRegion, Cell, CellType, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -13,14 +13,14 @@ use crate::{ util::Expr, }; use bus_mapping::evm::OpcodeId; -use eth_types::{Field, ToLittleEndian, ToScalar}; +use eth_types::{Field, ToScalar}; use halo2_proofs::{circuit::Value, plonk::Error}; #[derive(Clone, Debug)] pub(crate) struct SelfbalanceGadget { same_context: SameContextGadget, callee_address: Cell, - self_balance: Cell, + phase2_self_balance: Cell, } impl ExecutionGadget for SelfbalanceGadget { @@ -31,14 +31,14 @@ impl ExecutionGadget for SelfbalanceGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let callee_address = cb.call_context(None, CallContextFieldTag::CalleeAddress); - let self_balance = cb.query_cell(); + let phase2_self_balance = cb.query_cell_with_type(CellType::StoragePhase2); cb.account_read( callee_address.expr(), AccountFieldTag::Balance, - self_balance.expr(), + phase2_self_balance.expr(), ); - cb.stack_push(self_balance.expr()); + cb.stack_push(phase2_self_balance.expr()); let opcode = cb.query_cell(); let step_state_transition = StepStateTransition { @@ -52,7 +52,7 @@ impl ExecutionGadget for SelfbalanceGadget { Self { same_context, - self_balance, + phase2_self_balance, callee_address, } } @@ -79,14 +79,8 @@ impl ExecutionGadget for SelfbalanceGadget { )?; let self_balance = block.rws[step.rw_indices[2]].stack_value(); - self.self_balance.assign( - region, - offset, - Value::known(Word::random_linear_combine( - self_balance.to_le_bytes(), - block.randomness, - )), - )?; + self.phase2_self_balance + .assign(region, offset, region.word_rlc(self_balance))?; Ok(()) } diff --git a/zkevm-circuits/src/evm_circuit/execution/sha3.rs b/zkevm-circuits/src/evm_circuit/execution/sha3.rs index 2b09155c13..635e8b1b26 100644 --- a/zkevm-circuits/src/evm_circuit/execution/sha3.rs +++ b/zkevm-circuits/src/evm_circuit/execution/sha3.rs @@ -37,8 +37,8 @@ impl ExecutionGadget for Sha3Gadget { let opcode = cb.query_cell(); let offset = cb.query_cell(); - let size = cb.query_rlc(); - let sha3_rlc = cb.query_rlc(); + let size = cb.query_word_rlc(); + let sha3_rlc = cb.query_word_rlc(); cb.stack_pop(offset.expr()); cb.stack_pop(size.expr()); @@ -48,6 +48,7 @@ impl ExecutionGadget for Sha3Gadget { let copy_rwc_inc = cb.query_cell(); let rlc_acc = cb.query_cell(); + cb.condition(memory_address.has_length(), |cb| { cb.copy_table_lookup( cb.curr.state.call_id.expr(), @@ -62,6 +63,7 @@ impl ExecutionGadget for Sha3Gadget { copy_rwc_inc.expr(), ); }); + cb.condition(not::expr(memory_address.has_length()), |cb| { cb.require_zero("copy_rwc_inc == 0 for size = 0", copy_rwc_inc.expr()); cb.require_zero("rlc_acc == 0 for size = 0", rlc_acc.expr()); @@ -112,9 +114,9 @@ impl ExecutionGadget for Sha3Gadget { let [memory_offset, size, sha3_output] = [step.rw_indices[0], step.rw_indices[1], step.rw_indices[2]] .map(|idx| block.rws[idx].stack_value()); - let memory_address = - self.memory_address - .assign(region, offset, memory_offset, size, block.randomness)?; + let memory_address = self + .memory_address + .assign(region, offset, memory_offset, size)?; self.sha3_rlc .assign(region, offset, Some(sha3_output.to_le_bytes()))?; @@ -130,8 +132,12 @@ impl ExecutionGadget for Sha3Gadget { let values: Vec = (3..3 + (size.low_u64() as usize)) .map(|i| block.rws[step.rw_indices[i]].memory_value()) .collect(); - let rlc_acc = rlc::value(values.iter().rev(), block.randomness); - self.rlc_acc.assign(region, offset, Value::known(rlc_acc))?; + + let rlc_acc = region + .challenges() + .keccak_input() + .map(|randomness| rlc::value(values.iter().rev(), randomness)); + self.rlc_acc.assign(region, offset, rlc_acc)?; // Memory expansion and dynamic gas cost for reading it. let (_, memory_expansion_gas_cost) = self.memory_expansion.assign( diff --git a/zkevm-circuits/src/evm_circuit/execution/shl_shr.rs b/zkevm-circuits/src/evm_circuit/execution/shl_shr.rs index b5dc703f95..551af565e0 100644 --- a/zkevm-circuits/src/evm_circuit/execution/shl_shr.rs +++ b/zkevm-circuits/src/evm_circuit/execution/shl_shr.rs @@ -54,11 +54,11 @@ impl ExecutionGadget for ShlShrGadget { let is_shl = OpcodeId::SHR.expr() - opcode.expr(); let is_shr = 1.expr() - is_shl.expr(); - let quotient = cb.query_word(); - let divisor = cb.query_word(); - let remainder = cb.query_word(); - let dividend = cb.query_word(); - let shift = cb.query_word(); + let quotient = cb.query_word_rlc(); + let divisor = cb.query_word_rlc(); + let remainder = cb.query_word_rlc(); + let dividend = cb.query_word_rlc(); + let shift = cb.query_word_rlc(); let shf0 = cb.query_cell(); let mul_add_words = diff --git a/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs b/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs index 46ea013bcb..e78898fc78 100644 --- a/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs +++ b/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs @@ -42,8 +42,8 @@ impl ExecutionGadget for SignedComparatorGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let opcode = cb.query_cell(); - let a = cb.query_word(); - let b = cb.query_word(); + let a = cb.query_word_rlc(); + let b = cb.query_word_rlc(); // The Signed Comparator gadget is used for both opcodes SLT and SGT. // Depending on whether the opcode is SLT or SGT, we diff --git a/zkevm-circuits/src/evm_circuit/execution/signextend.rs b/zkevm-circuits/src/evm_circuit/execution/signextend.rs index b5af6fdd93..ba670c8c60 100644 --- a/zkevm-circuits/src/evm_circuit/execution/signextend.rs +++ b/zkevm-circuits/src/evm_circuit/execution/signextend.rs @@ -17,7 +17,10 @@ use crate::{ use array_init::array_init; use bus_mapping::evm::OpcodeId; use eth_types::{Field, ToLittleEndian}; -use halo2_proofs::{circuit::Value, plonk::Error}; +use halo2_proofs::{ + circuit::Value, + plonk::{Error, Expression}, +}; #[derive(Clone, Debug)] pub(crate) struct SignextendGadget { @@ -36,8 +39,8 @@ impl ExecutionGadget for SignextendGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::SIGNEXTEND; fn configure(cb: &mut ConstraintBuilder) -> Self { - let index = cb.query_word(); - let value = cb.query_word(); + let index = cb.query_word_rlc(); + let value = cb.query_word_rlc(); let sign_byte = cb.query_cell(); let selectors = array_init(|_| cb.query_bool()); @@ -108,6 +111,8 @@ impl ExecutionGadget for SignextendGadget { // enabled need to be changed to the sign byte. // When a byte was selected all the **following** bytes need to be // replaced (hence the `selectors[idx - 1]`). + let powers_of_randomness: [Expression; 31] = + cb.challenges().evm_word_powers_of_randomness(); let result = Word::random_linear_combine_expr( array_init(|idx| { if idx == 0 { @@ -120,7 +125,7 @@ impl ExecutionGadget for SignextendGadget { ) } }), - cb.power_of_randomness(), + &powers_of_randomness, ); // Pop the byte index and the value from the stack, push the result on diff --git a/zkevm-circuits/src/evm_circuit/execution/sload.rs b/zkevm-circuits/src/evm_circuit/execution/sload.rs index d332875873..b6cdb5d98f 100644 --- a/zkevm-circuits/src/evm_circuit/execution/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/sload.rs @@ -7,14 +7,14 @@ use crate::{ constraint_builder::{ ConstraintBuilder, ReversionInfo, StepStateTransition, Transition::Delta, }, - select, CachedRegion, Cell, Word, + select, CachedRegion, Cell, CellType, }, witness::{Block, Call, ExecStep, Transaction}, }, table::CallContextFieldTag, util::Expr, }; -use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar}; +use eth_types::{evm_types::GasCost, Field, ToScalar}; use halo2_proofs::{ circuit::Value, plonk::{Error, Expression}, @@ -26,9 +26,9 @@ pub(crate) struct SloadGadget { tx_id: Cell, reversion_info: ReversionInfo, callee_address: Cell, - key: Cell, - value: Cell, - committed_value: Cell, + phase2_key: Cell, + phase2_value: Cell, + phase2_committed_value: Cell, is_warm: Cell, } @@ -44,27 +44,27 @@ impl ExecutionGadget for SloadGadget { let mut reversion_info = cb.reversion_info_read(None); let callee_address = cb.call_context(None, CallContextFieldTag::CalleeAddress); - let key = cb.query_cell(); + let phase2_key = cb.query_cell_with_type(CellType::StoragePhase2); // Pop the key from the stack - cb.stack_pop(key.expr()); + cb.stack_pop(phase2_key.expr()); - let value = cb.query_cell(); - let committed_value = cb.query_cell(); + let phase2_value = cb.query_cell_with_type(CellType::StoragePhase2); + let phase2_committed_value = cb.query_cell_with_type(CellType::StoragePhase2); cb.account_storage_read( callee_address.expr(), - key.expr(), - value.expr(), + phase2_key.expr(), + phase2_value.expr(), tx_id.expr(), - committed_value.expr(), + phase2_committed_value.expr(), ); - cb.stack_push(value.expr()); + cb.stack_push(phase2_value.expr()); let is_warm = cb.query_bool(); cb.account_storage_access_list_write( tx_id.expr(), callee_address.expr(), - key.expr(), + phase2_key.expr(), true.expr(), is_warm.expr(), Some(&mut reversion_info), @@ -85,9 +85,9 @@ impl ExecutionGadget for SloadGadget { tx_id, reversion_info, callee_address, - key, - value, - committed_value, + phase2_key, + phase2_value, + phase2_committed_value, is_warm, } } @@ -123,32 +123,14 @@ impl ExecutionGadget for SloadGadget { let [key, value] = [step.rw_indices[4], step.rw_indices[6]].map(|idx| block.rws[idx].stack_value()); - self.key.assign( - region, - offset, - Value::known(Word::random_linear_combine( - key.to_le_bytes(), - block.randomness, - )), - )?; - self.value.assign( - region, - offset, - Value::known(Word::random_linear_combine( - value.to_le_bytes(), - block.randomness, - )), - )?; + self.phase2_key + .assign(region, offset, region.word_rlc(key))?; + self.phase2_value + .assign(region, offset, region.word_rlc(value))?; let (_, committed_value) = block.rws[step.rw_indices[5]].aux_pair(); - self.committed_value.assign( - region, - offset, - Value::known(Word::random_linear_combine( - committed_value.to_le_bytes(), - block.randomness, - )), - )?; + self.phase2_committed_value + .assign(region, offset, region.word_rlc(committed_value))?; let (_, is_warm) = block.rws[step.rw_indices[7]].tx_access_list_value_pair(); self.is_warm diff --git a/zkevm-circuits/src/evm_circuit/execution/sstore.rs b/zkevm-circuits/src/evm_circuit/execution/sstore.rs index b2319e9c59..ef5889439a 100644 --- a/zkevm-circuits/src/evm_circuit/execution/sstore.rs +++ b/zkevm-circuits/src/evm_circuit/execution/sstore.rs @@ -8,7 +8,7 @@ use crate::{ ConstraintBuilder, ReversionInfo, StepStateTransition, Transition::Delta, }, math_gadget::{IsEqualGadget, IsZeroGadget}, - not, select, CachedRegion, Cell, Word, + not, select, CachedRegion, Cell, CellType, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -16,7 +16,7 @@ use crate::{ util::Expr, }; -use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar}; +use eth_types::{evm_types::GasCost, Field, ToScalar}; use halo2_proofs::{ circuit::Value, plonk::{Error, Expression}, @@ -29,10 +29,10 @@ pub(crate) struct SstoreGadget { is_static: Cell, reversion_info: ReversionInfo, callee_address: Cell, - key: Cell, - value: Cell, - value_prev: Cell, - original_value: Cell, + phase2_key: Cell, + phase2_value: Cell, + phase2_value_prev: Cell, + phase2_original_value: Cell, is_warm: Cell, tx_refund_prev: Cell, gas_cost: SstoreGasGadget, @@ -56,23 +56,23 @@ impl ExecutionGadget for SstoreGadget { let mut reversion_info = cb.reversion_info_read(None); let callee_address = cb.call_context(None, CallContextFieldTag::CalleeAddress); - let key = cb.query_cell(); + let phase2_key = cb.query_cell_with_type(CellType::StoragePhase2); // Pop the key from the stack - cb.stack_pop(key.expr()); + cb.stack_pop(phase2_key.expr()); - let value = cb.query_cell(); + let phase2_value = cb.query_cell_with_type(CellType::StoragePhase2); // Pop the value from the stack - cb.stack_pop(value.expr()); + cb.stack_pop(phase2_value.expr()); - let value_prev = cb.query_cell(); - let original_value = cb.query_cell(); + let phase2_value_prev = cb.query_cell_with_type(CellType::StoragePhase2); + let phase2_original_value = cb.query_cell_with_type(CellType::StoragePhase2); cb.account_storage_write( callee_address.expr(), - key.expr(), - value.expr(), - value_prev.expr(), + phase2_key.expr(), + phase2_value.expr(), + phase2_value_prev.expr(), tx_id.expr(), - original_value.expr(), + phase2_original_value.expr(), Some(&mut reversion_info), ); @@ -80,7 +80,7 @@ impl ExecutionGadget for SstoreGadget { cb.account_storage_access_list_write( tx_id.expr(), callee_address.expr(), - key.expr(), + phase2_key.expr(), true.expr(), is_warm.expr(), Some(&mut reversion_info), @@ -88,9 +88,9 @@ impl ExecutionGadget for SstoreGadget { let gas_cost = SstoreGasGadget::construct( cb, - value.clone(), - value_prev.clone(), - original_value.clone(), + phase2_value.clone(), + phase2_value_prev.clone(), + phase2_original_value.clone(), is_warm.clone(), ); @@ -98,9 +98,9 @@ impl ExecutionGadget for SstoreGadget { let tx_refund = SstoreTxRefundGadget::construct( cb, tx_refund_prev.clone(), - value.clone(), - value_prev.clone(), - original_value.clone(), + phase2_value.clone(), + phase2_value_prev.clone(), + phase2_original_value.clone(), ); cb.tx_refund_write( tx_id.expr(), @@ -125,10 +125,10 @@ impl ExecutionGadget for SstoreGadget { is_static, reversion_info, callee_address, - key, - value, - value_prev, - original_value, + phase2_key, + phase2_value, + phase2_value_prev, + phase2_original_value, is_warm, tx_refund_prev, gas_cost, @@ -169,40 +169,16 @@ impl ExecutionGadget for SstoreGadget { let [key, value] = [step.rw_indices[5], step.rw_indices[6]].map(|idx| block.rws[idx].stack_value()); - self.key.assign( - region, - offset, - Value::known(Word::random_linear_combine( - key.to_le_bytes(), - block.randomness, - )), - )?; - self.value.assign( - region, - offset, - Value::known(Word::random_linear_combine( - value.to_le_bytes(), - block.randomness, - )), - )?; + self.phase2_key + .assign(region, offset, region.word_rlc(key))?; + self.phase2_value + .assign(region, offset, region.word_rlc(value))?; let (_, value_prev, _, original_value) = block.rws[step.rw_indices[7]].storage_value_aux(); - self.value_prev.assign( - region, - offset, - Value::known(Word::random_linear_combine( - value_prev.to_le_bytes(), - block.randomness, - )), - )?; - self.original_value.assign( - region, - offset, - Value::known(Word::random_linear_combine( - original_value.to_le_bytes(), - block.randomness, - )), - )?; + self.phase2_value_prev + .assign(region, offset, region.word_rlc(value_prev))?; + self.phase2_original_value + .assign(region, offset, region.word_rlc(original_value))?; let (_, is_warm) = block.rws[step.rw_indices[8]].tx_access_list_value_pair(); self.is_warm @@ -220,7 +196,6 @@ impl ExecutionGadget for SstoreGadget { value_prev, original_value, is_warm, - block.randomness, )?; self.tx_refund.assign( @@ -231,7 +206,6 @@ impl ExecutionGadget for SstoreGadget { value, value_prev, original_value, - block.randomness, )?; Ok(()) } @@ -307,48 +281,28 @@ impl SstoreGasGadget { value_prev: eth_types::Word, original_value: eth_types::Word, is_warm: bool, - randomness: F, ) -> Result<(), Error> { - self.value.assign( - region, - offset, - Value::known(Word::random_linear_combine(value.to_le_bytes(), randomness)), - )?; - self.value_prev.assign( - region, - offset, - Value::known(Word::random_linear_combine( - value_prev.to_le_bytes(), - randomness, - )), - )?; - self.original_value.assign( - region, - offset, - Value::known(Word::random_linear_combine( - original_value.to_le_bytes(), - randomness, - )), - )?; + self.value.assign(region, offset, region.word_rlc(value))?; + self.value_prev + .assign(region, offset, region.word_rlc(value_prev))?; + self.original_value + .assign(region, offset, region.word_rlc(original_value))?; self.is_warm .assign(region, offset, Value::known(F::from(is_warm as u64)))?; - self.value_eq_prev.assign( + self.value_eq_prev.assign_value( region, offset, - Word::random_linear_combine(value.to_le_bytes(), randomness), - Word::random_linear_combine(value_prev.to_le_bytes(), randomness), + region.word_rlc(value), + region.word_rlc(value_prev), )?; - self.original_eq_prev.assign( + self.original_eq_prev.assign_value( region, offset, - Word::random_linear_combine(original_value.to_le_bytes(), randomness), - Word::random_linear_combine(value_prev.to_le_bytes(), randomness), - )?; - self.original_is_zero.assign( - region, - offset, - Word::random_linear_combine(original_value.to_le_bytes(), randomness), + region.word_rlc(original_value), + region.word_rlc(value_prev), )?; + self.original_is_zero + .assign_value(region, offset, region.word_rlc(original_value))?; debug_assert_eq!( calc_expected_gas_cost(value, value_prev, original_value, is_warm), gas_cost @@ -452,63 +406,40 @@ impl SstoreTxRefundGadget { value: eth_types::Word, value_prev: eth_types::Word, original_value: eth_types::Word, - randomness: F, ) -> Result<(), Error> { self.tx_refund_old .assign(region, offset, Value::known(F::from(tx_refund_old)))?; - self.value.assign( - region, - offset, - Value::known(Word::random_linear_combine(value.to_le_bytes(), randomness)), - )?; - self.value_prev.assign( - region, - offset, - Value::known(Word::random_linear_combine( - value_prev.to_le_bytes(), - randomness, - )), - )?; - self.original_value.assign( - region, - offset, - Value::known(Word::random_linear_combine( - original_value.to_le_bytes(), - randomness, - )), - )?; - self.value_prev_is_zero_gadget.assign( - region, - offset, - Word::random_linear_combine(value_prev.to_le_bytes(), randomness), - )?; - self.value_is_zero_gadget.assign( - region, - offset, - Word::random_linear_combine(value.to_le_bytes(), randomness), - )?; - self.original_is_zero_gadget.assign( + self.value.assign(region, offset, region.word_rlc(value))?; + self.value_prev + .assign(region, offset, region.word_rlc(value_prev))?; + self.original_value + .assign(region, offset, region.word_rlc(original_value))?; + self.value_prev_is_zero_gadget + .assign_value(region, offset, region.word_rlc(value_prev))?; + self.value_is_zero_gadget + .assign_value(region, offset, region.word_rlc(value))?; + self.original_is_zero_gadget.assign_value( region, offset, - Word::random_linear_combine(original_value.to_le_bytes(), randomness), + region.word_rlc(original_value), )?; - self.original_eq_value_gadget.assign( + self.original_eq_value_gadget.assign_value( region, offset, - Word::random_linear_combine(original_value.to_le_bytes(), randomness), - Word::random_linear_combine(value.to_le_bytes(), randomness), + region.word_rlc(original_value), + region.word_rlc(value), )?; - self.prev_eq_value_gadget.assign( + self.prev_eq_value_gadget.assign_value( region, offset, - Word::random_linear_combine(value_prev.to_le_bytes(), randomness), - Word::random_linear_combine(value.to_le_bytes(), randomness), + region.word_rlc(value_prev), + region.word_rlc(value), )?; - self.original_eq_prev_gadget.assign( + self.original_eq_prev_gadget.assign_value( region, offset, - Word::random_linear_combine(original_value.to_le_bytes(), randomness), - Word::random_linear_combine(value_prev.to_le_bytes(), randomness), + region.word_rlc(original_value), + region.word_rlc(value_prev), )?; debug_assert_eq!( calc_expected_tx_refund(tx_refund_old, value, value_prev, original_value), diff --git a/zkevm-circuits/src/evm_circuit/execution/swap.rs b/zkevm-circuits/src/evm_circuit/execution/swap.rs index d9b7125db1..0808574def 100644 --- a/zkevm-circuits/src/evm_circuit/execution/swap.rs +++ b/zkevm-circuits/src/evm_circuit/execution/swap.rs @@ -5,19 +5,19 @@ use crate::{ util::{ common_gadget::SameContextGadget, constraint_builder::{ConstraintBuilder, StepStateTransition, Transition::Delta}, - CachedRegion, Cell, Word, + CachedRegion, Cell, CellType, }, witness::{Block, Call, ExecStep, Transaction}, }, util::Expr, }; -use eth_types::{evm_types::OpcodeId, Field, ToLittleEndian}; -use halo2_proofs::{circuit::Value, plonk::Error}; +use eth_types::{evm_types::OpcodeId, Field}; +use halo2_proofs::plonk::Error; #[derive(Clone, Debug)] pub(crate) struct SwapGadget { same_context: SameContextGadget, - values: [Cell; 2], + phase2_values: [Cell; 2], } impl ExecutionGadget for SwapGadget { @@ -28,20 +28,23 @@ impl ExecutionGadget for SwapGadget { fn configure(cb: &mut ConstraintBuilder) -> Self { let opcode = cb.query_cell(); - let values = [cb.query_cell(), cb.query_cell()]; + let phase2_values = [ + cb.query_cell_with_type(CellType::StoragePhase2), + cb.query_cell_with_type(CellType::StoragePhase2), + ]; // The stack index we have to peek, deduced from the 'x' value of // 'swapx' The offset starts at 1 for SWAP1 let swap_offset = opcode.expr() - (OpcodeId::SWAP1.as_u64() - 1).expr(); // Peek the value at `swap_offset` - cb.stack_lookup(false.expr(), swap_offset.clone(), values[0].expr()); + cb.stack_lookup(false.expr(), swap_offset.clone(), phase2_values[0].expr()); // Peek the value at the top of the stack - cb.stack_lookup(false.expr(), 0.expr(), values[1].expr()); + cb.stack_lookup(false.expr(), 0.expr(), phase2_values[1].expr()); // Write the value previously at the top of the stack to `swap_offset` - cb.stack_lookup(true.expr(), swap_offset, values[1].expr()); + cb.stack_lookup(true.expr(), swap_offset, phase2_values[1].expr()); // Write the value previously at `swap_offset` to the top of the stack - cb.stack_lookup(true.expr(), 0.expr(), values[0].expr()); + cb.stack_lookup(true.expr(), 0.expr(), phase2_values[0].expr()); // State transition let step_state_transition = StepStateTransition { @@ -54,7 +57,7 @@ impl ExecutionGadget for SwapGadget { Self { same_context, - values, + phase2_values, } } @@ -69,19 +72,12 @@ impl ExecutionGadget for SwapGadget { ) -> Result<(), Error> { self.same_context.assign_exec_step(region, offset, step)?; - for (cell, value) in self.values.iter().zip( + for (cell, value) in self.phase2_values.iter().zip( [step.rw_indices[0], step.rw_indices[1]] .map(|idx| block.rws[idx].stack_value()) .iter(), ) { - cell.assign( - region, - offset, - Value::known(Word::random_linear_combine( - value.to_le_bytes(), - block.randomness, - )), - )?; + cell.assign(region, offset, region.word_rlc(*value))?; } Ok(()) diff --git a/zkevm-circuits/src/evm_circuit/param.rs b/zkevm-circuits/src/evm_circuit/param.rs index b392318735..cf12b26b1f 100644 --- a/zkevm-circuits/src/evm_circuit/param.rs +++ b/zkevm-circuits/src/evm_circuit/param.rs @@ -10,6 +10,12 @@ pub const MAX_STEP_HEIGHT: usize = 21; pub(crate) const STEP_STATE_HEIGHT: usize = 1; pub(crate) const N_CELLS_STEP_STATE: usize = 11; +// Number of phase2 columns +pub(crate) const N_PHASE2_COLUMNS: usize = 2; + +// Number of phase3 columns +pub(crate) const N_PHASE3_COLUMNS: usize = 1; + // Number of copy columns pub(crate) const N_COPY_COLUMNS: usize = 2; diff --git a/zkevm-circuits/src/evm_circuit/step.rs b/zkevm-circuits/src/evm_circuit/step.rs index 25b86b9793..be2011cd3a 100644 --- a/zkevm-circuits/src/evm_circuit/step.rs +++ b/zkevm-circuits/src/evm_circuit/step.rs @@ -2,13 +2,12 @@ use super::util::{CachedRegion, CellManager, CellType}; use crate::{ evm_circuit::{ param::{MAX_STEP_HEIGHT, STEP_STATE_HEIGHT, STEP_WIDTH}, - util::{Cell, RandomLinearCombination}, + util::Cell, witness::{Block, Call, ExecStep}, }, util::Expr, }; use bus_mapping::evm::OpcodeId; -use eth_types::ToLittleEndian; use halo2_proofs::{ arithmetic::FieldExt, circuit::Value, @@ -331,8 +330,8 @@ pub(crate) struct DynamicSelectorHalf { impl DynamicSelectorHalf { pub(crate) fn new(cell_manager: &mut CellManager, count: usize) -> Self { - let target_pairs = cell_manager.query_cells(CellType::Storage, (count + 1) / 2); - let target_odd = cell_manager.query_cell(CellType::Storage); + let target_pairs = cell_manager.query_cells(CellType::StoragePhase1, (count + 1) / 2); + let target_odd = cell_manager.query_cell(CellType::StoragePhase1); Self { count, target_pairs, @@ -474,17 +473,17 @@ impl Step { &mut cell_manager, ExecutionState::amount(), ), - rw_counter: cell_manager.query_cell(CellType::Storage), - call_id: cell_manager.query_cell(CellType::Storage), - is_root: cell_manager.query_cell(CellType::Storage), - is_create: cell_manager.query_cell(CellType::Storage), - code_hash: cell_manager.query_cell(CellType::Storage), - program_counter: cell_manager.query_cell(CellType::Storage), - stack_pointer: cell_manager.query_cell(CellType::Storage), - gas_left: cell_manager.query_cell(CellType::Storage), - memory_word_size: cell_manager.query_cell(CellType::Storage), - reversible_write_counter: cell_manager.query_cell(CellType::Storage), - log_id: cell_manager.query_cell(CellType::Storage), + rw_counter: cell_manager.query_cell(CellType::StoragePhase1), + call_id: cell_manager.query_cell(CellType::StoragePhase1), + is_root: cell_manager.query_cell(CellType::StoragePhase1), + is_create: cell_manager.query_cell(CellType::StoragePhase1), + code_hash: cell_manager.query_cell(CellType::StoragePhase2), + program_counter: cell_manager.query_cell(CellType::StoragePhase1), + stack_pointer: cell_manager.query_cell(CellType::StoragePhase1), + gas_left: cell_manager.query_cell(CellType::StoragePhase1), + memory_word_size: cell_manager.query_cell(CellType::StoragePhase1), + reversible_write_counter: cell_manager.query_cell(CellType::StoragePhase1), + log_id: cell_manager.query_cell(CellType::StoragePhase1), } }; Self { @@ -506,7 +505,7 @@ impl Step { &self, region: &mut CachedRegion<'_, '_, F>, offset: usize, - block: &Block, + _block: &Block, call: &Call, step: &ExecStep, ) -> Result<(), Error> { @@ -529,14 +528,9 @@ impl Step { offset, Value::known(F::from(call.is_create as u64)), )?; - self.state.code_hash.assign( - region, - offset, - Value::known(RandomLinearCombination::random_linear_combine( - call.code_hash.to_le_bytes(), - block.randomness, - )), - )?; + self.state + .code_hash + .assign(region, offset, region.word_rlc(call.code_hash))?; self.state.program_counter.assign( region, offset, diff --git a/zkevm-circuits/src/evm_circuit/util.rs b/zkevm-circuits/src/evm_circuit/util.rs index e204ab6cde..0af142a1ad 100644 --- a/zkevm-circuits/src/evm_circuit/util.rs +++ b/zkevm-circuits/src/evm_circuit/util.rs @@ -1,10 +1,14 @@ use crate::{ evm_circuit::{ - param::{LOOKUP_CONFIG, N_BYTES_MEMORY_ADDRESS, N_COPY_COLUMNS}, + param::{ + LOOKUP_CONFIG, N_BYTES_MEMORY_ADDRESS, N_COPY_COLUMNS, N_PHASE2_COLUMNS, + N_PHASE3_COLUMNS, + }, table::Table, }, - util::{query_expression, Expr}, + util::{query_expression, Challenges, Expr}, }; +use eth_types::ToLittleEndian; use eth_types::U256; use halo2_proofs::{ arithmetic::FieldExt, @@ -74,7 +78,7 @@ impl Expr for &Cell { pub struct CachedRegion<'r, 'b, F: FieldExt> { region: &'r mut Region<'b, F>, advice: Vec>, - power_of_randomness: [F; 31], + challenges: &'r Challenges>, width_start: usize, height_start: usize, } @@ -83,7 +87,7 @@ impl<'r, 'b, F: FieldExt> CachedRegion<'r, 'b, F> { /// New cached region pub(crate) fn new( region: &'r mut Region<'b, F>, - power_of_randomness: [F; 31], + challenges: &'r Challenges>, width: usize, height: usize, width_start: usize, @@ -92,7 +96,7 @@ impl<'r, 'b, F: FieldExt> CachedRegion<'r, 'b, F> { Self { region, advice: vec![vec![F::zero(); height]; width], - power_of_randomness, + challenges, width_start, height_start, } @@ -133,8 +137,14 @@ impl<'r, 'b, F: FieldExt> CachedRegion<'r, 'b, F> { [(((row_index - self.height_start) as i32) + rotation.0) as usize] } - pub fn get_instance(&self, _row_index: usize, column_index: usize, _rotation: Rotation) -> F { - self.power_of_randomness[column_index] + pub fn challenges(&self) -> &Challenges> { + self.challenges + } + + pub fn word_rlc(&self, n: U256) -> Value { + self.challenges + .evm_word() + .map(|r| Word::random_linear_combine(n.to_le_bytes(), r)) } /// Constrains a cell to have a constant value. @@ -159,7 +169,16 @@ pub struct StoredExpression { cell: Cell, cell_type: CellType, expr: Expression, - expr_id: String, + expr_id: Vec, +} + +use std::hash::{Hash, Hasher}; + +impl Hash for StoredExpression{ + fn hash(&self, state: &mut H) { + self.expr_id.hash(state); + self.cell_type.hash(state); + } } impl StoredExpression { @@ -168,39 +187,79 @@ impl StoredExpression { region: &mut CachedRegion<'_, '_, F>, offset: usize, ) -> Result, Error> { + let challenges = &[ + region.challenges.evm_word(), + region.challenges.keccak_input(), + ]; let value = self.expr.evaluate( - &|scalar| scalar, + &|scalar| Value::known(scalar), &|_| unimplemented!("selector column"), &|fixed_query| { - region.get_fixed(offset, fixed_query.column_index(), fixed_query.rotation()) + Value::known(region.get_fixed( + offset, + fixed_query.column_index(), + fixed_query.rotation(), + )) }, &|advide_query| { - region.get_advice(offset, advide_query.column_index(), advide_query.rotation()) - }, - &|instance_query| { - region.get_instance( + Value::known(region.get_advice( offset, - instance_query.column_index(), - instance_query.rotation(), - ) + advide_query.column_index(), + advide_query.rotation(), + )) }, - &|_| unimplemented!(), + &|_| unimplemented!("instance column"), + &|challenge| challenges[challenge.index()], &|a| -a, &|a, b| a + b, &|a, b| a * b, - &|a, scalar| a * scalar, + &|a, scalar| a * Value::known(scalar), ); - self.cell.assign(region, offset, Value::known(value)) + self.cell.assign(region, offset, value) } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub(crate) enum CellType { - Storage, + StoragePhase1, + StoragePhase2, + StoragePhase3, StoragePermutation, Lookup(Table), } +impl CellType { + fn expr_phase(value: &Expression) -> u8 { + use Expression::*; + match value { + Challenge(challenge) => challenge.phase() + 1, + Constant(_) | Selector(_) | Fixed(_) | Advice(_) | Instance(_) => 0, + Negated(a) | Expression::Scaled(a, _) => Self::expr_phase(a), + Sum(a, b) | Product(a, b) => std::cmp::max(Self::expr_phase(a), Self::expr_phase(b)), + } + } + + /// Return the phase of the expression + pub(crate) fn storage_for(value: &Expression) -> CellType { + match Self::expr_phase(value) { + 0 => CellType::StoragePhase1, + 1 => CellType::StoragePhase2, + 2 => CellType::StoragePhase3, + _ => unreachable!(), + } + } + + /// Return the phase of the expression + pub(crate) fn storage_for_inv(value: &Expression) -> CellType { + match Self::expr_phase(value) { + 0 => CellType::StoragePhase1, + 1 => CellType::StoragePhase3, + 2 => unimplemented!(), + _ => unreachable!(), + } + } +} + #[derive(Clone, Debug)] pub(crate) struct CellColumn { pub(crate) index: usize, @@ -241,15 +300,27 @@ impl CellManager { } columns.push(CellColumn { index: c, - cell_type: CellType::Storage, + cell_type: CellType::StoragePhase1, height: 0, expr: cells[c * height].expr(), }); } }); - // Mark columns used for lookups + // Mark columns used for Phase3 constraints let mut column_idx = 0; + for _ in 0..N_PHASE3_COLUMNS { + columns[column_idx].cell_type = CellType::StoragePhase3; + column_idx += 1; + } + + // Mark columns used for Phase2 constraints + for _ in 0..N_PHASE2_COLUMNS { + columns[column_idx].cell_type = CellType::StoragePhase2; + column_idx += 1; + } + + // Mark columns used for lookups for &(table, count) in LOOKUP_CONFIG { for _ in 0usize..count { columns[column_idx].cell_type = CellType::Lookup(table); @@ -297,7 +368,7 @@ impl CellManager { } // Replace a CellType::Storage by CellType::StoragePermutation if the later has // better height - if cell_type == CellType::Storage { + if cell_type == CellType::StoragePhase1 { for column in self.columns.iter() { if column.cell_type == CellType::StoragePermutation && column.height < best_height { best_index = Some(column.index); diff --git a/zkevm-circuits/src/evm_circuit/util/common_gadget.rs b/zkevm-circuits/src/evm_circuit/util/common_gadget.rs index 95663688e3..fc4e2d8da4 100644 --- a/zkevm-circuits/src/evm_circuit/util/common_gadget.rs +++ b/zkevm-circuits/src/evm_circuit/util/common_gadget.rs @@ -16,7 +16,7 @@ use crate::{ util::Expr, witness::{Block, Call, ExecStep}, }; -use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar, U256}; +use eth_types::{evm_types::GasCost, Field, ToScalar, U256}; use halo2_proofs::{ circuit::Value, plonk::{Error, Expression}, @@ -235,14 +235,8 @@ impl RestoreContextGadget { )?; } - self.caller_code_hash.assign( - region, - offset, - Value::known(Word::random_linear_combine( - caller_code_hash.to_le_bytes(), - block.randomness, - )), - )?; + self.caller_code_hash + .assign(region, offset, region.word_rlc(caller_code_hash))?; Ok(()) } @@ -264,8 +258,8 @@ impl ) -> Self { debug_assert!(updates.len() == N_ADDENDS - 1); - let balance_addend = cb.query_word(); - let balance_sum = cb.query_word(); + let balance_addend = cb.query_word_rlc(); + let balance_sum = cb.query_word_rlc(); let [value, value_prev] = if INCREASE { [balance_sum.expr(), balance_addend.expr()] diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index b39b9aaaa5..5ce3493669 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -9,7 +9,7 @@ use crate::{ AccountFieldTag, BytecodeFieldTag, CallContextFieldTag, RwTableTag, TxContextFieldTag, TxLogFieldTag, TxReceiptFieldTag, }, - util::{build_tx_log_expression, Expr}, + util::{build_tx_log_expression, Challenges, Expr}, }; use eth_types::Field; use gadgets::util::{and, not}; @@ -264,7 +264,8 @@ pub(crate) struct ConstraintBuilder<'a, F> { pub max_degree: usize, pub(crate) curr: Step, pub(crate) next: Step, - power_of_randomness: &'a [Expression; 31], + challenges: &'a Challenges>, + word_power_of_randomness: &'a [Expression; 31], execution_state: ExecutionState, constraints: Constraints, rw_counter_offset: Expression, @@ -281,14 +282,15 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { pub(crate) fn new( curr: Step, next: Step, - power_of_randomness: &'a [Expression; 31], + challenges: &'a Challenges>, + word_power_of_randomness: &'a [Expression;31], execution_state: ExecutionState, ) -> Self { Self { max_degree: MAX_DEGREE, curr, next, - power_of_randomness, + challenges, execution_state, constraints: Constraints { step: Vec::new(), @@ -304,6 +306,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { condition: None, constraints_location: ConstraintLocation::Step, stored_expressions: Vec::new(), + word_power_of_randomness, } } @@ -329,8 +332,8 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { ) } - pub(crate) fn power_of_randomness(&self) -> &[Expression] { - self.power_of_randomness + pub(crate) fn challenges(&self) -> &Challenges> { + self.challenges } pub(crate) fn execution_state(&self) -> ExecutionState { @@ -371,12 +374,8 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { self.query_cell_with_type(CellType::Lookup(Table::Byte)) } - pub(crate) fn query_word(&mut self) -> Word { - self.query_rlc() - } - - pub(crate) fn query_rlc(&mut self) -> RandomLinearCombination { - RandomLinearCombination::::new(self.query_bytes(), self.power_of_randomness) + pub(crate) fn query_word_rlc(&mut self) -> RandomLinearCombination { + RandomLinearCombination::::new(self.query_bytes(), self.word_power_of_randomness) } pub(crate) fn query_bytes(&mut self) -> [Cell; N] { @@ -388,7 +387,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { } pub(crate) fn query_cell(&mut self) -> Cell { - self.query_cell_with_type(CellType::Storage) + self.query_cell_with_type(CellType::StoragePhase1) } pub(crate) fn query_copy_cell(&mut self) -> Cell { @@ -399,6 +398,12 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { self.query_cells(cell_type, 1).first().unwrap().clone() } + pub(crate) fn query_bool_with_type(&mut self, cell_type: CellType) -> Cell { + let cell = self.query_cell_with_type(cell_type); + self.require_boolean("Constrain cell to be a bool", cell.expr()); + cell + } + fn query_cells(&mut self, cell_type: CellType, count: usize) -> Vec> { if self.in_next_step { &mut self.next @@ -409,6 +414,10 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { .query_cells(cell_type, count) } + pub(crate) fn word_rlc(&self, bytes: [Expression; N]) -> Expression { + RandomLinearCombination::random_linear_combine_expr(bytes, self.word_power_of_randomness) + } + // Common pub(crate) fn require_zero(&mut self, name: &'static str, constraint: Expression) { @@ -613,7 +622,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { field_tag: TxContextFieldTag, index: Option>, ) -> Word { - let word = self.query_word(); + let word = self.query_word_rlc(); self.tx_context_lookup(id, field_tag, index, word.expr()); word } @@ -984,7 +993,11 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { call_id: Option>, field_tag: CallContextFieldTag, ) -> Cell { - let cell = self.query_cell(); + let phase = match field_tag { + CallContextFieldTag::CodeHash => CellType::StoragePhase2, + _ => CellType::StoragePhase1, + }; + let cell = self.query_cell_with_type(phase); self.call_context_lookup(false.expr(), call_id, field_tag, cell.expr()); cell } @@ -1380,17 +1393,25 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { } pub(crate) fn add_lookup(&mut self, name: &str, lookup: Lookup) { + //let now = std::time::Instant::now(); let lookup = match &self.condition { Some(condition) => lookup.conditional(condition.clone()), None => lookup, }; - + //let diff_1 = now.elapsed(); let compressed_expr = self.split_expression( "Lookup compression", - rlc::expr(&lookup.input_exprs(), self.power_of_randomness), + rlc::expr(&lookup.input_exprs(), self.word_power_of_randomness), MAX_DEGREE - IMPLICIT_DEGREE, ); + //let diff_2 = now.elapsed(); self.store_expression(name, compressed_expr, CellType::Lookup(lookup.table())); + /* + if now.elapsed() > std::time::Duration::from_millis(2) { + let diff_3 = now.elapsed(); + println!("add_lookup: {:<10} {:<10} {:<10}", (diff_3 - diff_2).as_millis(), (diff_2 - diff_1).as_millis(), diff_1.as_millis() ); + } + */ } pub(crate) fn store_expression( @@ -1399,8 +1420,10 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { expr: Expression, cell_type: CellType, ) -> Expression { + // Check if we already stored the expression somewhere - let stored_expression = self.find_stored_expression(expr.clone(), cell_type); + let stored_expression = self.find_stored_expression(&expr, cell_type); + match stored_expression { Some(stored_expression) => { debug_assert!( @@ -1428,7 +1451,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { name, cell: cell.clone(), cell_type, - expr_id: expr.identifier(), + expr_id: expr.fast_identifier(), expr, }); cell.expr() @@ -1438,10 +1461,14 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { pub(crate) fn find_stored_expression( &self, - expr: Expression, + expr: &Expression, cell_type: CellType, ) -> Option<&StoredExpression> { - let expr_id = expr.identifier(); + let now = std::time::Instant::now(); + let expr_id = expr.fast_identifier(); + if now.elapsed().as_millis() > 0 { + println!("store_expression {} -> stored_expressions_len {}", now.elapsed().as_millis(), self.stored_expressions.len()); + } self.stored_expressions .iter() .find(|&e| e.cell_type == cell_type && e.expr_id == expr_id) @@ -1473,7 +1500,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { if expr.degree() > max_degree { self.split_expression(name, expr, max_degree) } else { - self.store_expression(name, expr, CellType::Storage) + self.store_expression(name, expr, CellType::StoragePhase1) } }; if a.degree() >= b.degree() { diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget.rs index 2c4f3ba736..83b391e40d 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget.rs @@ -1,4 +1,4 @@ -use super::CachedRegion; +use super::{CachedRegion, CellType}; use crate::{ evm_circuit::{ param::N_BYTES_WORD, @@ -24,7 +24,7 @@ pub struct IsZeroGadget { impl IsZeroGadget { pub(crate) fn construct(cb: &mut ConstraintBuilder, value: Expression) -> Self { - let inverse = cb.query_cell(); + let inverse = cb.query_cell_with_type(CellType::storage_for_inv(&value)); let is_zero = 1.expr() - (value.clone() * inverse.expr()); // when `value != 0` check `inverse = a.invert()`: value * (1 - value * @@ -58,6 +58,17 @@ impl IsZeroGadget { F::zero() }) } + + pub(crate) fn assign_value( + &self, + region: &mut CachedRegion<'_, '_, F>, + offset: usize, + value: Value, + ) -> Result, Error> { + value + .map(|value| self.assign(region, offset, value)) + .transpose() + } } /// Returns `1` when `lhs == rhs`, and returns `0` otherwise. @@ -90,6 +101,18 @@ impl IsEqualGadget { ) -> Result { self.is_zero.assign(region, offset, lhs - rhs) } + + pub(crate) fn assign_value( + &self, + region: &mut CachedRegion<'_, '_, F>, + offset: usize, + lhs: Value, + rhs: Value, + ) -> Result, Error> { + lhs.zip(rhs) + .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs)) + .transpose() + } } #[derive(Clone, Debug)] @@ -100,8 +123,16 @@ pub struct BatchedIsZeroGadget { impl BatchedIsZeroGadget { pub(crate) fn construct(cb: &mut ConstraintBuilder, values: [Expression; N]) -> Self { - let is_zero = cb.query_bool(); - let nonempty_witness = cb.query_cell(); + let values_in_phase_1 = values + .iter() + .any(|value| CellType::storage_for(value) == CellType::StoragePhase1); + let in_phase = if values_in_phase_1 { + CellType::StoragePhase2 + } else { + CellType::StoragePhase1 + }; + let is_zero = cb.query_bool_with_type(in_phase); + let nonempty_witness = cb.query_cell_with_type(in_phase); for value in values.iter() { cb.require_zero( @@ -145,6 +176,19 @@ impl BatchedIsZeroGadget { Ok(is_zero) } + + pub(crate) fn assign_value( + &self, + region: &mut CachedRegion<'_, '_, F>, + offset: usize, + values: [Value; N], + ) -> Result, Error> { + let values: Value<[F; N]> = + Value::>::from_iter(values).map(|vv| vv.try_into().unwrap()); + values + .map(|values| self.assign(region, offset, values)) + .transpose() + } } /// Construction of 2 256-bit words addition and result, which is useful for @@ -301,7 +345,7 @@ impl MulWordByU64Gadget { ) -> Self { let gadget = Self { multiplicand, - product: cb.query_word(), + product: cb.query_word_rlc(), carry_lo: cb.query_bytes(), }; @@ -471,6 +515,18 @@ impl LtGadget { pub(crate) fn diff_bytes(&self) -> Vec> { self.diff.to_vec() } + + pub(crate) fn assign_value( + &self, + region: &mut CachedRegion<'_, '_, F>, + offset: usize, + lhs: Value, + rhs: Value, + ) -> Result)>, Error> { + lhs.zip(rhs) + .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs)) + .transpose() + } } /// Returns `1` when `lhs < rhs`, and returns `0` otherwise. @@ -647,8 +703,8 @@ impl ConstantDivisionGadget { numerator: Expression, denominator: u64, ) -> Self { - let quotient = cb.query_cell(); - let remainder = cb.query_cell(); + let quotient = cb.query_cell_with_type(CellType::storage_for(&numerator)); + let remainder = cb.query_cell_with_type(CellType::storage_for(&numerator)); // Require that remainder < denominator cb.range_lookup(remainder.expr(), denominator); @@ -700,6 +756,16 @@ impl ConstantDivisionGadget { Ok((quotient, remainder)) } + pub(crate) fn assign_value( + &self, + region: &mut CachedRegion<'_, '_, F>, + offset: usize, + numerator: Value, + ) -> Result, Error> { + numerator + .map(|numerator| self.assign(region, offset, numerator.get_lower_128())) + .transpose() + } } /// Returns `rhs` when `lhs < rhs`, and returns `lhs` otherwise. @@ -747,6 +813,18 @@ impl MinMaxGadget { (lhs, rhs) }) } + + pub(crate) fn assign_value( + &self, + region: &mut CachedRegion<'_, '_, F>, + offset: usize, + lhs: Value, + rhs: Value, + ) -> Result, Error> { + lhs.zip(rhs) + .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs)) + .transpose() + } } // This function generates a Lagrange polynomial in the range [start, end) which @@ -1188,8 +1266,8 @@ pub(crate) struct ModGadget { impl ModGadget { pub(crate) fn construct(cb: &mut ConstraintBuilder, words: [&util::Word; 3]) -> Self { let (a, n, r) = (words[0], words[1], words[2]); - let k = cb.query_word(); - let a_or_zero = cb.query_word(); + let k = cb.query_word_rlc(); + let a_or_zero = cb.query_word_rlc(); let n_is_zero = IsZeroGadget::construct(cb, sum::expr(&n.cells)); let a_or_is_zero = IsZeroGadget::construct(cb, sum::expr(&a_or_zero.cells)); let mul = MulAddWordsGadget::construct(cb, [&k, n, r, &a_or_zero]); @@ -1226,7 +1304,6 @@ impl ModGadget { a: Word, n: Word, r: Word, - randomness: F, ) -> Result<(), Error> { let k = if n.is_zero() { Word::zero() } else { a / n }; let a_or_zero = if n.is_zero() { Word::zero() } else { a }; @@ -1241,11 +1318,11 @@ impl ModGadget { .assign(region, offset, F::from(a_or_zero_sum))?; self.mul.assign(region, offset, [k, n, r, a_or_zero])?; self.lt.assign(region, offset, r, n)?; - self.eq.assign( + self.eq.assign_value( region, offset, - util::Word::random_linear_combine(a.to_le_bytes(), randomness), - util::Word::random_linear_combine(a_or_zero.to_le_bytes(), randomness), + region.word_rlc(a), + region.word_rlc(a_or_zero), )?; Ok(()) @@ -1265,9 +1342,9 @@ pub(crate) struct AbsWordGadget { impl AbsWordGadget { pub(crate) fn construct(cb: &mut ConstraintBuilder) -> Self { - let x = cb.query_word(); - let x_abs = cb.query_word(); - let sum = cb.query_word(); + let x = cb.query_word_rlc(); + let x_abs = cb.query_word_rlc(); + let sum = cb.query_word_rlc(); let x_lo = from_bytes::expr(&x.cells[0..16]); let x_hi = from_bytes::expr(&x.cells[16..32]); let x_abs_lo = from_bytes::expr(&x_abs.cells[0..16]); diff --git a/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs b/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs index e6a6d5a48d..a06f97b63e 100644 --- a/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs +++ b/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs @@ -6,7 +6,7 @@ use crate::{ constraint_builder::ConstraintBuilder, from_bytes, math_gadget::{ConstantDivisionGadget, IsZeroGadget, MinMaxGadget, RangeCheckGadget}, - select, sum, Cell, MemoryAddress, Word, + select, sum, Cell, MemoryAddress, }, }, util::Expr, @@ -76,7 +76,7 @@ impl MemoryAddressGadget { memory_length: MemoryAddress, ) -> Self { let memory_length_is_zero = IsZeroGadget::construct(cb, sum::expr(&memory_length.cells)); - let memory_offset_bytes = cb.query_rlc(); + let memory_offset_bytes = cb.query_word_rlc(); let has_length = 1.expr() - memory_length_is_zero.expr(); cb.condition(has_length, |cb| { @@ -101,7 +101,6 @@ impl MemoryAddressGadget { offset: usize, memory_offset: U256, memory_length: U256, - randomness: F, ) -> Result { let memory_offset_bytes = memory_offset.to_le_bytes(); let memory_length_bytes = memory_length.to_le_bytes(); @@ -109,7 +108,7 @@ impl MemoryAddressGadget { self.memory_offset.assign( region, offset, - Value::known(Word::random_linear_combine(memory_offset_bytes, randomness)), + region.word_rlc(U256::from_little_endian(&memory_offset_bytes)), )?; self.memory_offset_bytes.assign( region, diff --git a/zkevm-circuits/src/state_circuit.rs b/zkevm-circuits/src/state_circuit.rs index 43e5873728..8761a846c0 100644 --- a/zkevm-circuits/src/state_circuit.rs +++ b/zkevm-circuits/src/state_circuit.rs @@ -90,6 +90,7 @@ impl SubCircuitConfig for StateCircuitConfig { ) -> Self { let selector = meta.fixed_column(); let lookups = LookupsChip::configure(meta); + let power_of_randomness : [Expression;31]= challenges.evm_word_powers_of_randomness(); let rw_counter = MpiChip::configure(meta, selector, rw_table.rw_counter, lookups); let tag = BinaryNumberChip::configure(meta, selector, Some(rw_table.tag)); @@ -101,7 +102,7 @@ impl SubCircuitConfig for StateCircuitConfig { selector, rw_table.storage_key, lookups, - challenges.evm_word_powers_of_randomness(), + power_of_randomness.clone(), ); let initial_value = meta.advice_column_in(SecondPhase); @@ -121,7 +122,7 @@ impl SubCircuitConfig for StateCircuitConfig { meta, sort_keys, lookups, - challenges.evm_word_powers_of_randomness(), + power_of_randomness.clone() ); let config = Self { @@ -133,7 +134,7 @@ impl SubCircuitConfig for StateCircuitConfig { lexicographic_ordering, not_first_access: meta.advice_column(), lookups, - power_of_randomness: challenges.evm_word_powers_of_randomness(), + power_of_randomness, rw_table, mpt_table, }; @@ -582,7 +583,7 @@ mod state_circuit_stats { let mut implemented_states = Vec::new(); for state in ExecutionState::iter() { - let height = circuit.execution.get_step_height_option(state); + let height = circuit.0.execution.get_step_height_option(state); if height.is_some() { implemented_states.push(state); } diff --git a/zkevm-circuits/src/super_circuit.rs b/zkevm-circuits/src/super_circuit.rs index 1c7e282b97..d75be28dd9 100644 --- a/zkevm-circuits/src/super_circuit.rs +++ b/zkevm-circuits/src/super_circuit.rs @@ -170,7 +170,7 @@ impl; 31] = array::from_fn(|i| { Expression::Constant(F::from(MOCK_RANDOMNESS).pow(&[1 + i as u64, 0, 0, 0])) }); @@ -228,14 +228,14 @@ impl, block: &BlockContext, - randomness: F, + randomness: Value, ) -> Result<(), Error> { layouter.assign_region( || "block table", @@ -709,7 +709,7 @@ impl BlockTable { || format!("block table row {}", offset), *column, offset, - || Value::known(value), + || value, )?; } offset += 1; @@ -816,6 +816,7 @@ impl KeccakTable { let keccak_table_columns = self.columns(); for input in inputs.clone() { for row in Self::assignments(input, challenges) { + dbg!(row); // let mut column_index = 0; for (column, value) in keccak_table_columns.iter().zip_eq(row) { region.assign_advice( @@ -913,8 +914,8 @@ impl CopyTable { .map(|(value, _)| *value) .collect::>(); challenges - .evm_word() - .map(|evm_word_challenge| rlc::value(values.iter().rev(), evm_word_challenge)) + .keccak_input() + .map(|keccak_input| rlc::value(values.iter().rev(), keccak_input)) } else { Value::known(F::zero()) }; diff --git a/zkevm-circuits/src/witness/block.rs b/zkevm-circuits/src/witness/block.rs index 0b22e1e517..4cb357161e 100644 --- a/zkevm-circuits/src/witness/block.rs +++ b/zkevm-circuits/src/witness/block.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, marker::PhantomData}; use crate::{evm_circuit::util::RandomLinearCombination, table::BlockContextFieldTag}; use bus_mapping::{ @@ -6,7 +6,7 @@ use bus_mapping::{ Error, }; use eth_types::{Address, Field, ToLittleEndian, ToScalar, Word}; -use halo2_proofs::halo2curves::bn256::Fr; +use halo2_proofs::{circuit::Value, halo2curves::bn256::Fr}; use itertools::Itertools; use super::{step::step_convert, tx::tx_convert, Bytecode, ExecStep, RwMap, Transaction}; @@ -18,6 +18,8 @@ use super::{step::step_convert, tx::tx_convert, Bytecode, ExecStep, RwMap, Trans pub struct Block { /// The randomness for random linear combination pub randomness: F, + /// TODO REMOVE + pub _marker: PhantomData, /// Transactions in the block pub txs: Vec, /// EndBlock step that is repeated after the last transaction and before @@ -77,52 +79,58 @@ pub struct BlockContext { impl BlockContext { /// Assignments for block table - pub fn table_assignments(&self, randomness: F) -> Vec<[F; 3]> { + pub fn table_assignments(&self, randomness: Value) -> Vec<[Value; 3]> { [ vec![ [ - F::from(BlockContextFieldTag::Coinbase as u64), - F::zero(), - self.coinbase.to_scalar().unwrap(), + Value::known(F::from(BlockContextFieldTag::Coinbase as u64)), + Value::known(F::zero()), + Value::known(self.coinbase.to_scalar().unwrap()), ], [ - F::from(BlockContextFieldTag::Timestamp as u64), - F::zero(), - self.timestamp.to_scalar().unwrap(), + Value::known(F::from(BlockContextFieldTag::Timestamp as u64)), + Value::known(F::zero()), + Value::known(self.timestamp.to_scalar().unwrap()), ], [ - F::from(BlockContextFieldTag::Number as u64), - F::zero(), - self.number.to_scalar().unwrap(), + Value::known(F::from(BlockContextFieldTag::Number as u64)), + Value::known(F::zero()), + Value::known(self.number.to_scalar().unwrap()), ], [ - F::from(BlockContextFieldTag::Difficulty as u64), - F::zero(), - RandomLinearCombination::random_linear_combine( - self.difficulty.to_le_bytes(), - randomness, - ), + Value::known(F::from(BlockContextFieldTag::Difficulty as u64)), + Value::known(F::zero()), + randomness.map(|randomness| { + RandomLinearCombination::random_linear_combine( + self.difficulty.to_le_bytes(), + randomness, + ) + }), ], [ - F::from(BlockContextFieldTag::GasLimit as u64), - F::zero(), - F::from(self.gas_limit), + Value::known(F::from(BlockContextFieldTag::GasLimit as u64)), + Value::known(F::zero()), + Value::known(F::from(self.gas_limit)), ], [ - F::from(BlockContextFieldTag::BaseFee as u64), - F::zero(), - RandomLinearCombination::random_linear_combine( - self.base_fee.to_le_bytes(), - randomness, - ), + Value::known(F::from(BlockContextFieldTag::BaseFee as u64)), + Value::known(F::zero()), + randomness.map(|randomness| { + RandomLinearCombination::random_linear_combine( + self.base_fee.to_le_bytes(), + randomness, + ) + }), ], [ - F::from(BlockContextFieldTag::ChainId as u64), - F::zero(), - RandomLinearCombination::random_linear_combine( - self.chain_id.to_le_bytes(), - randomness, - ), + Value::known(F::from(BlockContextFieldTag::ChainId as u64)), + Value::known(F::zero()), + randomness.map(|randomness| { + RandomLinearCombination::random_linear_combine( + self.chain_id.to_le_bytes(), + randomness, + ) + }), ], ], { @@ -132,12 +140,14 @@ impl BlockContext { .enumerate() .map(|(idx, hash)| { [ - F::from(BlockContextFieldTag::BlockHash as u64), - (self.number - len_history + idx).to_scalar().unwrap(), - RandomLinearCombination::random_linear_combine( - hash.to_le_bytes(), - randomness, - ), + Value::known(F::from(BlockContextFieldTag::BlockHash as u64)), + Value::known((self.number - len_history + idx).to_scalar().unwrap()), + randomness.map(|randomness| { + RandomLinearCombination::random_linear_combine( + hash.to_le_bytes(), + randomness, + ) + }), ] }) .collect() @@ -168,8 +178,9 @@ pub fn block_convert( code_db: &bus_mapping::state_db::CodeDB, ) -> Result, Error> { Ok(Block { - // randomness: Fr::from(0xcafeu64), // TODO: Uncomment - randomness: Fr::from(0x100), // Special value to reveal elements after RLC + randomness: Fr::from(0xcafeu64), // TODO: Uncomment + _marker: PhantomData::default(), + // randomness: Fr::from(0x100), // Special value to reveal elements after RLC context: block.into(), rws: RwMap::from(&block.container), txs: block diff --git a/zkevm-circuits/src/witness/rw.rs b/zkevm-circuits/src/witness/rw.rs index 8773c89043..9e092ff6a1 100644 --- a/zkevm-circuits/src/witness/rw.rs +++ b/zkevm-circuits/src/witness/rw.rs @@ -233,6 +233,10 @@ impl RwRow { .rev() .fold(F::zero(), |acc, value| acc * randomness + value) } + + pub(crate) fn rlc_value(&self, randomness: Value) -> Value { + randomness.map(|randomness| self.rlc(randomness)) + } } impl Rw { From f6da00f3693106bece8bff8133e65fbf5ac390a6 Mon Sep 17 00:00:00 2001 From: adria0 Date: Thu, 15 Dec 2022 12:27:44 +0100 Subject: [PATCH 02/18] Fixed copy_circuit_valid_sha3 --- zkevm-circuits/src/copy_circuit.rs | 2 +- zkevm-circuits/src/table.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zkevm-circuits/src/copy_circuit.rs b/zkevm-circuits/src/copy_circuit.rs index 788a77896d..7ee6f551a1 100644 --- a/zkevm-circuits/src/copy_circuit.rs +++ b/zkevm-circuits/src/copy_circuit.rs @@ -308,7 +308,7 @@ impl SubCircuitConfig for CopyCircuitConfig { cb.require_equal( "rows[2].value == rows[0].value * r + rows[1].value", meta.query_advice(value, Rotation(2)), - meta.query_advice(value, Rotation::cur()) * challenges.evm_word() + meta.query_advice(value, Rotation::cur()) * challenges.keccak_input() + meta.query_advice(value, Rotation::next()), ); diff --git a/zkevm-circuits/src/table.rs b/zkevm-circuits/src/table.rs index ca055ef98d..945d7d979f 100644 --- a/zkevm-circuits/src/table.rs +++ b/zkevm-circuits/src/table.rs @@ -996,7 +996,7 @@ impl CopyTable { if is_read_step { Value::known(F::from(copy_step.value as u64)) } else { - value_acc = value_acc * challenges.evm_word() + value_acc = value_acc * challenges.keccak_input() + Value::known(F::from(copy_step.value as u64)); value_acc } From eaafdf9b281ae9ab0012b1f2d72f0fbe744480b9 Mon Sep 17 00:00:00 2001 From: adria0 Date: Fri, 16 Dec 2022 11:29:55 +0100 Subject: [PATCH 03/18] Remove leftovers --- .../src/evm_circuit/util/constraint_builder.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index 5ce3493669..a73ab6a9bf 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -1393,25 +1393,16 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { } pub(crate) fn add_lookup(&mut self, name: &str, lookup: Lookup) { - //let now = std::time::Instant::now(); let lookup = match &self.condition { Some(condition) => lookup.conditional(condition.clone()), None => lookup, }; - //let diff_1 = now.elapsed(); let compressed_expr = self.split_expression( "Lookup compression", rlc::expr(&lookup.input_exprs(), self.word_power_of_randomness), MAX_DEGREE - IMPLICIT_DEGREE, ); - //let diff_2 = now.elapsed(); self.store_expression(name, compressed_expr, CellType::Lookup(lookup.table())); - /* - if now.elapsed() > std::time::Duration::from_millis(2) { - let diff_3 = now.elapsed(); - println!("add_lookup: {:<10} {:<10} {:<10}", (diff_3 - diff_2).as_millis(), (diff_2 - diff_1).as_millis(), diff_1.as_millis() ); - } - */ } pub(crate) fn store_expression( @@ -1464,11 +1455,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { expr: &Expression, cell_type: CellType, ) -> Option<&StoredExpression> { - let now = std::time::Instant::now(); let expr_id = expr.fast_identifier(); - if now.elapsed().as_millis() > 0 { - println!("store_expression {} -> stored_expressions_len {}", now.elapsed().as_millis(), self.stored_expressions.len()); - } self.stored_expressions .iter() .find(|&e| e.cell_type == cell_type && e.expr_id == expr_id) From 8120bd4cdecfbfe94224562c24c157c9f5cdb8cb Mon Sep 17 00:00:00 2001 From: adria0 Date: Fri, 16 Dec 2022 12:49:35 +0100 Subject: [PATCH 04/18] lookup_input wip --- zkevm-circuits/src/evm_circuit/execution.rs | 13 ++++--- zkevm-circuits/src/evm_circuit/util.rs | 7 ++-- .../evm_circuit/util/constraint_builder.rs | 15 ++++---- zkevm-circuits/src/super_circuit.rs | 2 ++ zkevm-circuits/src/util.rs | 35 ++++++++++++++++--- 5 files changed, 53 insertions(+), 19 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index e25ad501a0..8505e3997c 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -411,6 +411,7 @@ impl ExecutionConfig { let step_next = Step::new(meta, advices, MAX_STEP_HEIGHT, true); let word_powers_of_randomness : [Expression;31] = challenges.evm_word_powers_of_randomness(); + let lookup_powers_of_randomness : [Expression;31] = challenges.lookup_input_powers_of_randomness(); macro_rules! configure_gadget { () => { Self::configure_gadget( @@ -423,6 +424,7 @@ impl ExecutionConfig { q_step_last, &challenges, &word_powers_of_randomness, + &lookup_powers_of_randomness, &step_curr, &step_next, &mut height_map, @@ -576,7 +578,8 @@ impl ExecutionConfig { q_step_first: Selector, q_step_last: Selector, challenges: &Challenges>, - word_power_of_randomness: &[Expression;31], + word_powers_of_randomness: &[Expression;31], + lookup_powers_of_randomness: &[Expression;31], step_curr: &Step, step_next: &Step, height_map: &mut HashMap, @@ -589,7 +592,8 @@ impl ExecutionConfig { step_curr.clone(), step_next.clone(), challenges, - word_power_of_randomness, + word_powers_of_randomness, + lookup_powers_of_randomness, G::EXECUTION_STATE, ); G::configure(&mut cb); @@ -603,7 +607,8 @@ impl ExecutionConfig { step_curr.clone(), step_next.clone(), &challenges, - word_power_of_randomness, + word_powers_of_randomness, + lookup_powers_of_randomness, G::EXECUTION_STATE, ); @@ -738,7 +743,7 @@ impl ExecutionConfig { challenges: &Challenges>, cell_manager: &CellManager, ) { - let powers_of_randomness: [Expression; 31] = challenges.evm_word_powers_of_randomness(); + let powers_of_randomness: [Expression; 31] = challenges.lookup_input_powers_of_randomness(); for column in cell_manager.columns().iter() { if let CellType::Lookup(table) = column.cell_type { let name = format!("{:?}", table); diff --git a/zkevm-circuits/src/evm_circuit/util.rs b/zkevm-circuits/src/evm_circuit/util.rs index 0af142a1ad..93dac28f2d 100644 --- a/zkevm-circuits/src/evm_circuit/util.rs +++ b/zkevm-circuits/src/evm_circuit/util.rs @@ -187,10 +187,6 @@ impl StoredExpression { region: &mut CachedRegion<'_, '_, F>, offset: usize, ) -> Result, Error> { - let challenges = &[ - region.challenges.evm_word(), - region.challenges.keccak_input(), - ]; let value = self.expr.evaluate( &|scalar| Value::known(scalar), &|_| unimplemented!("selector column"), @@ -209,7 +205,7 @@ impl StoredExpression { )) }, &|_| unimplemented!("instance column"), - &|challenge| challenges[challenge.index()], + &|challenge| *region.challenges().indexed()[challenge.index()], &|a| -a, &|a, b| a + b, &|a, b| a * b, @@ -226,6 +222,7 @@ pub(crate) enum CellType { StoragePhase3, StoragePermutation, Lookup(Table), + LookupPhase3(Table) } impl CellType { diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index a73ab6a9bf..625ca46c2c 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -265,7 +265,8 @@ pub(crate) struct ConstraintBuilder<'a, F> { pub(crate) curr: Step, pub(crate) next: Step, challenges: &'a Challenges>, - word_power_of_randomness: &'a [Expression; 31], + word_powers_of_randomness: &'a [Expression; 31], + lookup_powers_of_randomness: &'a [Expression; 31], execution_state: ExecutionState, constraints: Constraints, rw_counter_offset: Expression, @@ -283,7 +284,8 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { curr: Step, next: Step, challenges: &'a Challenges>, - word_power_of_randomness: &'a [Expression;31], + word_powers_of_randomness: &'a [Expression;31], + lookup_powers_of_randomness: &'a [Expression;31], execution_state: ExecutionState, ) -> Self { Self { @@ -306,7 +308,8 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { condition: None, constraints_location: ConstraintLocation::Step, stored_expressions: Vec::new(), - word_power_of_randomness, + word_powers_of_randomness, + lookup_powers_of_randomness, } } @@ -375,7 +378,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { } pub(crate) fn query_word_rlc(&mut self) -> RandomLinearCombination { - RandomLinearCombination::::new(self.query_bytes(), self.word_power_of_randomness) + RandomLinearCombination::::new(self.query_bytes(), self.word_powers_of_randomness) } pub(crate) fn query_bytes(&mut self) -> [Cell; N] { @@ -415,7 +418,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { } pub(crate) fn word_rlc(&self, bytes: [Expression; N]) -> Expression { - RandomLinearCombination::random_linear_combine_expr(bytes, self.word_power_of_randomness) + RandomLinearCombination::random_linear_combine_expr(bytes, self.word_powers_of_randomness) } // Common @@ -1399,7 +1402,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { }; let compressed_expr = self.split_expression( "Lookup compression", - rlc::expr(&lookup.input_exprs(), self.word_power_of_randomness), + rlc::expr(&lookup.input_exprs(), self.lookup_powers_of_randomness), MAX_DEGREE - IMPLICIT_DEGREE, ); self.store_expression(name, compressed_expr, CellType::Lookup(lookup.table())); diff --git a/zkevm-circuits/src/super_circuit.rs b/zkevm-circuits/src/super_circuit.rs index d75be28dd9..3656ef10da 100644 --- a/zkevm-circuits/src/super_circuit.rs +++ b/zkevm-circuits/src/super_circuit.rs @@ -177,6 +177,7 @@ impl( pub struct Challenges { evm_word: T, keccak_input: T, + lookup_input: T, } impl Challenges { @@ -61,17 +62,19 @@ impl Challenges { Self { evm_word: meta.challenge_usable_after(FirstPhase), keccak_input: meta.challenge_usable_after(FirstPhase), + lookup_input: meta.challenge_usable_after(SecondPhase), } } /// Returns `Expression` of challenges from `ConstraintSystem`. pub fn exprs(&self, meta: &mut ConstraintSystem) -> Challenges> { - let [evm_word, keccak_input] = query_expression(meta, |meta| { - [self.evm_word, self.keccak_input].map(|challenge| meta.query_challenge(challenge)) + let [evm_word, keccak_input, lookup_input] = query_expression(meta, |meta| { + [self.evm_word, self.keccak_input, self.lookup_input].map(|challenge| meta.query_challenge(challenge)) }); Challenges { evm_word, keccak_input, + lookup_input, } } @@ -80,6 +83,7 @@ impl Challenges { Challenges { evm_word: layouter.get_challenge(self.evm_word), keccak_input: layouter.get_challenge(self.keccak_input), + lookup_input: layouter.get_challenge(self.lookup_input), } } } @@ -95,10 +99,21 @@ impl Challenges { self.keccak_input.clone() } - pub(crate) fn mock(evm_word: T, keccak_input: T) -> Self { + /// Returns challenge of `lookup_input`. + pub fn lookup_input(&self) -> T { + self.lookup_input.clone() + } + + /// Returns the challenges indexed by the challenge index + pub fn indexed(&self ) -> [&T;3] { + [&self.evm_word, &self.keccak_input, &self.lookup_input] + } + + pub(crate) fn mock(evm_word: T, keccak_input: T, lookup_input: T) -> Self { Self { evm_word, keccak_input, + lookup_input } } } @@ -114,6 +129,18 @@ impl Challenges> { .try_into() .unwrap() } + + /// Returns powers of randomness for lookups + pub fn lookup_input_powers_of_randomness(&self) -> [Expression; S] { + std::iter::successors(self.lookup_input.clone().into(), |power| { + (self.lookup_input.clone() * power.clone()).into() + }) + .take(S) + .collect::>() + .try_into() + .unwrap() + } + } pub(crate) fn build_tx_log_address(index: u64, field_tag: TxLogFieldTag, log_id: u64) -> Address { From 74b9b8b4fc3e0eb09228bf3cfc3d7961c026e580 Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 2 Jan 2023 12:49:15 +0100 Subject: [PATCH 05/18] fix _dummy_cols, cleanup, fmt --- zkevm-circuits/src/evm_circuit/execution.rs | 20 ++++---- .../src/evm_circuit/execution/callop.rs | 8 +-- .../src/evm_circuit/execution/sha3.rs | 4 +- zkevm-circuits/src/evm_circuit/util.rs | 4 +- .../evm_circuit/util/constraint_builder.rs | 5 +- zkevm-circuits/src/state_circuit.rs | 4 +- zkevm-circuits/src/table.rs | 1 - zkevm-circuits/src/util.rs | 49 ++++++++++--------- 8 files changed, 51 insertions(+), 44 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 8505e3997c..4573e1b904 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -322,7 +322,6 @@ impl ExecutionConfig { .try_into() .unwrap(); - let step_curr = Step::new(meta, advices, 0, false); let mut height_map = HashMap::new(); @@ -410,11 +409,13 @@ impl ExecutionConfig { let mut stored_expressions_map = HashMap::new(); let step_next = Step::new(meta, advices, MAX_STEP_HEIGHT, true); - let word_powers_of_randomness : [Expression;31] = challenges.evm_word_powers_of_randomness(); - let lookup_powers_of_randomness : [Expression;31] = challenges.lookup_input_powers_of_randomness(); + let word_powers_of_randomness: [Expression; 31] = + challenges.evm_word_powers_of_randomness(); + let lookup_powers_of_randomness: [Expression; 31] = + challenges.lookup_input_powers_of_randomness(); macro_rules! configure_gadget { () => { - Self::configure_gadget( + Self::configure_gadget( meta, advices, q_usable, @@ -578,8 +579,8 @@ impl ExecutionConfig { q_step_first: Selector, q_step_last: Selector, challenges: &Challenges>, - word_powers_of_randomness: &[Expression;31], - lookup_powers_of_randomness: &[Expression;31], + word_powers_of_randomness: &[Expression; 31], + lookup_powers_of_randomness: &[Expression; 31], step_curr: &Step, step_next: &Step, height_map: &mut HashMap, @@ -629,7 +630,7 @@ impl ExecutionConfig { !height_map.contains_key(&G::EXECUTION_STATE), "execution state already configured" ); - + height_map.insert(G::EXECUTION_STATE, height); debug_assert!( !stored_expressions_map.contains_key(&G::EXECUTION_STATE), @@ -743,7 +744,8 @@ impl ExecutionConfig { challenges: &Challenges>, cell_manager: &CellManager, ) { - let powers_of_randomness: [Expression; 31] = challenges.lookup_input_powers_of_randomness(); + let lookup_powers_of_randomness: [Expression; 31] = + challenges.lookup_input_powers_of_randomness(); for column in cell_manager.columns().iter() { if let CellType::Lookup(table) = column.cell_type { let name = format!("{:?}", table); @@ -762,7 +764,7 @@ impl ExecutionConfig { .table_exprs(meta); vec![( column.expr(), - rlc::expr(&table_expressions, &powers_of_randomness), + rlc::expr(&table_expressions, &lookup_powers_of_randomness), )] }); } diff --git a/zkevm-circuits/src/evm_circuit/execution/callop.rs b/zkevm-circuits/src/evm_circuit/execution/callop.rs index b93f16450c..c531670588 100644 --- a/zkevm-circuits/src/evm_circuit/execution/callop.rs +++ b/zkevm-circuits/src/evm_circuit/execution/callop.rs @@ -64,7 +64,6 @@ impl ExecutionGadget for CallOpGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::CALL_OP; fn configure(cb: &mut ConstraintBuilder) -> Self { - let opcode = cb.query_cell(); cb.opcode_lookup(opcode.expr(), 1.expr()); let is_call = IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::CALL.expr()); @@ -359,7 +358,7 @@ impl ExecutionGadget for CallOpGadget { ..StepStateTransition::new_context() }); }); - + Self { opcode, is_call, @@ -856,7 +855,10 @@ mod test { #[test] fn callop_base() { - test_ok(caller(&OpcodeId::CALL, Stack::default(), true), callee(bytecode!{})); + test_ok( + caller(&OpcodeId::CALL, Stack::default(), true), + callee(bytecode! {}), + ); // use crate::evm_circuit::util::print_op_count; // print_op_count(); } diff --git a/zkevm-circuits/src/evm_circuit/execution/sha3.rs b/zkevm-circuits/src/evm_circuit/execution/sha3.rs index 635e8b1b26..581f559707 100644 --- a/zkevm-circuits/src/evm_circuit/execution/sha3.rs +++ b/zkevm-circuits/src/evm_circuit/execution/sha3.rs @@ -48,7 +48,7 @@ impl ExecutionGadget for Sha3Gadget { let copy_rwc_inc = cb.query_cell(); let rlc_acc = cb.query_cell(); - + cb.condition(memory_address.has_length(), |cb| { cb.copy_table_lookup( cb.curr.state.call_id.expr(), @@ -63,7 +63,7 @@ impl ExecutionGadget for Sha3Gadget { copy_rwc_inc.expr(), ); }); - + cb.condition(not::expr(memory_address.has_length()), |cb| { cb.require_zero("copy_rwc_inc == 0 for size = 0", copy_rwc_inc.expr()); cb.require_zero("rlc_acc == 0 for size = 0", rlc_acc.expr()); diff --git a/zkevm-circuits/src/evm_circuit/util.rs b/zkevm-circuits/src/evm_circuit/util.rs index 93dac28f2d..c32ebb81b6 100644 --- a/zkevm-circuits/src/evm_circuit/util.rs +++ b/zkevm-circuits/src/evm_circuit/util.rs @@ -174,7 +174,7 @@ pub struct StoredExpression { use std::hash::{Hash, Hasher}; -impl Hash for StoredExpression{ +impl Hash for StoredExpression { fn hash(&self, state: &mut H) { self.expr_id.hash(state); self.cell_type.hash(state); @@ -222,7 +222,7 @@ pub(crate) enum CellType { StoragePhase3, StoragePermutation, Lookup(Table), - LookupPhase3(Table) + LookupPhase3(Table), } impl CellType { diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index 625ca46c2c..ebdd7bd3c9 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -284,8 +284,8 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { curr: Step, next: Step, challenges: &'a Challenges>, - word_powers_of_randomness: &'a [Expression;31], - lookup_powers_of_randomness: &'a [Expression;31], + word_powers_of_randomness: &'a [Expression; 31], + lookup_powers_of_randomness: &'a [Expression; 31], execution_state: ExecutionState, ) -> Self { Self { @@ -1414,7 +1414,6 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { expr: Expression, cell_type: CellType, ) -> Expression { - // Check if we already stored the expression somewhere let stored_expression = self.find_stored_expression(&expr, cell_type); diff --git a/zkevm-circuits/src/state_circuit.rs b/zkevm-circuits/src/state_circuit.rs index 8761a846c0..68744af7d8 100644 --- a/zkevm-circuits/src/state_circuit.rs +++ b/zkevm-circuits/src/state_circuit.rs @@ -90,7 +90,7 @@ impl SubCircuitConfig for StateCircuitConfig { ) -> Self { let selector = meta.fixed_column(); let lookups = LookupsChip::configure(meta); - let power_of_randomness : [Expression;31]= challenges.evm_word_powers_of_randomness(); + let power_of_randomness: [Expression; 31] = challenges.evm_word_powers_of_randomness(); let rw_counter = MpiChip::configure(meta, selector, rw_table.rw_counter, lookups); let tag = BinaryNumberChip::configure(meta, selector, Some(rw_table.tag)); @@ -122,7 +122,7 @@ impl SubCircuitConfig for StateCircuitConfig { meta, sort_keys, lookups, - power_of_randomness.clone() + power_of_randomness.clone(), ); let config = Self { diff --git a/zkevm-circuits/src/table.rs b/zkevm-circuits/src/table.rs index 945d7d979f..4915a1891a 100644 --- a/zkevm-circuits/src/table.rs +++ b/zkevm-circuits/src/table.rs @@ -816,7 +816,6 @@ impl KeccakTable { let keccak_table_columns = self.columns(); for input in inputs.clone() { for row in Self::assignments(input, challenges) { - dbg!(row); // let mut column_index = 0; for (column, value) in keccak_table_columns.iter().zip_eq(row) { region.assign_advice( diff --git a/zkevm-circuits/src/util.rs b/zkevm-circuits/src/util.rs index bf78743a42..16ee1c01d2 100644 --- a/zkevm-circuits/src/util.rs +++ b/zkevm-circuits/src/util.rs @@ -2,7 +2,9 @@ use halo2_proofs::{ arithmetic::FieldExt, circuit::{Layouter, Value}, - plonk::{Challenge, ConstraintSystem, Error, Expression, FirstPhase, VirtualCells, SecondPhase}, + plonk::{ + Challenge, ConstraintSystem, Error, Expression, FirstPhase, SecondPhase, VirtualCells, + }, poly::Rotation, }; @@ -57,7 +59,11 @@ impl Challenges { /// Construct `Challenges` by allocating challenges in specific phases. pub fn construct(meta: &mut ConstraintSystem) -> Self { #[cfg(test)] - let _dummy_col = meta.advice_column(); + let _dummy_cols = [ + meta.advice_column(), + meta.advice_column_in(SecondPhase), + meta.advice_column_in(halo2_proofs::plonk::ThirdPhase), + ]; Self { evm_word: meta.challenge_usable_after(FirstPhase), @@ -69,7 +75,8 @@ impl Challenges { /// Returns `Expression` of challenges from `ConstraintSystem`. pub fn exprs(&self, meta: &mut ConstraintSystem) -> Challenges> { let [evm_word, keccak_input, lookup_input] = query_expression(meta, |meta| { - [self.evm_word, self.keccak_input, self.lookup_input].map(|challenge| meta.query_challenge(challenge)) + [self.evm_word, self.keccak_input, self.lookup_input] + .map(|challenge| meta.query_challenge(challenge)) }); Challenges { evm_word, @@ -99,30 +106,30 @@ impl Challenges { self.keccak_input.clone() } - /// Returns challenge of `lookup_input`. - pub fn lookup_input(&self) -> T { - self.lookup_input.clone() - } + /// Returns challenge of `lookup_input`. + pub fn lookup_input(&self) -> T { + self.lookup_input.clone() + } /// Returns the challenges indexed by the challenge index - pub fn indexed(&self ) -> [&T;3] { + pub fn indexed(&self) -> [&T; 3] { [&self.evm_word, &self.keccak_input, &self.lookup_input] - } + } pub(crate) fn mock(evm_word: T, keccak_input: T, lookup_input: T) -> Self { Self { evm_word, keccak_input, - lookup_input + lookup_input, } } } impl Challenges> { - /// Returns powers of randomness for word RLC encoding - pub fn evm_word_powers_of_randomness(&self) -> [Expression; S] { - std::iter::successors(self.evm_word.clone().into(), |power| { - (self.evm_word.clone() * power.clone()).into() + /// Returns powers of randomness + fn powers_of(base: Expression) -> [Expression; S] { + std::iter::successors(base.clone().into(), |power| { + (base.clone() * power.clone()).into() }) .take(S) .collect::>() @@ -130,17 +137,15 @@ impl Challenges> { .unwrap() } + /// Returns powers of randomness for word RLC encoding + pub fn evm_word_powers_of_randomness(&self) -> [Expression; S] { + Self::powers_of(self.evm_word.clone()) + } + /// Returns powers of randomness for lookups pub fn lookup_input_powers_of_randomness(&self) -> [Expression; S] { - std::iter::successors(self.lookup_input.clone().into(), |power| { - (self.lookup_input.clone() * power.clone()).into() - }) - .take(S) - .collect::>() - .try_into() - .unwrap() + Self::powers_of(self.lookup_input.clone()) } - } pub(crate) fn build_tx_log_address(index: u64, field_tag: TxLogFieldTag, log_id: u64) -> Address { From c9dd231f65301e175ecea0d310397e3072ed22c3 Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 2 Jan 2023 14:34:38 +0100 Subject: [PATCH 06/18] revert fast id, split_expression phase fix --- zkevm-circuits/src/evm_circuit/util.rs | 4 ++-- zkevm-circuits/src/evm_circuit/util/constraint_builder.rs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/util.rs b/zkevm-circuits/src/evm_circuit/util.rs index c32ebb81b6..49f7990907 100644 --- a/zkevm-circuits/src/evm_circuit/util.rs +++ b/zkevm-circuits/src/evm_circuit/util.rs @@ -169,7 +169,7 @@ pub struct StoredExpression { cell: Cell, cell_type: CellType, expr: Expression, - expr_id: Vec, + expr_id: String, } use std::hash::{Hash, Hasher}; @@ -246,7 +246,7 @@ impl CellType { } } - /// Return the phase of the expression + /// Return the phase for the inverse of an the expression pub(crate) fn storage_for_inv(value: &Expression) -> CellType { match Self::expr_phase(value) { 0 => CellType::StoragePhase1, diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index ebdd7bd3c9..d4c802054e 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -1444,7 +1444,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { name, cell: cell.clone(), cell_type, - expr_id: expr.fast_identifier(), + expr_id: expr.identifier(), expr, }); cell.expr() @@ -1457,7 +1457,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { expr: &Expression, cell_type: CellType, ) -> Option<&StoredExpression> { - let expr_id = expr.fast_identifier(); + let expr_id = expr.identifier(); self.stored_expressions .iter() .find(|&e| e.cell_type == cell_type && e.expr_id == expr_id) @@ -1489,7 +1489,8 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { if expr.degree() > max_degree { self.split_expression(name, expr, max_degree) } else { - self.store_expression(name, expr, CellType::StoragePhase1) + let cell_type = CellType::storage_for(&expr); + self.store_expression(name, expr, cell_type) } }; if a.degree() >= b.degree() { From d41b85c1f044da04878ba0e6c4c375d39347e0d6 Mon Sep 17 00:00:00 2001 From: adria0 Date: Tue, 3 Jan 2023 10:49:21 +0100 Subject: [PATCH 07/18] limit 12 pows in lookup_powers_of_randomness --- zkevm-circuits/src/evm_circuit/execution.rs | 6 +++--- zkevm-circuits/src/evm_circuit/util/constraint_builder.rs | 4 ++-- .../src/evm_circuit/util/math_gadget/test_util.rs | 5 ++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 57089cee32..70d0cedbd5 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -414,9 +414,9 @@ impl ExecutionConfig { let mut stored_expressions_map = HashMap::new(); let step_next = Step::new(meta, advices, MAX_STEP_HEIGHT, true); - let word_powers_of_randomness: [Expression; 31] = + let word_powers_of_randomness = challenges.evm_word_powers_of_randomness(); - let lookup_powers_of_randomness: [Expression; 31] = + let lookup_powers_of_randomness = challenges.lookup_input_powers_of_randomness(); macro_rules! configure_gadget { () => { @@ -584,7 +584,7 @@ impl ExecutionConfig { q_step_last: Selector, challenges: &Challenges>, word_powers_of_randomness: &[Expression; 31], - lookup_powers_of_randomness: &[Expression; 31], + lookup_powers_of_randomness: &[Expression; 12], step_curr: &Step, step_next: &Step, height_map: &mut HashMap, diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index 44764c267a..ede00f3a9c 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -266,7 +266,7 @@ pub(crate) struct ConstraintBuilder<'a, F> { pub(crate) next: Step, challenges: &'a Challenges>, word_powers_of_randomness: &'a [Expression; 31], - lookup_powers_of_randomness: &'a [Expression; 31], + lookup_powers_of_randomness: &'a [Expression; 12], execution_state: ExecutionState, constraints: Constraints, rw_counter_offset: Expression, @@ -285,7 +285,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { next: Step, challenges: &'a Challenges>, word_powers_of_randomness: &'a [Expression; 31], - lookup_powers_of_randomness: &'a [Expression; 31], + lookup_powers_of_randomness: &'a [Expression; 12], execution_state: ExecutionState, ) -> Self { Self { diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/test_util.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/test_util.rs index 64fca8ba01..75f7b2ffb9 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/test_util.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/test_util.rs @@ -93,9 +93,8 @@ impl> Circuit for UnitTestMathGadgetBaseC let step_next = Step::new(meta, advices, MAX_STEP_HEIGHT, true); let challenges = Challenges::construct(meta); let challenges_exprs = challenges.exprs(meta); - let - evm_word_powers_of_randomness: [_;31] = challenges_exprs.evm_word_powers_of_randomness(); - let lookup_input_powers_of_randomness: [_;31]= challenges_exprs.lookup_input_powers_of_randomness(); + let evm_word_powers_of_randomness = challenges_exprs.evm_word_powers_of_randomness(); + let lookup_input_powers_of_randomness = challenges_exprs.lookup_input_powers_of_randomness(); let mut cb = ConstraintBuilder::new( step_curr.clone(), step_next, From 5ba2cf199415c57356e03c0e3875a0a2ad1bdd44 Mon Sep 17 00:00:00 2001 From: adria0 Date: Tue, 3 Jan 2023 11:31:35 +0100 Subject: [PATCH 08/18] EVM lookup columns in phase3 --- zkevm-circuits/src/evm_circuit/execution.rs | 9 ++++++--- zkevm-circuits/src/evm_circuit/util.rs | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 70d0cedbd5..b7b74c7506 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -1,7 +1,7 @@ use super::util::{CachedRegion, CellManager, StoredExpression}; use crate::{ evm_circuit::{ - param::{MAX_STEP_HEIGHT, N_PHASE2_COLUMNS, N_PHASE3_COLUMNS, STEP_WIDTH}, + param::{MAX_STEP_HEIGHT, N_PHASE2_COLUMNS, N_PHASE3_COLUMNS, STEP_WIDTH, LOOKUP_CONFIG}, step::{ExecutionState, Step}, table::Table, util::{ @@ -311,13 +311,16 @@ impl ExecutionConfig { let num_rows_inv = meta.advice_column(); let q_step_first = meta.complex_selector(); let q_step_last = meta.complex_selector(); + + let lookup_column_count: usize = LOOKUP_CONFIG.iter().map(|(_,count)| *count).sum(); + let advices = [(); STEP_WIDTH] .iter() .enumerate() .map(|(n, _)| { - if n < N_PHASE3_COLUMNS { + if n < N_PHASE3_COLUMNS + lookup_column_count { meta.advice_column_in(ThirdPhase) - } else if n < N_PHASE3_COLUMNS + N_PHASE2_COLUMNS { + } else if n < N_PHASE3_COLUMNS + lookup_column_count + N_PHASE2_COLUMNS { meta.advice_column_in(SecondPhase) } else { meta.advice_column_in(FirstPhase) diff --git a/zkevm-circuits/src/evm_circuit/util.rs b/zkevm-circuits/src/evm_circuit/util.rs index 49f7990907..db1707869e 100644 --- a/zkevm-circuits/src/evm_circuit/util.rs +++ b/zkevm-circuits/src/evm_circuit/util.rs @@ -221,8 +221,7 @@ pub(crate) enum CellType { StoragePhase2, StoragePhase3, StoragePermutation, - Lookup(Table), - LookupPhase3(Table), + Lookup(Table) } impl CellType { @@ -311,20 +310,21 @@ impl CellManager { column_idx += 1; } - // Mark columns used for Phase2 constraints - for _ in 0..N_PHASE2_COLUMNS { - columns[column_idx].cell_type = CellType::StoragePhase2; - column_idx += 1; - } - - // Mark columns used for lookups + // Mark columns used for lookups in Phase3 for &(table, count) in LOOKUP_CONFIG { for _ in 0usize..count { columns[column_idx].cell_type = CellType::Lookup(table); column_idx += 1; } } - // Mark columns used for copy constraints + + // Mark columns used for Phase2 constraints + for _ in 0..N_PHASE2_COLUMNS { + columns[column_idx].cell_type = CellType::StoragePhase2; + column_idx += 1; + } + + // Mark columns used for copy constraints for _ in 0..N_COPY_COLUMNS { meta.enable_equality(advices[column_idx]); columns[column_idx].cell_type = CellType::StoragePermutation; From f23089a1b2900744a4b8ee510dca3ec2cd0c1d0c Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 9 Jan 2023 15:11:08 +0100 Subject: [PATCH 09/18] Extract Value contents to order instead ordering by Value --- zkevm-circuits/src/evm_circuit/execution.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index b7b74c7506..ff4007517c 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -1,7 +1,7 @@ use super::util::{CachedRegion, CellManager, StoredExpression}; use crate::{ evm_circuit::{ - param::{MAX_STEP_HEIGHT, N_PHASE2_COLUMNS, N_PHASE3_COLUMNS, STEP_WIDTH, LOOKUP_CONFIG}, + param::{LOOKUP_CONFIG, MAX_STEP_HEIGHT, N_PHASE2_COLUMNS, N_PHASE3_COLUMNS, STEP_WIDTH}, step::{ExecutionState, Step}, table::Table, util::{ @@ -312,8 +312,8 @@ impl ExecutionConfig { let q_step_first = meta.complex_selector(); let q_step_last = meta.complex_selector(); - let lookup_column_count: usize = LOOKUP_CONFIG.iter().map(|(_,count)| *count).sum(); - + let lookup_column_count: usize = LOOKUP_CONFIG.iter().map(|(_, count)| *count).sum(); + let advices = [(); STEP_WIDTH] .iter() .enumerate() @@ -417,10 +417,8 @@ impl ExecutionConfig { let mut stored_expressions_map = HashMap::new(); let step_next = Step::new(meta, advices, MAX_STEP_HEIGHT, true); - let word_powers_of_randomness = - challenges.evm_word_powers_of_randomness(); - let lookup_powers_of_randomness = - challenges.lookup_input_powers_of_randomness(); + let word_powers_of_randomness = challenges.evm_word_powers_of_randomness(); + let lookup_powers_of_randomness = challenges.lookup_input_powers_of_randomness(); macro_rules! configure_gadget { () => { Self::configure_gadget( @@ -1220,11 +1218,14 @@ impl ExecutionConfig { .evm_word() .map(|randomness| rw.table_assignment_aux(randomness).rlc(randomness)) }) - .collect(); + .fold(BTreeSet::::new(), |mut set, value| { + value.map(|value| set.insert(value)); + set + }); // [TODO] Check this for (name, value) in assigned_rw_values.iter() { - if !rlc_assignments.contains(&Value::known(*value)) { + if !rlc_assignments.contains(value) { log::error!("rw lookup error: name: {}, step: {:?}", *name, step); } } From 8aa678d26f65fb2a5ddb84c2d33b0f78ec135a81 Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 9 Jan 2023 16:14:04 +0100 Subject: [PATCH 10/18] Removed leftovers & misspells --- zkevm-circuits/src/evm_circuit/execution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index ff4007517c..2638b9fda3 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -592,7 +592,7 @@ impl ExecutionConfig { stored_expressions_map: &mut HashMap>>, ) -> G { // Configure the gadget with the max height first so we can find out the actual - // heightn + // height let height = { let mut cb = ConstraintBuilder::new( step_curr.clone(), From 3ded7074c0e5b904718f2159e9092a87fa4c4bb5 Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 9 Jan 2023 17:20:22 +0100 Subject: [PATCH 11/18] Move Value::transpose from halo2 to this crate --- zkevm-circuits/src/evm_circuit/util.rs | 9 +++++++++ .../src/evm_circuit/util/math_gadget/batched_is_zero.rs | 7 +++---- .../evm_circuit/util/math_gadget/constant_division.rs | 6 +++--- .../src/evm_circuit/util/math_gadget/is_equal.rs | 7 +++---- .../src/evm_circuit/util/math_gadget/is_zero.rs | 7 +++---- zkevm-circuits/src/evm_circuit/util/math_gadget/lt.rs | 7 +++---- .../src/evm_circuit/util/math_gadget/min_max.rs | 7 +++---- 7 files changed, 27 insertions(+), 23 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/util.rs b/zkevm-circuits/src/evm_circuit/util.rs index db1707869e..b347cc9991 100644 --- a/zkevm-circuits/src/evm_circuit/util.rs +++ b/zkevm-circuits/src/evm_circuit/util.rs @@ -556,3 +556,12 @@ pub(crate) fn split_u256_limb64(value: &U256) -> [U256; 4] { U256([value.0[3], 0, 0, 0]), ] } + +/// Transposes an `Value` of a [`Result`] into a [`Result`] of an `Value`. +pub(crate) fn transpose_val_ret(value: Value>) -> Result,E> { + let mut ret= Ok(Value::unknown()); + value.map(|value| { + ret = value.map(Value::known); + }); + ret +} diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs index a761c95688..500480454d 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs @@ -1,5 +1,5 @@ use crate::{ - evm_circuit::util::{constraint_builder::ConstraintBuilder, CachedRegion, Cell, CellType}, + evm_circuit::util::{constraint_builder::ConstraintBuilder, CachedRegion, Cell, CellType, transpose_val_ret}, util::Expr, }; use eth_types::Field; @@ -78,9 +78,8 @@ impl BatchedIsZeroGadget { ) -> Result, Error> { let values: Value<[F; N]> = Value::>::from_iter(values).map(|vv| vv.try_into().unwrap()); - values - .map(|values| self.assign(region, offset, values)) - .transpose() + transpose_val_ret(values + .map(|values| self.assign(region, offset, values))) } } diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs index dcfee232d0..15f7b8d085 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs @@ -1,6 +1,6 @@ use crate::{ evm_circuit::util::{ - constraint_builder::ConstraintBuilder, math_gadget::*, CachedRegion, Cell, CellType, + constraint_builder::ConstraintBuilder, math_gadget::*, CachedRegion, Cell, CellType, transpose_val_ret }, util::Expr, }; @@ -89,9 +89,9 @@ impl ConstantDivisionGadget { offset: usize, numerator: Value, ) -> Result, Error> { - numerator + transpose_val_ret(numerator .map(|numerator| self.assign(region, offset, numerator.get_lower_128())) - .transpose() + ) } } diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/is_equal.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/is_equal.rs index 6a12a41999..896e42cb4f 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/is_equal.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/is_equal.rs @@ -1,6 +1,6 @@ use crate::evm_circuit::{ util::constraint_builder::ConstraintBuilder, - util::{math_gadget::*, CachedRegion}, + util::{math_gadget::*, CachedRegion, transpose_val_ret}, }; use eth_types::Field; use halo2_proofs::{plonk::{Error, Expression}, circuit::Value}; @@ -43,9 +43,8 @@ impl IsEqualGadget { lhs: Value, rhs: Value, ) -> Result, Error> { - lhs.zip(rhs) - .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs)) - .transpose() + transpose_val_ret(lhs.zip(rhs) + .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs))) } } diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs index a13ab34d68..f9bf138dc6 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs @@ -1,5 +1,5 @@ use crate::{ - evm_circuit::util::{constraint_builder::ConstraintBuilder, CachedRegion, Cell, CellType}, + evm_circuit::util::{constraint_builder::ConstraintBuilder, CachedRegion, Cell, CellType, transpose_val_ret}, util::Expr, }; use eth_types::Field; @@ -58,9 +58,8 @@ impl IsZeroGadget { offset: usize, value: Value, ) -> Result, Error> { - value - .map(|value| self.assign(region, offset, value)) - .transpose() + transpose_val_ret(value + .map(|value| self.assign(region, offset, value))) } } diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/lt.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/lt.rs index b5dce52cb0..90c18bd6c3 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/lt.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/lt.rs @@ -1,6 +1,6 @@ use crate::{ evm_circuit::util::{ - constraint_builder::ConstraintBuilder, from_bytes, pow_of_two, CachedRegion, Cell, + constraint_builder::ConstraintBuilder, from_bytes, pow_of_two, CachedRegion, Cell,transpose_val_ret }, util::Expr, }; @@ -91,9 +91,8 @@ impl LtGadget { lhs: Value, rhs: Value, ) -> Result)>, Error> { - lhs.zip(rhs) - .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs)) - .transpose() + transpose_val_ret(lhs.zip(rhs) + .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs))) } } diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/min_max.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/min_max.rs index 26709bfad0..0e4010e155 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/min_max.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/min_max.rs @@ -1,5 +1,5 @@ use crate::evm_circuit::util::{ - constraint_builder::ConstraintBuilder, math_gadget::*, select, CachedRegion, + constraint_builder::ConstraintBuilder, math_gadget::*, select, CachedRegion, transpose_val_ret }; use eth_types::Field; use halo2_proofs::{plonk::{Error, Expression}, circuit::Value}; @@ -56,9 +56,8 @@ impl MinMaxGadget { lhs: Value, rhs: Value, ) -> Result, Error> { - lhs.zip(rhs) - .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs)) - .transpose() + transpose_val_ret(lhs.zip(rhs) + .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs))) } } From 8bfda72c435b7469fbbe15949a99b058e73351af Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 9 Jan 2023 19:06:34 +0100 Subject: [PATCH 12/18] Fix phases in is_zero gagets --- zkevm-circuits/src/evm_circuit/param.rs | 2 +- zkevm-circuits/src/evm_circuit/util.rs | 2 +- .../util/math_gadget/batched_is_zero.rs | 16 ++++++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/param.rs b/zkevm-circuits/src/evm_circuit/param.rs index cf12b26b1f..469efcde32 100644 --- a/zkevm-circuits/src/evm_circuit/param.rs +++ b/zkevm-circuits/src/evm_circuit/param.rs @@ -11,7 +11,7 @@ pub(crate) const STEP_STATE_HEIGHT: usize = 1; pub(crate) const N_CELLS_STEP_STATE: usize = 11; // Number of phase2 columns -pub(crate) const N_PHASE2_COLUMNS: usize = 2; +pub(crate) const N_PHASE2_COLUMNS: usize = 3; // Number of phase3 columns pub(crate) const N_PHASE3_COLUMNS: usize = 1; diff --git a/zkevm-circuits/src/evm_circuit/util.rs b/zkevm-circuits/src/evm_circuit/util.rs index b347cc9991..cb28806d6c 100644 --- a/zkevm-circuits/src/evm_circuit/util.rs +++ b/zkevm-circuits/src/evm_circuit/util.rs @@ -248,7 +248,7 @@ impl CellType { /// Return the phase for the inverse of an the expression pub(crate) fn storage_for_inv(value: &Expression) -> CellType { match Self::expr_phase(value) { - 0 => CellType::StoragePhase1, + 0 => CellType::StoragePhase2, 1 => CellType::StoragePhase3, 2 => unimplemented!(), _ => unreachable!(), diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs index 500480454d..5f831b5b76 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs @@ -16,14 +16,18 @@ pub struct BatchedIsZeroGadget { impl BatchedIsZeroGadget { pub(crate) fn construct(cb: &mut ConstraintBuilder, values: [Expression; N]) -> Self { - let values_in_phase_1 = values + let max_values_phase= values .iter() - .any(|value| CellType::storage_for(value) == CellType::StoragePhase1); - let in_phase = if values_in_phase_1 { - CellType::StoragePhase2 - } else { - CellType::StoragePhase1 + .map(CellType::expr_phase) + .max() + .expect("BatchedIsZeroGadget needs at least one expression"); + + let in_phase = match max_values_phase { + 0 => CellType::StoragePhase2, + 1 => CellType::StoragePhase3, + _ => unimplemented!() }; + let is_zero = cb.query_bool_with_type(in_phase); let nonempty_witness = cb.query_cell_with_type(in_phase); From c755ee266c16dfc878887c3a1eb3990f27ba76ca Mon Sep 17 00:00:00 2001 From: adria0 Date: Tue, 10 Jan 2023 10:36:13 +0100 Subject: [PATCH 13/18] Revert: use halo2 from git --- Cargo.lock | 6 ++++++ Cargo.toml | 2 +- bus-mapping/Cargo.toml | 2 +- circuit-benchmarks/Cargo.toml | 2 +- eth-types/Cargo.toml | 2 +- gadgets/Cargo.toml | 2 +- integration-tests/Cargo.toml | 2 +- testool/Cargo.toml | 2 +- zkevm-circuits/Cargo.toml | 10 +++++----- 9 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db5a7fc75a..0959925470 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1166,6 +1166,7 @@ dependencies = [ [[package]] name = "ecc" version = "0.1.0" +source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2022_09_09#2d708b4453387f03059aad68d6d87441db112a2f" dependencies = [ "group", "integer", @@ -1179,6 +1180,7 @@ dependencies = [ [[package]] name = "ecdsa" version = "0.1.0" +source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2022_09_09#2d708b4453387f03059aad68d6d87441db112a2f" dependencies = [ "ecc", "group", @@ -1983,6 +1985,7 @@ dependencies = [ [[package]] name = "halo2_proofs" version = "0.2.0" +source = "git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2022_09_10#a9e99a72a65d7c98e8a4258c2c94269c834d1c10" dependencies = [ "blake2b_simd", "ff", @@ -2013,6 +2016,7 @@ dependencies = [ [[package]] name = "halo2wrong" version = "0.1.0" +source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2022_09_09#2d708b4453387f03059aad68d6d87441db112a2f" dependencies = [ "group", "halo2_proofs 0.2.0", @@ -2317,6 +2321,7 @@ dependencies = [ [[package]] name = "integer" version = "0.1.0" +source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2022_09_09#2d708b4453387f03059aad68d6d87441db112a2f" dependencies = [ "group", "maingate", @@ -2571,6 +2576,7 @@ dependencies = [ [[package]] name = "maingate" version = "0.1.0" +source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2022_09_09#2d708b4453387f03059aad68d6d87441db112a2f" dependencies = [ "group", "halo2wrong", diff --git a/Cargo.toml b/Cargo.toml index d28a358ecb..830e7f7119 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ members = [ ] [patch.crates-io] -halo2_proofs = { path = "../halo2/halo2_proofs" } +halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } # Definition of benchmarks profile to use. [profile.bench] diff --git a/bus-mapping/Cargo.toml b/bus-mapping/Cargo.toml index eb74761172..740ce57505 100644 --- a/bus-mapping/Cargo.toml +++ b/bus-mapping/Cargo.toml @@ -13,7 +13,7 @@ mock = { path = "../mock", optional = true } ethers-core = "0.17.0" ethers-providers = "0.17.0" -halo2_proofs = { path = "../../halo2/halo2_proofs" } +halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } itertools = "0.10" lazy_static = "1.4" log = "0.4.14" diff --git a/circuit-benchmarks/Cargo.toml b/circuit-benchmarks/Cargo.toml index f02b6e7da6..f81a7c4a18 100644 --- a/circuit-benchmarks/Cargo.toml +++ b/circuit-benchmarks/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -halo2_proofs = { path = "../../halo2/halo2_proofs" } +halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } ark-std = { version = "0.3", features = ["print-trace"] } zkevm-circuits = { path = "../zkevm-circuits", features = ["test"]} keccak256 = { path = "../keccak256" } diff --git a/eth-types/Cargo.toml b/eth-types/Cargo.toml index ca6905d30d..56a5abf922 100644 --- a/eth-types/Cargo.toml +++ b/eth-types/Cargo.toml @@ -10,7 +10,7 @@ ethers-core = "0.17.0" ethers-signers = "0.17.0" hex = "0.4" lazy_static = "1.4" -halo2_proofs = { path = "../../halo2/halo2_proofs" } +halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } regex = "1.5.4" serde = {version = "1.0.130", features = ["derive"] } serde_json = "1.0.66" diff --git a/gadgets/Cargo.toml b/gadgets/Cargo.toml index ea844fa2c7..3e72f464c5 100644 --- a/gadgets/Cargo.toml +++ b/gadgets/Cargo.toml @@ -6,7 +6,7 @@ authors = ["The appliedzkp team"] license = "MIT OR Apache-2.0" [dependencies] -halo2_proofs = { path = "../../halo2/halo2_proofs" } +halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } sha3 = "0.7.2" eth-types = { path = "../eth-types" } digest = "0.7.6" diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 720fcea40d..0d602d0575 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -19,7 +19,7 @@ url = "2.2.2" pretty_assertions = "1.0.0" log = "0.4.14" env_logger = "0.9" -halo2_proofs = { path = "../../halo2/halo2_proofs" } +halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } rand_chacha = "0.3" paste = "1.0" rand_xorshift = "0.3.0" diff --git a/testool/Cargo.toml b/testool/Cargo.toml index 5dff220027..dccaad037d 100644 --- a/testool/Cargo.toml +++ b/testool/Cargo.toml @@ -33,7 +33,7 @@ yaml-rust = "0.4.5" zkevm-circuits = { path="../zkevm-circuits", features=["test"] } rand_chacha = "0.3" rand = "0.8" -halo2_proofs = { path = "../../halo2/halo2_proofs" } +halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } [features] diff --git a/zkevm-circuits/Cargo.toml b/zkevm-circuits/Cargo.toml index be426b6d8b..c56005a6d5 100644 --- a/zkevm-circuits/Cargo.toml +++ b/zkevm-circuits/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -halo2_proofs = { path = "../../halo2/halo2_proofs" } +halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } num = "0.4" sha3 = "0.10" array-init = "2.0.0" @@ -27,10 +27,10 @@ lazy_static = "1.4" keccak256 = { path = "../keccak256"} log = "0.4" env_logger = "0.9" -ecdsa = { path = "../../halo2wrong/ecdsa" } -ecc = { path = "../../halo2wrong/ecc" } -maingate = { path = "../../halo2wrong/maingate" } -integer = { path = "../../halo2wrong/integer" } +ecdsa = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2022_09_09" } +ecc = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2022_09_09" } +maingate = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2022_09_09" } +integer = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2022_09_09" } libsecp256k1 = "0.7" num-bigint = { version = "0.4" } subtle = "2.4" From 61710e8bf5b106f085b0c6f9fdc2b920d493e3e1 Mon Sep 17 00:00:00 2001 From: adria0 Date: Wed, 11 Jan 2023 11:09:53 +0100 Subject: [PATCH 14/18] Fix phase computation for inv --- zkevm-circuits/src/evm_circuit/param.rs | 2 +- zkevm-circuits/src/evm_circuit/util.rs | 22 ++++++++----------- .../evm_circuit/util/constraint_builder.rs | 2 +- .../util/math_gadget/batched_is_zero.rs | 13 ++++------- .../util/math_gadget/constant_division.rs | 4 ++-- .../evm_circuit/util/math_gadget/is_zero.rs | 2 +- 6 files changed, 18 insertions(+), 27 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/param.rs b/zkevm-circuits/src/evm_circuit/param.rs index 469efcde32..cf12b26b1f 100644 --- a/zkevm-circuits/src/evm_circuit/param.rs +++ b/zkevm-circuits/src/evm_circuit/param.rs @@ -11,7 +11,7 @@ pub(crate) const STEP_STATE_HEIGHT: usize = 1; pub(crate) const N_CELLS_STEP_STATE: usize = 11; // Number of phase2 columns -pub(crate) const N_PHASE2_COLUMNS: usize = 3; +pub(crate) const N_PHASE2_COLUMNS: usize = 2; // Number of phase3 columns pub(crate) const N_PHASE3_COLUMNS: usize = 1; diff --git a/zkevm-circuits/src/evm_circuit/util.rs b/zkevm-circuits/src/evm_circuit/util.rs index 7f420714e8..e9a03ebba1 100644 --- a/zkevm-circuits/src/evm_circuit/util.rs +++ b/zkevm-circuits/src/evm_circuit/util.rs @@ -260,9 +260,9 @@ pub(crate) enum CellType { } impl CellType { - fn expr_phase(value: &Expression) -> u8 { + fn expr_phase(expr: &Expression) -> u8 { use Expression::*; - match value { + match expr { Challenge(challenge) => challenge.phase() + 1, Constant(_) | Selector(_) | Fixed(_) | Advice(_) | Instance(_) => 0, Negated(a) | Expression::Scaled(a, _) => Self::expr_phase(a), @@ -270,9 +270,9 @@ impl CellType { } } - /// Return the phase of the expression - pub(crate) fn storage_for(value: &Expression) -> CellType { - match Self::expr_phase(value) { + /// Return the storage phase of phase + pub(crate) fn storage_for_phase(phase: u8) -> CellType { + match phase { 0 => CellType::StoragePhase1, 1 => CellType::StoragePhase2, 2 => CellType::StoragePhase3, @@ -280,15 +280,11 @@ impl CellType { } } - /// Return the phase for the inverse of an the expression - pub(crate) fn storage_for_inv(value: &Expression) -> CellType { - match Self::expr_phase(value) { - 0 => CellType::StoragePhase2, - 1 => CellType::StoragePhase3, - 2 => unimplemented!(), - _ => unreachable!(), - } + /// Return the storage cell of the expression + pub(crate) fn storage_for_expr(expr: &Expression) -> CellType { + Self::storage_for_phase::(Self::expr_phase::(expr)) } + } #[derive(Clone, Debug)] diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index ede00f3a9c..bd4d299fc2 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -1515,7 +1515,7 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { if expr.degree() > max_degree { self.split_expression(name, expr, max_degree) } else { - let cell_type = CellType::storage_for(&expr); + let cell_type = CellType::storage_for_expr(&expr); self.store_expression(name, expr, cell_type) } }; diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs index 5f831b5b76..6ebc4b54e3 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs @@ -21,15 +21,10 @@ impl BatchedIsZeroGadget { .map(CellType::expr_phase) .max() .expect("BatchedIsZeroGadget needs at least one expression"); - - let in_phase = match max_values_phase { - 0 => CellType::StoragePhase2, - 1 => CellType::StoragePhase3, - _ => unimplemented!() - }; - - let is_zero = cb.query_bool_with_type(in_phase); - let nonempty_witness = cb.query_cell_with_type(in_phase); + + let cell_type = CellType::storage_for_phase::(max_values_phase); + let is_zero = cb.query_bool_with_type(cell_type); + let nonempty_witness = cb.query_cell_with_type(cell_type); for value in values.iter() { cb.require_zero( diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs index 15f7b8d085..41a1db6c66 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs @@ -29,8 +29,8 @@ impl ConstantDivisionGadget { numerator: Expression, denominator: u64, ) -> Self { - let quotient = cb.query_cell_with_type(CellType::storage_for(&numerator)); - let remainder = cb.query_cell_with_type(CellType::storage_for(&numerator)); + let quotient = cb.query_cell_with_type(CellType::storage_for_expr(&numerator)); + let remainder = cb.query_cell_with_type(CellType::storage_for_expr(&numerator)); // Require that remainder < denominator cb.range_lookup(remainder.expr(), denominator); diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs index f9bf138dc6..cf2a2701bb 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs @@ -17,7 +17,7 @@ pub struct IsZeroGadget { impl IsZeroGadget { pub(crate) fn construct(cb: &mut ConstraintBuilder, value: Expression) -> Self { - let inverse = cb.query_cell_with_type(CellType::storage_for_inv(&value)); + let inverse = cb.query_cell_with_type(CellType::storage_for_expr(&value)); let is_zero = 1.expr() - (value.clone() * inverse.expr()); // when `value != 0` check `inverse = a.invert()`: value * (1 - value * From 248969b32025ee6cca3bf8b49bbfcac1d34e83ec Mon Sep 17 00:00:00 2001 From: adria0 Date: Wed, 11 Jan 2023 11:10:34 +0100 Subject: [PATCH 15/18] fmt --- zkevm-circuits/src/evm_circuit.rs | 1 - zkevm-circuits/src/evm_circuit/execution.rs | 7 ++- .../src/evm_circuit/execution/balance.rs | 11 ++--- .../src/evm_circuit/execution/callop.rs | 18 ++----- .../src/evm_circuit/execution/extcodesize.rs | 11 ++--- .../src/evm_circuit/execution/mulmod.rs | 3 +- zkevm-circuits/src/evm_circuit/util.rs | 15 +++--- .../util/math_gadget/batched_is_zero.rs | 27 ++++++----- .../util/math_gadget/constant_division.rs | 9 ++-- .../evm_circuit/util/math_gadget/is_equal.rs | 14 ++++-- .../evm_circuit/util/math_gadget/is_zero.rs | 7 +-- .../src/evm_circuit/util/math_gadget/lt.rs | 10 ++-- .../evm_circuit/util/math_gadget/lt_word.rs | 1 - .../evm_circuit/util/math_gadget/min_max.rs | 15 ++++-- .../evm_circuit/util/math_gadget/modulo.rs | 2 +- .../evm_circuit/util/math_gadget/test_util.rs | 48 +++++++++++-------- zkevm-circuits/src/util.rs | 4 +- 17 files changed, 104 insertions(+), 99 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit.rs b/zkevm-circuits/src/evm_circuit.rs index ed79ad6655..1809aefcc2 100644 --- a/zkevm-circuits/src/evm_circuit.rs +++ b/zkevm-circuits/src/evm_circuit.rs @@ -491,7 +491,6 @@ pub mod test { let prover = MockProver::::run(k, &circuit, vec![]).unwrap(); prover.verify_at_rows_par(active_gate_rows.into_iter(), active_lookup_rows.into_iter()) } - } #[cfg(test)] diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 74df96db80..05f5d53afc 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -1227,7 +1227,12 @@ impl ExecutionConfig { // enable with `RUST_LOG=debug` if log::log_enabled!(log::Level::Debug) { // expensive function call - Self::check_rw_lookup(&assigned_stored_expressions, step, block, region.challenges()); + Self::check_rw_lookup( + &assigned_stored_expressions, + step, + block, + region.challenges(), + ); } Ok(()) } diff --git a/zkevm-circuits/src/evm_circuit/execution/balance.rs b/zkevm-circuits/src/evm_circuit/execution/balance.rs index 88b53ad543..fe72f66c08 100644 --- a/zkevm-circuits/src/evm_circuit/execution/balance.rs +++ b/zkevm-circuits/src/evm_circuit/execution/balance.rs @@ -6,9 +6,7 @@ use crate::evm_circuit::util::constraint_builder::Transition::Delta; use crate::evm_circuit::util::constraint_builder::{ ConstraintBuilder, ReversionInfo, StepStateTransition, }; -use crate::evm_circuit::util::{ - from_bytes, select, CachedRegion, Cell, Word, -}; +use crate::evm_circuit::util::{from_bytes, select, CachedRegion, Cell, Word}; use crate::evm_circuit::witness::{Block, Call, ExecStep, Rw, Transaction}; use crate::table::{AccountFieldTag, CallContextFieldTag}; use crate::util::Expr; @@ -130,11 +128,8 @@ impl ExecutionGadget for BalanceGadget { } => (0.into(), false), _ => unreachable!(), }; - self.balance.assign( - region, - offset, - region.word_rlc(balance) - )?; + self.balance + .assign(region, offset, region.word_rlc(balance))?; self.exists .assign(region, offset, Value::known(F::from(exists)))?; diff --git a/zkevm-circuits/src/evm_circuit/execution/callop.rs b/zkevm-circuits/src/evm_circuit/execution/callop.rs index d2ab6ce67d..2b1ef57213 100644 --- a/zkevm-circuits/src/evm_circuit/execution/callop.rs +++ b/zkevm-circuits/src/evm_circuit/execution/callop.rs @@ -10,9 +10,7 @@ use crate::evm_circuit::util::math_gadget::{ CmpWordsGadget, ConstantDivisionGadget, IsEqualGadget, IsZeroGadget, MinMaxGadget, }; use crate::evm_circuit::util::memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}; -use crate::evm_circuit::util::{ - from_bytes, or, select, sum, CachedRegion, Cell, Word, CellType, -}; +use crate::evm_circuit::util::{from_bytes, or, select, sum, CachedRegion, Cell, CellType, Word}; use crate::evm_circuit::witness::{Block, Call, ExecStep, Rw, Transaction}; use crate::table::{AccountFieldTag, CallContextFieldTag}; use crate::util::Expr; @@ -366,10 +364,7 @@ impl ExecutionGadget for CallOpGadget { (CallContextFieldTag::LastCalleeReturnDataLength, 0.expr()), (CallContextFieldTag::IsRoot, 0.expr()), (CallContextFieldTag::IsCreate, 0.expr()), - ( - CallContextFieldTag::CodeHash, - callee_code_hash.expr(), - ), + (CallContextFieldTag::CodeHash, callee_code_hash.expr()), ] { cb.call_context_lookup(true.expr(), Some(callee_call_id.expr()), field_tag, value); } @@ -524,7 +519,7 @@ impl ExecutionGadget for CallOpGadget { _ => unreachable!(), }; let callee_code_hash = region.word_rlc(U256::from_little_endian(&callee_code_hash)); - + self.opcode .assign(region, offset, Value::known(F::from(opcode.as_u64())))?; self.is_call.assign( @@ -651,11 +646,8 @@ impl ExecutionGadget for CallOpGadget { 0 } + memory_expansion_gas_cost; let gas_available = step.gas_left - gas_cost; - self.one_64th_gas.assign( - region, - offset, - gas_available.into(), - )?; + self.one_64th_gas + .assign(region, offset, gas_available.into())?; self.capped_callee_gas_left.assign( region, offset, diff --git a/zkevm-circuits/src/evm_circuit/execution/extcodesize.rs b/zkevm-circuits/src/evm_circuit/execution/extcodesize.rs index 8553adb094..39a503d7c2 100644 --- a/zkevm-circuits/src/evm_circuit/execution/extcodesize.rs +++ b/zkevm-circuits/src/evm_circuit/execution/extcodesize.rs @@ -6,9 +6,7 @@ use crate::evm_circuit::util::constraint_builder::Transition::Delta; use crate::evm_circuit::util::constraint_builder::{ ConstraintBuilder, ReversionInfo, StepStateTransition, }; -use crate::evm_circuit::util::{ - from_bytes, select, CachedRegion, Cell, Word, -}; +use crate::evm_circuit::util::{from_bytes, select, CachedRegion, Cell, Word}; use crate::evm_circuit::witness::{Block, Call, ExecStep, Rw, Transaction}; use crate::table::{AccountFieldTag, CallContextFieldTag}; use crate::util::Expr; @@ -151,11 +149,8 @@ impl ExecutionGadget for ExtcodesizeGadget { self.exists .assign(region, offset, Value::known(F::from(exists)))?; - self.code_hash.assign( - region, - offset, - region.word_rlc(code_hash) - )?; + self.code_hash + .assign(region, offset, region.word_rlc(code_hash))?; self.code_size .assign(region, offset, Value::known(F::from(code_size)))?; for (c, b) in self diff --git a/zkevm-circuits/src/evm_circuit/execution/mulmod.rs b/zkevm-circuits/src/evm_circuit/execution/mulmod.rs index e2919c5b89..4f2242df54 100644 --- a/zkevm-circuits/src/evm_circuit/execution/mulmod.rs +++ b/zkevm-circuits/src/evm_circuit/execution/mulmod.rs @@ -147,8 +147,7 @@ impl ExecutionGadget for MulModGadget { self.d.assign(region, offset, Some(d.to_le_bytes()))?; self.e.assign(region, offset, Some(e.to_le_bytes()))?; - self.modword - .assign(region, offset, a, n, a_reduced, k1)?; + self.modword.assign(region, offset, a, n, a_reduced, k1)?; self.mul512_left .assign(region, offset, [a_reduced, b, d, e], None)?; self.mul512_right diff --git a/zkevm-circuits/src/evm_circuit/util.rs b/zkevm-circuits/src/evm_circuit/util.rs index e9a03ebba1..38c415abba 100644 --- a/zkevm-circuits/src/evm_circuit/util.rs +++ b/zkevm-circuits/src/evm_circuit/util.rs @@ -256,7 +256,7 @@ pub(crate) enum CellType { StoragePhase2, StoragePhase3, StoragePermutation, - Lookup(Table) + Lookup(Table), } impl CellType { @@ -284,7 +284,6 @@ impl CellType { pub(crate) fn storage_for_expr(expr: &Expression) -> CellType { Self::storage_for_phase::(Self::expr_phase::(expr)) } - } #[derive(Clone, Debug)] @@ -355,7 +354,7 @@ impl CellManager { column_idx += 1; } - // Mark columns used for copy constraints + // Mark columns used for copy constraints for _ in 0..N_COPY_COLUMNS { meta.enable_equality(advices[column_idx]); columns[column_idx].cell_type = CellType::StoragePermutation; @@ -589,10 +588,10 @@ pub(crate) fn split_u256_limb64(value: &U256) -> [U256; 4] { } /// Transposes an `Value` of a [`Result`] into a [`Result`] of an `Value`. -pub(crate) fn transpose_val_ret(value: Value>) -> Result,E> { - let mut ret= Ok(Value::unknown()); +pub(crate) fn transpose_val_ret(value: Value>) -> Result, E> { + let mut ret = Ok(Value::unknown()); value.map(|value| { ret = value.map(Value::known); - }); - ret -} + }); + ret +} diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs index 6ebc4b54e3..a23af6c2e4 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/batched_is_zero.rs @@ -1,5 +1,7 @@ use crate::{ - evm_circuit::util::{constraint_builder::ConstraintBuilder, CachedRegion, Cell, CellType, transpose_val_ret}, + evm_circuit::util::{ + constraint_builder::ConstraintBuilder, transpose_val_ret, CachedRegion, Cell, CellType, + }, util::Expr, }; use eth_types::Field; @@ -16,16 +18,16 @@ pub struct BatchedIsZeroGadget { impl BatchedIsZeroGadget { pub(crate) fn construct(cb: &mut ConstraintBuilder, values: [Expression; N]) -> Self { - let max_values_phase= values - .iter() - .map(CellType::expr_phase) - .max() - .expect("BatchedIsZeroGadget needs at least one expression"); - - let cell_type = CellType::storage_for_phase::(max_values_phase); - let is_zero = cb.query_bool_with_type(cell_type); - let nonempty_witness = cb.query_cell_with_type(cell_type); - + let max_values_phase = values + .iter() + .map(CellType::expr_phase) + .max() + .expect("BatchedIsZeroGadget needs at least one expression"); + + let cell_type = CellType::storage_for_phase::(max_values_phase); + let is_zero = cb.query_bool_with_type(cell_type); + let nonempty_witness = cb.query_cell_with_type(cell_type); + for value in values.iter() { cb.require_zero( "is_zero is 0 if there is any non-zero value", @@ -77,8 +79,7 @@ impl BatchedIsZeroGadget { ) -> Result, Error> { let values: Value<[F; N]> = Value::>::from_iter(values).map(|vv| vv.try_into().unwrap()); - transpose_val_ret(values - .map(|values| self.assign(region, offset, values))) + transpose_val_ret(values.map(|values| self.assign(region, offset, values))) } } diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs index 41a1db6c66..52589c68c0 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/constant_division.rs @@ -1,6 +1,7 @@ use crate::{ evm_circuit::util::{ - constraint_builder::ConstraintBuilder, math_gadget::*, CachedRegion, Cell, CellType, transpose_val_ret + constraint_builder::ConstraintBuilder, math_gadget::*, transpose_val_ret, CachedRegion, + Cell, CellType, }, util::Expr, }; @@ -89,9 +90,9 @@ impl ConstantDivisionGadget { offset: usize, numerator: Value, ) -> Result, Error> { - transpose_val_ret(numerator - .map(|numerator| self.assign(region, offset, numerator.get_lower_128())) - ) + transpose_val_ret( + numerator.map(|numerator| self.assign(region, offset, numerator.get_lower_128())), + ) } } diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/is_equal.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/is_equal.rs index 896e42cb4f..c731173790 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/is_equal.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/is_equal.rs @@ -1,9 +1,12 @@ use crate::evm_circuit::{ util::constraint_builder::ConstraintBuilder, - util::{math_gadget::*, CachedRegion, transpose_val_ret}, + util::{math_gadget::*, transpose_val_ret, CachedRegion}, }; use eth_types::Field; -use halo2_proofs::{plonk::{Error, Expression}, circuit::Value}; +use halo2_proofs::{ + circuit::Value, + plonk::{Error, Expression}, +}; /// Returns `1` when `lhs == rhs`, and returns `0` otherwise. #[derive(Clone, Debug)] @@ -43,10 +46,11 @@ impl IsEqualGadget { lhs: Value, rhs: Value, ) -> Result, Error> { - transpose_val_ret(lhs.zip(rhs) - .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs))) + transpose_val_ret( + lhs.zip(rhs) + .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs)), + ) } - } #[cfg(test)] diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs index cf2a2701bb..b553c71365 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/is_zero.rs @@ -1,5 +1,7 @@ use crate::{ - evm_circuit::util::{constraint_builder::ConstraintBuilder, CachedRegion, Cell, CellType, transpose_val_ret}, + evm_circuit::util::{ + constraint_builder::ConstraintBuilder, transpose_val_ret, CachedRegion, Cell, CellType, + }, util::Expr, }; use eth_types::Field; @@ -58,8 +60,7 @@ impl IsZeroGadget { offset: usize, value: Value, ) -> Result, Error> { - transpose_val_ret(value - .map(|value| self.assign(region, offset, value))) + transpose_val_ret(value.map(|value| self.assign(region, offset, value))) } } diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/lt.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/lt.rs index 90c18bd6c3..ab7c7a8fc3 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/lt.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/lt.rs @@ -1,6 +1,7 @@ use crate::{ evm_circuit::util::{ - constraint_builder::ConstraintBuilder, from_bytes, pow_of_two, CachedRegion, Cell,transpose_val_ret + constraint_builder::ConstraintBuilder, from_bytes, pow_of_two, transpose_val_ret, + CachedRegion, Cell, }, util::Expr, }; @@ -91,10 +92,11 @@ impl LtGadget { lhs: Value, rhs: Value, ) -> Result)>, Error> { - transpose_val_ret(lhs.zip(rhs) - .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs))) + transpose_val_ret( + lhs.zip(rhs) + .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs)), + ) } - } #[cfg(test)] diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/lt_word.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/lt_word.rs index 65e33a162d..ae1408a348 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/lt_word.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/lt_word.rs @@ -63,7 +63,6 @@ impl LtWordGadget { )?; Ok(()) } - } #[cfg(test)] diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/min_max.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/min_max.rs index 0e4010e155..3cf605be0e 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/min_max.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/min_max.rs @@ -1,8 +1,11 @@ use crate::evm_circuit::util::{ - constraint_builder::ConstraintBuilder, math_gadget::*, select, CachedRegion, transpose_val_ret + constraint_builder::ConstraintBuilder, math_gadget::*, select, transpose_val_ret, CachedRegion, }; use eth_types::Field; -use halo2_proofs::{plonk::{Error, Expression}, circuit::Value}; +use halo2_proofs::{ + circuit::Value, + plonk::{Error, Expression}, +}; /// Returns `rhs` when `lhs < rhs`, and returns `lhs` otherwise. /// lhs and rhs `< 256**N_BYTES` /// `N_BYTES` is required to be `<= MAX_N_BYTES_INTEGER`. @@ -56,9 +59,11 @@ impl MinMaxGadget { lhs: Value, rhs: Value, ) -> Result, Error> { - transpose_val_ret(lhs.zip(rhs) - .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs))) - } + transpose_val_ret( + lhs.zip(rhs) + .map(|(lhs, rhs)| self.assign(region, offset, lhs, rhs)), + ) + } } #[cfg(test)] diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/modulo.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/modulo.rs index a04c4a16ba..2f62f5d181 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/modulo.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/modulo.rs @@ -5,7 +5,7 @@ use crate::{ util::Expr, }; use eth_types::{Field, ToLittleEndian, Word}; -use halo2_proofs::{plonk::Error}; +use halo2_proofs::plonk::Error; /// Constraints for the words a, n, r: /// a mod n = r, if n!=0 diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/test_util.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/test_util.rs index 72d842bdeb..8a5c0cf2a6 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/test_util.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/test_util.rs @@ -2,16 +2,20 @@ use itertools::Itertools; use std::marker::PhantomData; use strum::IntoEnumIterator; -use crate::{evm_circuit::{ - param::{MAX_STEP_HEIGHT, STEP_WIDTH}, - step::{ExecutionState, Step}, - table::{FixedTableTag, Table}, - util::{ - constraint_builder::ConstraintBuilder, rlc, CachedRegion, CellType, Expr, StoredExpression, - }, - Advice, Column, Fixed, -}, util::Challenges}; use crate::table::LookupTable; +use crate::{ + evm_circuit::{ + param::{MAX_STEP_HEIGHT, STEP_WIDTH}, + step::{ExecutionState, Step}, + table::{FixedTableTag, Table}, + util::{ + constraint_builder::ConstraintBuilder, rlc, CachedRegion, CellType, Expr, + StoredExpression, + }, + Advice, Column, Fixed, + }, + util::Challenges, +}; use eth_types::{Field, Word, U256}; pub(crate) use halo2_proofs::circuit::{Layouter, Value}; use halo2_proofs::{ @@ -102,7 +106,8 @@ impl> Circuit for UnitTestMathGadgetBaseC let challenges = Challenges::construct(meta); let challenges_exprs = challenges.exprs(meta); let evm_word_powers_of_randomness = challenges_exprs.evm_word_powers_of_randomness(); - let lookup_input_powers_of_randomness = challenges_exprs.lookup_input_powers_of_randomness(); + let lookup_input_powers_of_randomness = + challenges_exprs.lookup_input_powers_of_randomness(); let mut cb = ConstraintBuilder::new( step_curr.clone(), step_next, @@ -140,16 +145,19 @@ impl> Circuit for UnitTestMathGadgetBaseC } } - (UnitTestMathGadgetBaseCircuitConfig:: { - q_usable, - fixed_table, - advices, - step: step_curr, - stored_expressions, - math_gadget_container, - _marker: PhantomData, - challenges: challenges_exprs, - }, challenges) + ( + UnitTestMathGadgetBaseCircuitConfig:: { + q_usable, + fixed_table, + advices, + step: step_curr, + stored_expressions, + math_gadget_container, + _marker: PhantomData, + challenges: challenges_exprs, + }, + challenges, + ) } fn synthesize( diff --git a/zkevm-circuits/src/util.rs b/zkevm-circuits/src/util.rs index 046300ebd4..39421dbb80 100644 --- a/zkevm-circuits/src/util.rs +++ b/zkevm-circuits/src/util.rs @@ -4,7 +4,8 @@ use halo2_proofs::{ circuit::{Layouter, Value}, plonk::{ Challenge, ConstraintSystem, Error, Expression, FirstPhase, SecondPhase, VirtualCells, - }}; + }, +}; use crate::table::TxLogFieldTag; use crate::witness; @@ -28,7 +29,6 @@ pub(crate) fn random_linear_combine_word(bytes: [u8; 32], randomnes crate::evm_circuit::util::Word::random_linear_combine(bytes, randomness) } - /// All challenges used in `SuperCircuit`. #[derive(Default, Clone, Copy, Debug)] pub struct Challenges { From f4ab55412faf948e5a5080e7599d46aba04dc6fc Mon Sep 17 00:00:00 2001 From: adria0 Date: Wed, 11 Jan 2023 16:10:15 +0100 Subject: [PATCH 16/18] @han0110 nitpicks --- zkevm-circuits/src/evm_circuit/execution.rs | 1 - zkevm-circuits/src/evm_circuit/execution/callop.rs | 2 +- zkevm-circuits/src/evm_circuit/util.rs | 5 ++--- zkevm-circuits/src/witness/block.rs | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index e618306ab2..b19a0fb868 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -1293,7 +1293,6 @@ impl ExecutionConfig { set }); - // [TODO] Check this for (name, value) in assigned_rw_values.iter() { if !rlc_assignments.contains(value) { log::error!("rw lookup error: name: {}, step: {:?}", *name, step); diff --git a/zkevm-circuits/src/evm_circuit/execution/callop.rs b/zkevm-circuits/src/evm_circuit/execution/callop.rs index b857bcbf3f..3be4cc699d 100644 --- a/zkevm-circuits/src/evm_circuit/execution/callop.rs +++ b/zkevm-circuits/src/evm_circuit/execution/callop.rs @@ -11,7 +11,7 @@ use crate::evm_circuit::util::math_gadget::{ }; use crate::evm_circuit::util::memory_gadget::{MemoryAddressGadget, MemoryExpansionGadget}; use crate::evm_circuit::util::{ - from_bytes, not, or, select, sum, CachedRegion, Cell, Word, CellType, + from_bytes, not, or, select, sum, CachedRegion, Cell, CellType, Word, }; use crate::evm_circuit::witness::{Block, Call, ExecStep, Rw, Transaction}; use crate::table::{AccountFieldTag, CallContextFieldTag}; diff --git a/zkevm-circuits/src/evm_circuit/util.rs b/zkevm-circuits/src/evm_circuit/util.rs index 38c415abba..2364d85145 100644 --- a/zkevm-circuits/src/evm_circuit/util.rs +++ b/zkevm-circuits/src/evm_circuit/util.rs @@ -18,6 +18,7 @@ use halo2_proofs::{ }; use itertools::Itertools; use std::collections::BTreeMap; +use std::hash::{Hash, Hasher}; pub(crate) mod common_gadget; pub(crate) mod constraint_builder; @@ -75,7 +76,6 @@ impl Expr for &Cell { self.expression.clone() } } - pub struct CachedRegion<'r, 'b, F: FieldExt> { region: &'r mut Region<'b, F>, advice: Vec>, @@ -207,8 +207,6 @@ pub struct StoredExpression { expr_id: String, } -use std::hash::{Hash, Hasher}; - impl Hash for StoredExpression { fn hash(&self, state: &mut H) { self.expr_id.hash(state); @@ -260,6 +258,7 @@ pub(crate) enum CellType { } impl CellType { + // The phase that given `Expression` becomes evaluateable. fn expr_phase(expr: &Expression) -> u8 { use Expression::*; match expr { diff --git a/zkevm-circuits/src/witness/block.rs b/zkevm-circuits/src/witness/block.rs index d51b46dcba..37257b2acb 100644 --- a/zkevm-circuits/src/witness/block.rs +++ b/zkevm-circuits/src/witness/block.rs @@ -175,7 +175,7 @@ pub fn block_convert( code_db: &bus_mapping::state_db::CodeDB, ) -> Result, Error> { Ok(Block { - randomness: F::from(0x10000), // Special value to reveal elements after RLC + randomness: F::from(0xcafeu64), // Special value to reveal elements after RLC context: block.into(), rws: RwMap::from(&block.container), txs: block From 693e4d5328762a55a7105cfd41eeda6f12a49e93 Mon Sep 17 00:00:00 2001 From: adria0 Date: Wed, 11 Jan 2023 17:50:04 +0100 Subject: [PATCH 17/18] Re-add comment --- zkevm-circuits/src/witness/block.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zkevm-circuits/src/witness/block.rs b/zkevm-circuits/src/witness/block.rs index 37257b2acb..a839a1cfe5 100644 --- a/zkevm-circuits/src/witness/block.rs +++ b/zkevm-circuits/src/witness/block.rs @@ -175,7 +175,8 @@ pub fn block_convert( code_db: &bus_mapping::state_db::CodeDB, ) -> Result, Error> { Ok(Block { - randomness: F::from(0xcafeu64), // Special value to reveal elements after RLC + // randomness: F::from(0x100), // Special value to reveal elements after RLC + randomness: F::from(0xcafeu64), context: block.into(), rws: RwMap::from(&block.container), txs: block From 93dc400bcc636afaf6b902955e5a1453b9e302e2 Mon Sep 17 00:00:00 2001 From: adria0 Date: Thu, 12 Jan 2023 13:34:52 +0100 Subject: [PATCH 18/18] Add empty_hash_rlc, cleanup comments --- zkevm-circuits/src/evm_circuit/execution/begin_tx.rs | 12 ++++-------- zkevm-circuits/src/evm_circuit/execution/callop.rs | 11 +++-------- .../src/evm_circuit/execution/error_oog_call.rs | 12 ++++-------- .../src/evm_circuit/execution/extcodehash.rs | 9 +++------ .../src/evm_circuit/execution/return_revert.rs | 5 +---- zkevm-circuits/src/evm_circuit/util.rs | 4 ++++ .../src/evm_circuit/util/constraint_builder.rs | 5 +++++ 7 files changed, 24 insertions(+), 34 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs index 0de08ce061..cd438f197c 100644 --- a/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs +++ b/zkevm-circuits/src/evm_circuit/execution/begin_tx.rs @@ -17,10 +17,9 @@ use crate::{ table::{AccountFieldTag, CallContextFieldTag, TxFieldTag as TxContextFieldTag}, util::Expr, }; -use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar, U256}; +use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar}; use halo2_proofs::circuit::Value; use halo2_proofs::plonk::Error; -use keccak256::EMPTY_HASH_LE; #[derive(Clone, Debug)] pub(crate) struct BeginTxGadget { @@ -157,11 +156,8 @@ impl ExecutionGadget for BeginTxGadget { phase2_code_hash.expr(), ); - let is_empty_code_hash = IsEqualGadget::construct( - cb, - phase2_code_hash.expr(), - cb.word_rlc((*EMPTY_HASH_LE).map(|byte| byte.expr())), - ); + let is_empty_code_hash = + IsEqualGadget::construct(cb, phase2_code_hash.expr(), cb.empty_hash_rlc()); cb.condition(is_empty_code_hash.expr(), |cb| { cb.require_equal( @@ -349,7 +345,7 @@ impl ExecutionGadget for BeginTxGadget { region, offset, region.word_rlc(callee_code_hash), - region.word_rlc(U256::from_little_endian(&*EMPTY_HASH_LE)), + region.empty_hash_rlc(), )?; Ok(()) } diff --git a/zkevm-circuits/src/evm_circuit/execution/callop.rs b/zkevm-circuits/src/evm_circuit/execution/callop.rs index 3be4cc699d..e675cefe7f 100644 --- a/zkevm-circuits/src/evm_circuit/execution/callop.rs +++ b/zkevm-circuits/src/evm_circuit/execution/callop.rs @@ -263,11 +263,8 @@ impl ExecutionGadget for CallOpGadget { cb.account_read(code_address, AccountFieldTag::NonExisting, 0.expr()); }); - let is_empty_code_hash = IsEqualGadget::construct( - cb, - callee_code_hash.expr(), - cb.word_rlc((*EMPTY_HASH_LE).map(|byte| byte.expr())), - ); + let is_empty_code_hash = + IsEqualGadget::construct(cb, callee_code_hash.expr(), cb.empty_hash_rlc()); // Sum up and verify gas cost. let gas_cost = select::expr( @@ -694,7 +691,7 @@ impl ExecutionGadget for CallOpGadget { region, offset, callee_code_hash, - region.word_rlc(U256::from_little_endian(&*EMPTY_HASH_LE)), + region.empty_hash_rlc(), )?; let has_value = !value.is_zero() && !is_delegatecall; let gas_cost = if is_warm_prev { @@ -978,8 +975,6 @@ mod test { caller(&OpcodeId::CALL, Stack::default(), true), callee(bytecode! {}), ); - // use crate::evm_circuit::util::print_op_count; - // print_op_count(); } fn test_ok(caller: Account, callee: Account) { diff --git a/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs b/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs index 6ff130afeb..a46537cd25 100644 --- a/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs +++ b/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs @@ -18,9 +18,8 @@ use crate::evm_circuit::{ use crate::table::{AccountFieldTag, CallContextFieldTag}; use crate::util::Expr; use bus_mapping::evm::OpcodeId; -use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar, U256}; +use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar}; use halo2_proofs::{circuit::Value, plonk::Error}; -use keccak256::EMPTY_HASH_LE; #[derive(Clone, Debug)] pub(crate) struct ErrorOOGCallGadget { @@ -115,11 +114,8 @@ impl ExecutionGadget for ErrorOOGCallGadget { }); let is_empty_nonce_and_balance = BatchedIsZeroGadget::construct(cb, [callee_nonce.expr(), balance.expr()]); - let is_empty_code_hash = IsEqualGadget::construct( - cb, - phase2_callee_code_hash.expr(), - cb.word_rlc((*EMPTY_HASH_LE).map(|byte| byte.expr())), - ); + let is_empty_code_hash = + IsEqualGadget::construct(cb, phase2_callee_code_hash.expr(), cb.empty_hash_rlc()); let is_empty_account = is_empty_nonce_and_balance.expr() * is_empty_code_hash.expr(); // Sum up gas cost let gas_cost = select::expr( @@ -290,7 +286,7 @@ impl ExecutionGadget for ErrorOOGCallGadget { region, offset, region.word_rlc(callee_code_hash), - region.word_rlc(U256::from_little_endian(&*EMPTY_HASH_LE)), + region.empty_hash_rlc(), )?; let is_empty_account = is_empty_nonce_and_balance * is_empty_code_hash; let has_value = !value.is_zero(); diff --git a/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs b/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs index 0c8f5f4530..18a08a6a37 100644 --- a/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs +++ b/zkevm-circuits/src/evm_circuit/execution/extcodehash.rs @@ -17,9 +17,8 @@ use crate::{ table::{AccountFieldTag, CallContextFieldTag}, util::Expr, }; -use eth_types::{evm_types::GasCost, Field, ToLittleEndian, U256}; +use eth_types::{evm_types::GasCost, Field, ToLittleEndian}; use halo2_proofs::{circuit::Value, plonk::Error}; -use keccak256::EMPTY_HASH_LE; #[derive(Clone, Debug)] pub(crate) struct ExtcodehashGadget { @@ -63,7 +62,6 @@ impl ExecutionGadget for ExtcodehashGadget { let code_hash = cb.query_cell(); cb.account_read(address, AccountFieldTag::CodeHash, code_hash.expr()); - let empty_code_hash_rlc = cb.word_rlc((*EMPTY_HASH_LE).map(|byte| byte.expr())); // Note that balance is RLC encoded, but RLC(x) = 0 iff x = 0, so we don't need // go to the work of writing out the RLC expression let is_empty = BatchedIsZeroGadget::construct( @@ -71,7 +69,7 @@ impl ExecutionGadget for ExtcodehashGadget { [ nonce.expr(), balance.expr(), - code_hash.expr() - empty_code_hash_rlc, + code_hash.expr() - cb.empty_hash_rlc(), ], ); @@ -148,11 +146,10 @@ impl ExecutionGadget for ExtcodehashGadget { self.balance.assign(region, offset, balance)?; self.code_hash.assign(region, offset, code_hash)?; - let empty_code_hash_rlc = region.word_rlc(U256::from_little_endian(&*EMPTY_HASH_LE)); self.is_empty.assign_value( region, offset, - [nonce, balance, code_hash - empty_code_hash_rlc], + [nonce, balance, code_hash - region.empty_hash_rlc()], )?; Ok(()) diff --git a/zkevm-circuits/src/evm_circuit/execution/return_revert.rs b/zkevm-circuits/src/evm_circuit/execution/return_revert.rs index 445caf96fe..5aae53e5f2 100644 --- a/zkevm-circuits/src/evm_circuit/execution/return_revert.rs +++ b/zkevm-circuits/src/evm_circuit/execution/return_revert.rs @@ -22,7 +22,6 @@ use bus_mapping::{circuit_input_builder::CopyDataType, evm::OpcodeId}; use eth_types::{Field, ToScalar, U256}; use ethers_core::utils::keccak256; use halo2_proofs::{circuit::Value, plonk::Error}; -use keccak256::EMPTY_HASH_LE; #[derive(Clone, Debug)] pub(crate) struct ReturnRevertGadget { @@ -121,13 +120,11 @@ impl ExecutionGadget for ReturnRevertGadget { .map(|tag| cb.call_context(None, tag)); let mut reversion_info = cb.reversion_info_read(None); - let empty_code_hash_rlc = cb.word_rlc((*EMPTY_HASH_LE).map(|byte| byte.expr())); - cb.account_write( address.expr(), AccountFieldTag::CodeHash, code_hash.expr(), - empty_code_hash_rlc, + cb.empty_hash_rlc(), Some(&mut reversion_info), ); diff --git a/zkevm-circuits/src/evm_circuit/util.rs b/zkevm-circuits/src/evm_circuit/util.rs index 2364d85145..575f3f86b2 100644 --- a/zkevm-circuits/src/evm_circuit/util.rs +++ b/zkevm-circuits/src/evm_circuit/util.rs @@ -17,6 +17,7 @@ use halo2_proofs::{ poly::Rotation, }; use itertools::Itertools; +use keccak256::EMPTY_HASH_LE; use std::collections::BTreeMap; use std::hash::{Hash, Hasher}; @@ -181,6 +182,9 @@ impl<'r, 'b, F: FieldExt> CachedRegion<'r, 'b, F> { .evm_word() .map(|r| Word::random_linear_combine(n.to_le_bytes(), r)) } + pub fn empty_hash_rlc(&self) -> Value { + self.word_rlc(U256::from_little_endian(&*EMPTY_HASH_LE)) + } /// Constrains a cell to have a constant value. /// diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index bd4d299fc2..c18d81f4e0 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -20,6 +20,7 @@ use halo2_proofs::{ Expression::{self, Constant}, }, }; +use keccak256::EMPTY_HASH_LE; use super::{rlc, CachedRegion, CellType, StoredExpression}; @@ -421,6 +422,10 @@ impl<'a, F: Field> ConstraintBuilder<'a, F> { RandomLinearCombination::random_linear_combine_expr(bytes, self.word_powers_of_randomness) } + pub(crate) fn empty_hash_rlc(&self) -> Expression { + self.word_rlc((*EMPTY_HASH_LE).map(|byte| byte.expr())) + } + // Common pub(crate) fn require_zero(&mut self, name: &'static str, constraint: Expression) {