diff --git a/etc/env/file_based/genesis.yaml b/etc/env/file_based/genesis.yaml index 1b154b9e9ea..9617b011d2c 100644 --- a/etc/env/file_based/genesis.yaml +++ b/etc/env/file_based/genesis.yaml @@ -12,5 +12,5 @@ prover: dummy_verifier: true genesis_protocol_semantic_version: 0.25.0 l1_batch_commit_data_generator_mode: Rollup -# Uncomment to enable EVM emulation (requires to run genesis) +# TODO: uncomment once EVM emulator is present in the `contracts` submodule # evm_emulator_hash: 0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91 diff --git a/zkstack_cli/crates/config/src/chain.rs b/zkstack_cli/crates/config/src/chain.rs index 6c82d6ef3c3..c8fa0717dff 100644 --- a/zkstack_cli/crates/config/src/chain.rs +++ b/zkstack_cli/crates/config/src/chain.rs @@ -40,6 +40,8 @@ pub struct ChainConfigInternal { pub wallet_creation: WalletCreation, #[serde(skip_serializing_if = "Option::is_none")] pub legacy_bridge: Option, + #[serde(default)] // for backward compatibility + pub evm_emulator: bool, } /// Chain configuration file. This file is created in the chain @@ -61,6 +63,7 @@ pub struct ChainConfig { pub wallet_creation: WalletCreation, pub shell: OnceCell, pub legacy_bridge: Option, + pub evm_emulator: bool, } impl Serialize for ChainConfig { @@ -157,6 +160,7 @@ impl ChainConfig { base_token: self.base_token.clone(), wallet_creation: self.wallet_creation, legacy_bridge: self.legacy_bridge, + evm_emulator: self.evm_emulator, } } } diff --git a/zkstack_cli/crates/config/src/ecosystem.rs b/zkstack_cli/crates/config/src/ecosystem.rs index 79cb1c4ea27..c67aebf2a46 100644 --- a/zkstack_cli/crates/config/src/ecosystem.rs +++ b/zkstack_cli/crates/config/src/ecosystem.rs @@ -178,6 +178,7 @@ impl EcosystemConfig { .artifacts_path .unwrap_or_else(|| self.get_chain_artifacts_path(name)), legacy_bridge: config.legacy_bridge, + evm_emulator: config.evm_emulator, }) } @@ -232,7 +233,11 @@ impl EcosystemConfig { } pub fn get_default_configs_path(&self) -> PathBuf { - self.link_to_code.join(CONFIGS_PATH) + Self::default_configs_path(&self.link_to_code) + } + + pub fn default_configs_path(link_to_code: &Path) -> PathBuf { + link_to_code.join(CONFIGS_PATH) } /// Path to the predefined ecosystem configs diff --git a/zkstack_cli/crates/config/src/genesis.rs b/zkstack_cli/crates/config/src/genesis.rs index 933252541f4..2d9ac7fcdc6 100644 --- a/zkstack_cli/crates/config/src/genesis.rs +++ b/zkstack_cli/crates/config/src/genesis.rs @@ -1,5 +1,6 @@ use std::path::Path; +use anyhow::Context as _; use xshell::Shell; use zksync_basic_types::L1ChainId; pub use zksync_config::GenesisConfig; @@ -11,11 +12,23 @@ use crate::{ ChainConfig, }; -pub fn update_from_chain_config(genesis: &mut GenesisConfig, config: &ChainConfig) { +pub fn update_from_chain_config( + genesis: &mut GenesisConfig, + config: &ChainConfig, +) -> anyhow::Result<()> { genesis.l2_chain_id = config.chain_id; // TODO(EVM-676): for now, the settlement layer is always the same as the L1 network genesis.l1_chain_id = L1ChainId(config.l1_network.chain_id()); genesis.l1_batch_commit_data_generator_mode = config.l1_batch_commit_data_generator_mode; + genesis.evm_emulator_hash = if config.evm_emulator { + Some(genesis.evm_emulator_hash.context( + "impossible to initialize a chain with EVM emulator: the template genesis config \ + does not contain EVM emulator hash", + )?) + } else { + None + }; + Ok(()) } impl FileConfigWithDefaultName for GenesisConfig { diff --git a/zkstack_cli/crates/zkstack/completion/_zkstack.zsh b/zkstack_cli/crates/zkstack/completion/_zkstack.zsh index b985f5b9334..4df431754c8 100644 --- a/zkstack_cli/crates/zkstack/completion/_zkstack.zsh +++ b/zkstack_cli/crates/zkstack/completion/_zkstack.zsh @@ -81,6 +81,7 @@ in-file\:"Specify file with wallets"))' \ '--base-token-price-nominator=[Base token nominator]:BASE_TOKEN_PRICE_NOMINATOR: ' \ '--base-token-price-denominator=[Base token denominator]:BASE_TOKEN_PRICE_DENOMINATOR: ' \ '--set-as-default=[Set as default chain]' \ +'--evm-emulator=[Enable EVM emulator]' \ '--start-containers=[Start reth and postgres containers after creation]' \ '--chain=[Chain to use]:CHAIN: ' \ '--legacy-bridge[]' \ @@ -241,6 +242,7 @@ in-file\:"Specify file with wallets"))' \ '--base-token-price-nominator=[Base token nominator]:BASE_TOKEN_PRICE_NOMINATOR: ' \ '--base-token-price-denominator=[Base token denominator]:BASE_TOKEN_PRICE_DENOMINATOR: ' \ '--set-as-default=[Set as default chain]' \ +'--evm-emulator=[Enable EVM emulator]' \ '--chain=[Chain to use]:CHAIN: ' \ '--legacy-bridge[]' \ '-v[Verbose mode]' \ diff --git a/zkstack_cli/crates/zkstack/completion/zkstack.fish b/zkstack_cli/crates/zkstack/completion/zkstack.fish index f90bcf2c4ac..a1261082e6f 100644 --- a/zkstack_cli/crates/zkstack/completion/zkstack.fish +++ b/zkstack_cli/crates/zkstack/completion/zkstack.fish @@ -73,6 +73,7 @@ complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_se complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from create" -l base-token-price-nominator -d 'Base token nominator' -r complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from create" -l base-token-price-denominator -d 'Base token denominator' -r complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from create" -l set-as-default -d 'Set as default chain' -r -f -a "{true\t'',false\t''}" +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from create" -l evm-emulator -d 'Enable EVM emulator' -r -f -a "{true\t'',false\t''}" complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from create" -l start-containers -d 'Start reth and postgres containers after creation' -r -f -a "{true\t'',false\t''}" complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from create" -l chain -d 'Chain to use' -r complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from create" -l legacy-bridge @@ -156,6 +157,7 @@ complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_s complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from create" -l base-token-price-nominator -d 'Base token nominator' -r complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from create" -l base-token-price-denominator -d 'Base token denominator' -r complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from create" -l set-as-default -d 'Set as default chain' -r -f -a "{true\t'',false\t''}" +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from create" -l evm-emulator -d 'Enable EVM emulator' -r -f -a "{true\t'',false\t''}" complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from create" -l chain -d 'Chain to use' -r complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from create" -l legacy-bridge complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from create" -s v -l verbose -d 'Verbose mode' diff --git a/zkstack_cli/crates/zkstack/completion/zkstack.sh b/zkstack_cli/crates/zkstack/completion/zkstack.sh index d21480bba2c..7cdb20ae9aa 100644 --- a/zkstack_cli/crates/zkstack/completion/zkstack.sh +++ b/zkstack_cli/crates/zkstack/completion/zkstack.sh @@ -1162,7 +1162,7 @@ _zkstack() { return 0 ;; zkstack__chain__create) - opts="-v -h --chain-name --chain-id --prover-mode --wallet-creation --wallet-path --l1-batch-commit-data-generator-mode --base-token-address --base-token-price-nominator --base-token-price-denominator --set-as-default --legacy-bridge --verbose --chain --ignore-prerequisites --help" + opts="-v -h --chain-name --chain-id --prover-mode --wallet-creation --wallet-path --l1-batch-commit-data-generator-mode --base-token-address --base-token-price-nominator --base-token-price-denominator --set-as-default --legacy-bridge --evm-emulator --verbose --chain --ignore-prerequisites --help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1219,6 +1219,10 @@ _zkstack() { COMPREPLY=($(compgen -W "true false" -- "${cur}")) return 0 ;; + --evm-emulator) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; --chain) COMPREPLY=($(compgen -f "${cur}")) return 0 @@ -4643,7 +4647,7 @@ _zkstack() { return 0 ;; zkstack__ecosystem__create) - opts="-v -h --ecosystem-name --l1-network --link-to-code --chain-name --chain-id --prover-mode --wallet-creation --wallet-path --l1-batch-commit-data-generator-mode --base-token-address --base-token-price-nominator --base-token-price-denominator --set-as-default --legacy-bridge --start-containers --verbose --chain --ignore-prerequisites --help" + opts="-v -h --ecosystem-name --l1-network --link-to-code --chain-name --chain-id --prover-mode --wallet-creation --wallet-path --l1-batch-commit-data-generator-mode --base-token-address --base-token-price-nominator --base-token-price-denominator --set-as-default --legacy-bridge --evm-emulator --start-containers --verbose --chain --ignore-prerequisites --help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -4715,6 +4719,10 @@ _zkstack() { COMPREPLY=($(compgen -W "true false" -- "${cur}")) return 0 ;; + --evm-emulator) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; --start-containers) COMPREPLY=($(compgen -W "true false" -- "${cur}")) return 0 diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/args/create.rs b/zkstack_cli/crates/zkstack/src/commands/chain/args/create.rs index ccf64ad27ac..ae08d4712b3 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/args/create.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/args/create.rs @@ -1,14 +1,22 @@ -use std::{path::PathBuf, str::FromStr}; +use std::{ + path::{Path, PathBuf}, + str::FromStr, +}; use anyhow::{bail, Context}; use clap::{Parser, ValueEnum, ValueHint}; use common::{Prompt, PromptConfirm, PromptSelect}; -use config::forge_interface::deploy_ecosystem::output::Erc20Token; +use config::{ + forge_interface::deploy_ecosystem::output::Erc20Token, traits::ReadConfigWithBasePath, + EcosystemConfig, +}; use serde::{Deserialize, Serialize}; use slugify_rs::slugify; use strum::{Display, EnumIter, IntoEnumIterator}; use types::{BaseToken, L1BatchCommitmentMode, L1Network, ProverMode, WalletCreation}; +use xshell::Shell; use zksync_basic_types::H160; +use zksync_config::GenesisConfig; use crate::{ defaults::L2_CHAIN_ID, @@ -18,6 +26,7 @@ use crate::{ MSG_BASE_TOKEN_PRICE_DENOMINATOR_PROMPT, MSG_BASE_TOKEN_PRICE_NOMINATOR_HELP, MSG_BASE_TOKEN_PRICE_NOMINATOR_PROMPT, MSG_BASE_TOKEN_SELECTION_PROMPT, MSG_CHAIN_ID_HELP, MSG_CHAIN_ID_PROMPT, MSG_CHAIN_ID_VALIDATOR_ERR, MSG_CHAIN_NAME_PROMPT, + MSG_EVM_EMULATOR_HASH_MISSING_ERR, MSG_EVM_EMULATOR_HELP, MSG_EVM_EMULATOR_PROMPT, MSG_L1_BATCH_COMMIT_DATA_GENERATOR_MODE_PROMPT, MSG_L1_COMMIT_DATA_GENERATOR_MODE_HELP, MSG_NUMBER_VALIDATOR_GREATHER_THAN_ZERO_ERR, MSG_NUMBER_VALIDATOR_NOT_ZERO_ERR, MSG_PROVER_MODE_HELP, MSG_PROVER_VERSION_PROMPT, MSG_SET_AS_DEFAULT_HELP, @@ -67,14 +76,18 @@ pub struct ChainCreateArgs { pub(crate) set_as_default: Option, #[clap(long, default_value = "false")] pub(crate) legacy_bridge: bool, + #[arg(long, help = MSG_EVM_EMULATOR_HELP, default_missing_value = "true", num_args = 0..=1)] + evm_emulator: Option, } impl ChainCreateArgs { pub fn fill_values_with_prompt( self, + shell: &Shell, number_of_chains: u32, l1_network: &L1Network, possible_erc20: Vec, + link_to_code: &Path, ) -> anyhow::Result { let mut chain_name = self .chain_name @@ -211,6 +224,25 @@ impl ChainCreateArgs { } }; + let default_genesis_config = GenesisConfig::read_with_base_path( + shell, + EcosystemConfig::default_configs_path(link_to_code), + ) + .context("failed reading genesis config")?; + let has_evm_emulation_support = default_genesis_config.evm_emulator_hash.is_some(); + let evm_emulator = self.evm_emulator.unwrap_or_else(|| { + if !has_evm_emulation_support { + false + } else { + PromptConfirm::new(MSG_EVM_EMULATOR_PROMPT) + .default(false) + .ask() + } + }); + if !has_evm_emulation_support && evm_emulator { + bail!(MSG_EVM_EMULATOR_HASH_MISSING_ERR); + } + let set_as_default = self.set_as_default.unwrap_or_else(|| { PromptConfirm::new(MSG_SET_AS_DEFAULT_PROMPT) .default(true) @@ -227,6 +259,7 @@ impl ChainCreateArgs { base_token, set_as_default, legacy_bridge: self.legacy_bridge, + evm_emulator, }) } } @@ -242,6 +275,7 @@ pub struct ChainCreateArgsFinal { pub base_token: BaseToken, pub set_as_default: bool, pub legacy_bridge: bool, + pub evm_emulator: bool, } #[derive(Debug, Clone, EnumIter, Display, PartialEq, Eq)] diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/build_transactions.rs b/zkstack_cli/crates/zkstack/src/commands/chain/build_transactions.rs index 5f1be15231b..d3953c65659 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/build_transactions.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/build_transactions.rs @@ -42,7 +42,7 @@ pub(crate) async fn run(args: BuildTransactionsArgs, shell: &Shell) -> anyhow::R logger::note(MSG_SELECTED_CONFIG, logger::object_to_string(&chain_config)); let mut genesis_config = chain_config.get_genesis_config()?; - update_from_chain_config(&mut genesis_config, &chain_config); + update_from_chain_config(&mut genesis_config, &chain_config)?; // Copy ecosystem contracts let mut contracts_config = config diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/create.rs b/zkstack_cli/crates/zkstack/src/commands/chain/create.rs index 48a320ec27e..bdf5711e321 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/create.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/create.rs @@ -30,9 +30,11 @@ fn create( let tokens = ecosystem_config.get_erc20_tokens(); let args = args .fill_values_with_prompt( + shell, ecosystem_config.list_of_chains().len() as u32, &ecosystem_config.l1_network, tokens, + &ecosystem_config.link_to_code, ) .context(MSG_ARGS_VALIDATOR_ERR)?; @@ -89,6 +91,7 @@ pub(crate) fn create_chain_inner( wallet_creation: args.wallet_creation, shell: OnceCell::from(shell.clone()), legacy_bridge, + evm_emulator: args.evm_emulator, }; create_wallets( diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/init/configs.rs b/zkstack_cli/crates/zkstack/src/commands/chain/init/configs.rs index 82986d9b41a..31c5c681e7d 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/init/configs.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/init/configs.rs @@ -81,7 +81,7 @@ pub async fn init_configs( // Initialize genesis config let mut genesis_config = chain_config.get_genesis_config()?; - update_from_chain_config(&mut genesis_config, chain_config); + update_from_chain_config(&mut genesis_config, chain_config)?; genesis_config.save_with_base_path(shell, &chain_config.configs)?; // Initialize contracts config diff --git a/zkstack_cli/crates/zkstack/src/commands/ecosystem/args/create.rs b/zkstack_cli/crates/zkstack/src/commands/ecosystem/args/create.rs index 14cb5206f6a..6b6c1236d36 100644 --- a/zkstack_cli/crates/zkstack/src/commands/ecosystem/args/create.rs +++ b/zkstack_cli/crates/zkstack/src/commands/ecosystem/args/create.rs @@ -71,7 +71,13 @@ impl EcosystemCreateArgs { // Make the only chain as a default one self.chain.set_as_default = Some(true); - let chain = self.chain.fill_values_with_prompt(0, &l1_network, vec![])?; + let chain = self.chain.fill_values_with_prompt( + shell, + 0, + &l1_network, + vec![], + Path::new(&link_to_code), + )?; let start_containers = self.start_containers.unwrap_or_else(|| { PromptConfirm::new(MSG_START_CONTAINERS_PROMPT) diff --git a/zkstack_cli/crates/zkstack/src/commands/ecosystem/common.rs b/zkstack_cli/crates/zkstack/src/commands/ecosystem/common.rs index 42b8f79b97e..00d937bba29 100644 --- a/zkstack_cli/crates/zkstack/src/commands/ecosystem/common.rs +++ b/zkstack_cli/crates/zkstack/src/commands/ecosystem/common.rs @@ -28,7 +28,7 @@ pub async fn deploy_l1( let deploy_config_path = DEPLOY_ECOSYSTEM_SCRIPT_PARAMS.input(&config.link_to_code); let default_genesis_config = GenesisConfig::read_with_base_path(shell, config.get_default_configs_path()) - .context("Context")?; + .context("failed reading genesis config")?; let wallets_config = config.get_wallets()?; // For deploying ecosystem we only need genesis batch params diff --git a/zkstack_cli/crates/zkstack/src/messages.rs b/zkstack_cli/crates/zkstack/src/messages.rs index b9786dc4d8d..516194ef721 100644 --- a/zkstack_cli/crates/zkstack/src/messages.rs +++ b/zkstack_cli/crates/zkstack/src/messages.rs @@ -156,6 +156,7 @@ pub(super) const MSG_BASE_TOKEN_ADDRESS_HELP: &str = "Base token address"; pub(super) const MSG_BASE_TOKEN_PRICE_NOMINATOR_HELP: &str = "Base token nominator"; pub(super) const MSG_BASE_TOKEN_PRICE_DENOMINATOR_HELP: &str = "Base token denominator"; pub(super) const MSG_SET_AS_DEFAULT_HELP: &str = "Set as default chain"; +pub(super) const MSG_EVM_EMULATOR_HELP: &str = "Enable EVM emulator"; pub(super) const MSG_CHAIN_NAME_PROMPT: &str = "What do you want to name the chain?"; pub(super) const MSG_CHAIN_ID_PROMPT: &str = "What's the chain id?"; pub(super) const MSG_WALLET_CREATION_PROMPT: &str = "Select how do you want to create the wallet"; @@ -170,6 +171,7 @@ pub(super) const MSG_BASE_TOKEN_PRICE_NOMINATOR_PROMPT: &str = pub(super) const MSG_BASE_TOKEN_PRICE_DENOMINATOR_PROMPT: &str = "What is the base token price denominator?"; pub(super) const MSG_SET_AS_DEFAULT_PROMPT: &str = "Set this chain as default?"; +pub(super) const MSG_EVM_EMULATOR_PROMPT: &str = "Enable EVM emulator?"; pub(super) const MSG_WALLET_PATH_INVALID_ERR: &str = "Invalid path"; pub(super) const MSG_NUMBER_VALIDATOR_NOT_ZERO_ERR: &str = "Number is not zero"; pub(super) const MSG_NUMBER_VALIDATOR_GREATHER_THAN_ZERO_ERR: &str = @@ -184,6 +186,9 @@ pub(super) const MSG_WALLET_CREATION_VALIDATOR_ERR: &str = "Localhost wallet is not supported for external networks"; pub(super) const MSG_WALLET_TOKEN_MULTIPLIER_SETTER_NOT_FOUND: &str = "Token Multiplier Setter not found. Specify it in a wallet config"; +pub(super) const MSG_EVM_EMULATOR_HASH_MISSING_ERR: &str = + "Impossible to initialize a chain with EVM emulator: the template genesis config \ + does not contain EVM emulator hash"; /// Chain genesis related messages pub(super) const MSG_L1_SECRETS_MUST_BE_PRESENTED: &str = "L1 secret must be presented";