From 876d234f374ad2d78a615a99dcd723cdf1e579ea Mon Sep 17 00:00:00 2001 From: Akase Cho Date: Sat, 25 Nov 2023 09:51:04 +0800 Subject: [PATCH] [feat] add feature switch of memory/stack/storage (#1038) * add feature switch * add missing * fix merge --- bus-mapping/Cargo.toml | 6 ++- bus-mapping/src/circuit_input_builder.rs | 2 +- bus-mapping/src/evm/opcodes.rs | 11 ++-- .../src/evm/opcodes/memory_expansion_test.rs | 15 +++--- bus-mapping/src/rpc.rs | 10 ++-- bus-mapping/src/util.rs | 41 ++++++++++++++- eth-types/Cargo.toml | 5 ++ eth-types/src/l2_types.rs | 25 ++++++--- eth-types/src/lib.rs | 52 ++++++++++++++----- external-tracer/Cargo.toml | 3 ++ external-tracer/src/lib.rs | 7 +-- mock/Cargo.toml | 3 ++ testool/Cargo.toml | 6 ++- testool/src/statetest/executor.rs | 5 +- testool/src/utils.rs | 28 ++++++++-- zkevm-circuits/Cargo.toml | 6 ++- 16 files changed, 173 insertions(+), 52 deletions(-) diff --git a/bus-mapping/Cargo.toml b/bus-mapping/Cargo.toml index 66571d6fae..37ba2466fd 100644 --- a/bus-mapping/Cargo.toml +++ b/bus-mapping/Cargo.toml @@ -41,8 +41,12 @@ mock = { path = "../mock" } rand.workspace = true [features] -default = ["test"] +default = ["test", "enable-stack", "enable-storage"] test = ["mock", "rand"] scroll = ["eth-types/scroll", "mock?/scroll"] # Enable shanghai feature of mock only if mock is enabled (by test). shanghai = ["eth-types/shanghai", "mock?/shanghai"] +tracer-tests = ["enable-memory"] +enable-stack = ["eth-types/enable-stack", "mock?/enable-stack"] +enable-memory = ["eth-types/enable-memory", "mock?/enable-memory"] +enable-storage = ["eth-types/enable-storage", "mock?/enable-storage"] \ No newline at end of file diff --git a/bus-mapping/src/circuit_input_builder.rs b/bus-mapping/src/circuit_input_builder.rs index 99724377e0..102930d256 100644 --- a/bus-mapping/src/circuit_input_builder.rs +++ b/bus-mapping/src/circuit_input_builder.rs @@ -8,7 +8,7 @@ mod execution; mod input_state_ref; #[cfg(feature = "scroll")] mod l2; -#[cfg(test)] +#[cfg(all(feature = "tracer-tests", feature = "enable-memory", test))] mod tracer_tests; mod transaction; diff --git a/bus-mapping/src/evm/opcodes.rs b/bus-mapping/src/evm/opcodes.rs index 1a404d8862..15bd6c6c41 100644 --- a/bus-mapping/src/evm/opcodes.rs +++ b/bus-mapping/src/evm/opcodes.rs @@ -12,7 +12,8 @@ use crate::{ use core::fmt::Debug; use eth_types::{evm_unimplemented, GethExecStep, ToAddress, ToWord, Word}; -use crate::util::CHECK_MEM_STRICT; +#[cfg(feature = "enable-memory")] +use crate::util::GETH_TRACE_CHECK_LEVEL; #[cfg(any(feature = "test", test))] pub use self::sha3::sha3_tests::{gen_sha3_code, MemoryKind}; @@ -70,7 +71,7 @@ mod error_precompile_failed; mod error_return_data_outofbound; mod error_write_protection; -#[cfg(test)] +#[cfg(all(feature = "enable-memory", test))] mod memory_expansion_test; #[cfg(feature = "test")] pub use callop::tests::PrecompileCallArgs; @@ -383,8 +384,8 @@ pub fn gen_associated_ops( state: &mut CircuitInputStateRef, geth_steps: &[GethExecStep], ) -> Result, Error> { - let check_level = if *CHECK_MEM_STRICT { 2 } else { 0 }; // 0: no check, 1: check and log error and fix, 2: check and assert_eq - if check_level >= 1 { + #[cfg(feature = "enable-memory")] + if GETH_TRACE_CHECK_LEVEL.should_check() { let memory_enabled = !geth_steps.iter().all(|s| s.memory.is_empty()); assert!(memory_enabled); if memory_enabled { @@ -414,7 +415,7 @@ pub fn gen_associated_ops( ); } } - if check_level >= 2 { + if GETH_TRACE_CHECK_LEVEL.should_panic() { panic!("mem wrong"); } state.call_ctx_mut()?.memory = geth_steps[0].memory.clone(); diff --git a/bus-mapping/src/evm/opcodes/memory_expansion_test.rs b/bus-mapping/src/evm/opcodes/memory_expansion_test.rs index 36eb5ad5a0..43b0424a47 100644 --- a/bus-mapping/src/evm/opcodes/memory_expansion_test.rs +++ b/bus-mapping/src/evm/opcodes/memory_expansion_test.rs @@ -15,14 +15,13 @@ fn might_neg_index(index: isize, len: usize) -> usize { } } -fn assert_expanded(_traces: &[GethExecStep], _before: isize, _after: isize) { - // FIXME: memory is removed - // let traces_len = traces.len(); - // let before = might_neg_index(before, traces_len); - // let after = might_neg_index(after, traces_len); - // let size_before = traces[before].memory.borrow().len(); - // let size_after = traces[after].memory.borrow().len(); - // assert_ne!(size_before, size_after); +fn assert_expanded(traces: &[GethExecStep], before: isize, after: isize) { + let traces_len = traces.len(); + let before = might_neg_index(before, traces_len); + let after = might_neg_index(after, traces_len); + let size_before = traces[before].memory.0.len(); + let size_after = traces[after].memory.0.len(); + assert_ne!(size_before, size_after); } fn trace_and_assert(code: Bytecode, before: isize, after: isize, assert_fn: FN) diff --git a/bus-mapping/src/rpc.rs b/bus-mapping/src/rpc.rs index b67d0fafe8..7525671829 100644 --- a/bus-mapping/src/rpc.rs +++ b/bus-mapping/src/rpc.rs @@ -11,7 +11,7 @@ use ethers_providers::JsonRpcClient; use serde::Serialize; use std::collections::HashMap; -use crate::util::CHECK_MEM_STRICT; +use crate::util::GETH_TRACE_CHECK_LEVEL; /// Serialize a type. /// @@ -45,9 +45,9 @@ pub(crate) struct GethLoggerConfig { impl Default for GethLoggerConfig { fn default() -> Self { Self { - enable_memory: false, - disable_stack: false, - disable_storage: false, + enable_memory: cfg!(feature = "enable-memory"), + disable_stack: !cfg!(feature = "enable-stack"), + disable_storage: !cfg!(feature = "enable-storage"), enable_return_data: true, timeout: None, } @@ -156,7 +156,7 @@ impl GethClient

{ pub async fn trace_tx_by_hash(&self, hash: H256) -> Result { let hash = serialize(&hash); let cfg = GethLoggerConfig { - enable_memory: *CHECK_MEM_STRICT, + enable_memory: cfg!(feature = "enable-memory") && GETH_TRACE_CHECK_LEVEL.should_check(), ..Default::default() }; let cfg = serialize(&cfg); diff --git a/bus-mapping/src/util.rs b/bus-mapping/src/util.rs index fb4340b75e..f6bc6e8ea8 100644 --- a/bus-mapping/src/util.rs +++ b/bus-mapping/src/util.rs @@ -3,6 +3,7 @@ use eth_types::{Hash, U256}; pub use eth_types::{KECCAK_CODE_HASH_EMPTY, POSEIDON_CODE_HASH_EMPTY}; use halo2_proofs::halo2curves::{bn256::Fr, group::ff::PrimeField}; use once_cell::sync::Lazy; +use std::convert::Infallible; use std::str::FromStr; @@ -12,8 +13,44 @@ pub fn read_env_var(var_name: &'static str, default: T) -> T .map(|s| s.parse::().unwrap_or_else(|_| default.clone())) .unwrap_or(default) } -/// .. -pub static CHECK_MEM_STRICT: Lazy = Lazy::new(|| read_env_var("CHECK_MEM_STRICT", false)); +/// env var for Geth trace sanity check level +pub static GETH_TRACE_CHECK_LEVEL: Lazy = + Lazy::new(|| read_env_var("GETH_TRACE_CHECK_LEVEL", GethTraceSanityCheckLevel::None)); + +/// Geth trace sanity check level +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum GethTraceSanityCheckLevel { + /// No sanity check + None, + /// Check sanity and log error + Check, + /// Panic on error + Strict, +} + +impl GethTraceSanityCheckLevel { + /// Whether to do sanity check + pub fn should_check(&self) -> bool { + *self != GethTraceSanityCheckLevel::None + } + + /// Whether to panic on error + pub fn should_panic(&self) -> bool { + *self == GethTraceSanityCheckLevel::Strict + } +} + +impl FromStr for GethTraceSanityCheckLevel { + type Err = Infallible; + + fn from_str(s: &str) -> Result { + match s { + "strict" => Ok(GethTraceSanityCheckLevel::Strict), + _ if !s.is_empty() => Ok(GethTraceSanityCheckLevel::Check), + _ => Ok(GethTraceSanityCheckLevel::None), + } + } +} /// Default number of bytes to pack into a field element. pub const POSEIDON_HASH_BYTES_IN_FIELD: usize = 31; diff --git a/eth-types/Cargo.toml b/eth-types/Cargo.toml index 43d47b92d2..c8ad12b1f8 100644 --- a/eth-types/Cargo.toml +++ b/eth-types/Cargo.toml @@ -30,3 +30,8 @@ default = ["warn-unimplemented"] warn-unimplemented = [] shanghai = [] scroll = [] + +# trace heap allocation related feature switches +enable-stack = [] +enable-memory = [] +enable-storage = [] \ No newline at end of file diff --git a/eth-types/src/l2_types.rs b/eth-types/src/l2_types.rs index 66dc88dd55..9730834b29 100644 --- a/eth-types/src/l2_types.rs +++ b/eth-types/src/l2_types.rs @@ -1,13 +1,20 @@ //! L2 types used to deserialize traces for l2geth. use crate::{ - evm_types::{Gas, GasCost, Memory, OpcodeId, ProgramCounter, Stack, Storage}, + evm_types::{Gas, GasCost, OpcodeId, ProgramCounter}, Block, GethExecError, GethExecStep, GethExecTrace, Hash, Transaction, Word, H256, }; use ethers_core::types::{Address, Bytes, U256, U64}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; +#[cfg(feature = "enable-memory")] +use crate::evm_types::Memory; +#[cfg(feature = "enable-stack")] +use crate::evm_types::Stack; +#[cfg(feature = "enable-storage")] +use crate::evm_types::Storage; + /// l2 block full trace #[derive(Deserialize, Serialize, Default, Debug, Clone)] pub struct BlockTrace { @@ -226,8 +233,11 @@ pub struct ExecStep { pub refund: u64, pub depth: isize, pub error: Option, + #[cfg(feature = "enable-stack")] pub stack: Option>, + #[cfg(feature = "enable-memory")] pub memory: Option>, + #[cfg(feature = "enable-storage")] pub storage: Option>, #[serde(rename = "extraData")] pub extra_data: Option, @@ -235,10 +245,6 @@ pub struct ExecStep { impl From for GethExecStep { fn from(e: ExecStep) -> Self { - let stack = e.stack.map_or_else(Stack::new, Stack::from); - let storage = e.storage.map_or_else(Storage::empty, Storage::from); - let memory = e.memory.map_or_else(Memory::default, Memory::from); - GethExecStep { pc: ProgramCounter(e.pc as usize), // FIXME @@ -248,9 +254,12 @@ impl From for GethExecStep { refund: Gas(e.refund), depth: e.depth as u16, error: e.error, - stack, - memory, - storage, + #[cfg(feature = "enable-stack")] + stack: e.stack.map_or_else(Stack::new, Stack::from), + #[cfg(feature = "enable-memory")] + memory: e.memory.map_or_else(Memory::default, Memory::from), + #[cfg(feature = "enable-storage")] + storage: e.storage.map_or_else(Storage::empty, Storage::from), } } } diff --git a/eth-types/src/lib.rs b/eth-types/src/lib.rs index 174965904f..1e8cd1b9a5 100644 --- a/eth-types/src/lib.rs +++ b/eth-types/src/lib.rs @@ -30,9 +30,7 @@ use halo2_proofs::{ halo2curves::{bn256::Fr, group::ff::PrimeField}, }; -use crate::evm_types::{ - memory::Memory, stack::Stack, storage::Storage, Gas, GasCost, OpcodeId, ProgramCounter, -}; +use crate::evm_types::{Gas, GasCost, OpcodeId, ProgramCounter}; use ethers_core::types; pub use ethers_core::{ abi::ethereum_types::{BigEndianHash, U512}, @@ -41,7 +39,6 @@ pub use ethers_core::{ Address, Block, Bytes, Signature, H160, H256, H64, U256, U64, }, }; - use once_cell::sync::Lazy; use serde::{de, Deserialize, Deserializer, Serialize}; use std::{ @@ -51,6 +48,13 @@ use std::{ str::FromStr, }; +#[cfg(feature = "enable-memory")] +use crate::evm_types::Memory; +#[cfg(feature = "enable-stack")] +use crate::evm_types::Stack; +#[cfg(feature = "enable-storage")] +use crate::evm_types::Storage; + /// Trait used to reduce verbosity with the declaration of the [`FieldExt`] /// trait and its repr. pub trait Field: @@ -357,12 +361,15 @@ struct GethExecStepInternal { depth: u16, error: Option, // stack is in hex 0x prefixed + #[cfg(feature = "enable-stack")] #[serde(default)] stack: Vec, // memory is in chunks of 32 bytes, in hex + #[cfg(feature = "enable-memory")] #[serde(default)] memory: Vec, // storage is hex -> hex + #[cfg(feature = "enable-storage")] #[serde(default)] storage: HashMap, } @@ -380,10 +387,13 @@ pub struct GethExecStep { pub depth: u16, pub error: Option, // stack is in hex 0x prefixed + #[cfg(feature = "enable-stack")] pub stack: Stack, // memory is in chunks of 32 bytes, in hex + #[cfg(feature = "enable-memory")] pub memory: Memory, // storage is hex -> hex + #[cfg(feature = "enable-storage")] pub storage: Storage, } @@ -580,18 +590,21 @@ impl<'a> fmt::Debug for DebugWord<'a> { impl fmt::Debug for GethExecStep { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Step") - .field("pc", &format_args!("0x{:04x}", self.pc.0)) + let mut f = f.debug_struct("Step"); + f.field("pc", &format_args!("0x{:04x}", self.pc.0)) .field("op", &self.op) .field("gas", &format_args!("{}", self.gas.0)) .field("gas_cost", &format_args!("{}", self.gas_cost.0)) .field("refund", &format_args!("{}", self.refund.0)) .field("depth", &self.depth) - .field("error", &self.error) - .field("stack", &self.stack) - // .field("memory", &self.memory) - .field("storage", &self.storage) - .finish() + .field("error", &self.error); + #[cfg(feature = "enable-stack")] + f.field("stack", &self.stack); + #[cfg(feature = "enable-memory")] + f.field("memory", &self.memory); + #[cfg(feature = "enable-storage")] + f.field("storage", &self.storage); + f.finish() } } @@ -609,13 +622,16 @@ impl<'de> Deserialize<'de> for GethExecStep { gas_cost: s.gas_cost, depth: s.depth, error: s.error, + #[cfg(feature = "enable-stack")] stack: Stack(s.stack.iter().map(|dw| dw.to_word()).collect::>()), + #[cfg(feature = "enable-memory")] memory: Memory::from( s.memory .iter() .map(|dw| dw.to_word()) .collect::>(), ), + #[cfg(feature = "enable-storage")] storage: Storage( s.storage .iter() @@ -741,7 +757,10 @@ macro_rules! word_map { #[cfg(test)] mod tests { use super::*; - use crate::evm_types::{memory::Memory, opcode_ids::OpcodeId, stack::Stack}; + use crate::evm_types::{opcode_ids::OpcodeId, stack::Stack}; + + #[cfg(feature = "enable-memory")] + use crate::evm_types::memory::Memory; #[test] fn test_to_u16_array() { @@ -837,8 +856,11 @@ mod tests { gas_cost: GasCost(3), depth: 1, error: None, + #[cfg(feature = "enable-stack")] stack: Stack::new(), + #[cfg(feature = "enable-storage")] storage: Storage(word_map!()), + #[cfg(feature = "enable-memory")] memory: Memory::new(), }, GethExecStep { @@ -849,8 +871,11 @@ mod tests { gas_cost: GasCost(2100), depth: 1, error: None, + #[cfg(feature = "enable-stack")] stack: Stack(vec![word!("0x1003e2d2"), word!("0x2a"), word!("0x0")]), + #[cfg(feature = "enable-storage")] storage: Storage(word_map!("0x0" => "0x6f")), + #[cfg(feature = "enable-memory")] memory: Memory::from(vec![word!("0x0"), word!("0x0"), word!("0x080")]), }, GethExecStep { @@ -861,12 +886,15 @@ mod tests { gas_cost: GasCost(42), depth: 1, error: None, + #[cfg(feature = "enable-stack")] stack: Stack(vec![ word!("0x3635c9adc5dea00000"), word!("0x40"), word!("0x0") ]), + #[cfg(feature = "enable-storage")] storage: Storage(word_map!()), + #[cfg(feature = "enable-memory")] memory: Memory::from(vec![ word!( "000000000000000000000000b8f67472dcc25589672a61905f7fd63f09e5d470" diff --git a/external-tracer/Cargo.toml b/external-tracer/Cargo.toml index bf9f15a3d3..e2ccd77bba 100644 --- a/external-tracer/Cargo.toml +++ b/external-tracer/Cargo.toml @@ -14,3 +14,6 @@ log.workspace = true [features] default = [] scroll = ["eth-types/scroll", "geth-utils/scroll"] +enable-stack = [] +enable-memory = [] +enable-storage = [] diff --git a/external-tracer/src/lib.rs b/external-tracer/src/lib.rs index a90b099db7..a397580248 100644 --- a/external-tracer/src/lib.rs +++ b/external-tracer/src/lib.rs @@ -49,15 +49,16 @@ pub struct LoggerConfig { impl Default for LoggerConfig { fn default() -> Self { Self { - enable_memory: false, - disable_stack: false, - disable_storage: false, + enable_memory: cfg!(feature = "enable-memory"), + disable_stack: !cfg!(feature = "enable-stack"), + disable_storage: !cfg!(feature = "enable-storage"), enable_return_data: true, } } } impl LoggerConfig { + #[cfg(feature = "enable-memory")] pub fn enable_memory() -> Self { Self { enable_memory: true, diff --git a/mock/Cargo.toml b/mock/Cargo.toml index 31f7d57a76..5ccb1088c7 100644 --- a/mock/Cargo.toml +++ b/mock/Cargo.toml @@ -19,3 +19,6 @@ log.workspace = true default = [] shanghai = ["eth-types/shanghai"] scroll = ["eth-types/scroll", "external-tracer/scroll"] +enable-stack = ["eth-types/enable-stack", "external-tracer/enable-stack"] +enable-memory = ["eth-types/enable-memory", "external-tracer/enable-memory"] +enable-storage = ["eth-types/enable-storage", "external-tracer/enable-storage"] diff --git a/testool/Cargo.toml b/testool/Cargo.toml index 2d04aa1338..f51c7e3c21 100644 --- a/testool/Cargo.toml +++ b/testool/Cargo.toml @@ -41,7 +41,7 @@ urlencoding = "2.1.2" ctor.workspace = true [features] -default = ["ignore-test-docker", "skip-self-destruct", "shanghai"] +default = ["ignore-test-docker", "skip-self-destruct", "shanghai", "enable-stack", "enable-storage"] onephase = ["zkevm-circuits/onephase"] ignore-test-docker = [] skip-self-destruct = [] @@ -50,3 +50,7 @@ scroll = ["bus-mapping/scroll", "eth-types/scroll", "external-tracer/scroll", "m parallel_syn = ["halo2_proofs/parallel_syn", "zkevm-circuits/parallel_syn", "prover?/parallel_syn"] inner-prove = ["prover/test", "parallel_syn", "scroll", "shanghai"] chunk-prove = ["prover/test", "parallel_syn", "scroll", "shanghai"] + +enable-stack = ["zkevm-circuits/enable-stack"] +enable-memory = ["zkevm-circuits/enable-memory"] +enable-storage = ["zkevm-circuits/enable-storage"] \ No newline at end of file diff --git a/testool/src/statetest/executor.rs b/testool/src/statetest/executor.rs index 8339941b4a..c50dbde3ef 100644 --- a/testool/src/statetest/executor.rs +++ b/testool/src/statetest/executor.rs @@ -204,7 +204,10 @@ fn into_traceconfig(st: StateTest) -> (String, TraceConfig, StateTestResult) { }], accounts, logger_config: LoggerConfig { - enable_memory: *bus_mapping::util::CHECK_MEM_STRICT, + enable_memory: cfg!(feature = "enable-memory") + && bus_mapping::util::GETH_TRACE_CHECK_LEVEL.should_check(), + disable_stack: !cfg!(feature = "enable-stack"), + disable_storage: !cfg!(feature = "enable-storage"), ..Default::default() }, #[cfg(feature = "shanghai")] diff --git a/testool/src/utils.rs b/testool/src/utils.rs index 3101f7f703..e2a4d3eb0e 100644 --- a/testool/src/utils.rs +++ b/testool/src/utils.rs @@ -1,11 +1,14 @@ use std::str::FromStr; use anyhow::{bail, Result}; -use eth_types::{bytecode::OpcodeWithData, Bytecode, GethExecTrace, U256}; +use eth_types::{bytecode::OpcodeWithData, Bytecode, GethExecTrace}; use log::{error, info}; use prettytable::Table; use std::process::{Command, Stdio}; +#[cfg(any(feature = "enable-stack", feature = "enable-storage"))] +use eth_types::U256; + #[derive(Debug, Eq, PartialEq, PartialOrd)] pub enum MainnetFork { Shanghai = 15, @@ -84,6 +87,7 @@ impl MainnetFork { } pub fn print_trace(trace: GethExecTrace) -> Result<()> { + #[cfg(any(feature = "enable-stack", feature = "enable-storage"))] fn u256_to_str(u: &U256) -> String { if *u > U256::from_str("0x1000000000000000").unwrap() { format!("0x{u:x}") @@ -91,6 +95,7 @@ pub fn print_trace(trace: GethExecTrace) -> Result<()> { u.to_string() } } + #[cfg(feature = "enable-storage")] fn kv(storage: std::collections::HashMap) -> Vec { let mut keys: Vec<_> = storage.keys().collect(); keys.sort(); @@ -135,6 +140,21 @@ pub fn print_trace(trace: GethExecTrace) -> Result<()> { "PC", "OP", "GAS", "GAS_COST", "DEPTH", "ERR", "STACK", "MEMORY", "STORAGE" ]); for step in trace.struct_logs { + #[cfg(feature = "enable-stack")] + let stack = step.stack.0.iter().map(u256_to_str).collect(); + #[cfg(not(feature = "enable-stack"))] + let stack = vec![]; + + #[cfg(feature = "enable-memory")] + let memory = step.memory.0.iter().map(ToString::to_string).collect(); + #[cfg(not(feature = "enable-memory"))] + let memory = vec![]; + + #[cfg(feature = "enable-storage")] + let storage = kv(step.storage.0); + #[cfg(not(feature = "enable-storage"))] + let storage = vec![]; + table.add_row(row![ format!("{}", step.pc.0), format!("{:?}", step.op), @@ -142,9 +162,9 @@ pub fn print_trace(trace: GethExecTrace) -> Result<()> { format!("{}", step.gas_cost.0), format!("{}", step.depth), step.error.map(|e| e.error()).unwrap_or(""), - split(step.stack.0.iter().map(u256_to_str).collect(), 30), - split(step.memory.0.iter().map(ToString::to_string).collect(), 30), - split(kv(step.storage.0), 30) + split(stack, 30), + split(memory, 30), + split(storage, 30) ]); } diff --git a/zkevm-circuits/Cargo.toml b/zkevm-circuits/Cargo.toml index 1fc3c10801..3ba0770015 100644 --- a/zkevm-circuits/Cargo.toml +++ b/zkevm-circuits/Cargo.toml @@ -58,7 +58,7 @@ cli-table = "0.4" paste = "1.0" [features] -default = ["test", "test-circuits", "shanghai", "debug-annotations", "parallel_syn"] +default = ["test", "test-circuits", "shanghai", "debug-annotations", "parallel_syn", "enable-stack", "enable-storage"] test = ["ethers-signers", "mock", "bus-mapping/test"] scroll = ["bus-mapping/scroll", "eth-types/scroll", "mock?/scroll", "zktrie", "poseidon-codehash"] @@ -73,3 +73,7 @@ poseidon-codehash = [] parallel_syn = ["hash-circuit/parallel_syn", "halo2_proofs/parallel_syn"] debug-annotations = [] + +enable-stack = ["bus-mapping/enable-stack"] +enable-memory = ["bus-mapping/enable-memory"] +enable-storage = ["bus-mapping/enable-storage"] \ No newline at end of file