Skip to content

Commit

Permalink
feat(zk_toolbox): Make chain create independent from ecosystem (#3210)
Browse files Browse the repository at this point in the history
## What ❔

<!-- What are the changes this PR brings about? -->
<!-- Example: This PR adds a PR template to the repo. -->
<!-- (For bigger PRs adding more context is appreciated) -->

## Why ❔

<!-- Why are these changes done? What goal do they contribute to? What
are the principles behind them? -->
<!-- Example: PR templates ensure PR reviewers, observers, and future
iterators are in context about the evolution of repos. -->

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [ ] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [ ] Code has been formatted via `zkstack dev fmt` and `zkstack dev
lint`.
  • Loading branch information
matias-gonz authored Nov 26, 2024
1 parent b15b532 commit 19c46c6
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 48 deletions.
4 changes: 2 additions & 2 deletions zkstack_cli/crates/config/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub(crate) const LOCAL_APPS_PATH: &str = "apps/";
pub(crate) const LOCAL_CHAINS_PATH: &str = "chains/";
pub(crate) const LOCAL_CONFIGS_PATH: &str = "configs/";
pub(crate) const LOCAL_GENERATED_PATH: &str = ".generated/";
pub(crate) const LOCAL_DB_PATH: &str = "db/";
pub(crate) const LOCAL_ARTIFACTS_PATH: &str = "artifacts/";
pub const LOCAL_DB_PATH: &str = "db/";
pub const LOCAL_ARTIFACTS_PATH: &str = "artifacts/";

/// Name of apps config file
pub const APPS_CONFIG_FILE: &str = "apps.yaml";
Expand Down
2 changes: 1 addition & 1 deletion zkstack_cli/crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pub use zksync_protobuf_config::{encode_yaml_repr, read_yaml_repr};

mod apps;
mod chain;
mod consts;
mod contracts;
mod ecosystem;
mod file_config;
Expand All @@ -28,6 +27,7 @@ mod wallets;

pub mod consensus_config;
pub mod consensus_secrets;
pub mod consts;
pub mod docker_compose;
pub mod explorer;
pub mod explorer_compose;
Expand Down
2 changes: 2 additions & 0 deletions zkstack_cli/crates/zkstack/completion/_zkstack.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ in-file\:"Specify file with wallets"))' \
'--base-token-price-denominator=[Base token denominator]:BASE_TOKEN_PRICE_DENOMINATOR:_default' \
'--set-as-default=[Set as default chain]' \
'--evm-emulator=[Enable EVM emulator]' \
'--l1-network=[L1 Network]:L1_NETWORK:(localhost sepolia holesky mainnet)' \
'--start-containers=[Start reth and postgres containers after creation]' \
'--chain=[Chain to use]:CHAIN:_default' \
'--legacy-bridge[]' \
Expand Down Expand Up @@ -243,6 +244,7 @@ in-file\:"Specify file with wallets"))' \
'--base-token-price-denominator=[Base token denominator]:BASE_TOKEN_PRICE_DENOMINATOR:_default' \
'--set-as-default=[Set as default chain]' \
'--evm-emulator=[Enable EVM emulator]' \
'--l1-network=[L1 Network]:L1_NETWORK:(localhost sepolia holesky mainnet)' \
'--chain=[Chain to use]:CHAIN:_default' \
'--legacy-bridge[]' \
'-v[Verbose mode]' \
Expand Down
2 changes: 2 additions & 0 deletions zkstack_cli/crates/zkstack/completion/zkstack.fish
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,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-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 l1-network -d 'L1 Network' -r -f -a "{localhost\t'',sepolia\t'',holesky\t'',mainnet\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
Expand Down Expand Up @@ -159,6 +160,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-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 l1-network -d 'L1 Network' -r -f -a "{localhost\t'',sepolia\t'',holesky\t'',mainnet\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'
Expand Down
12 changes: 10 additions & 2 deletions zkstack_cli/crates/zkstack/completion/zkstack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1652,7 +1652,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 --evm-emulator --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 --l1-network --verbose --chain --ignore-prerequisites --help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
Expand Down Expand Up @@ -1713,6 +1713,10 @@ _zkstack() {
COMPREPLY=($(compgen -W "true false" -- "${cur}"))
return 0
;;
--l1-network)
COMPREPLY=($(compgen -W "localhost sepolia holesky mainnet" -- "${cur}"))
return 0
;;
--chain)
COMPREPLY=($(compgen -f "${cur}"))
return 0
Expand Down Expand Up @@ -5305,7 +5309,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 --evm-emulator --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 --l1-network --start-containers --verbose --chain --ignore-prerequisites --help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
Expand Down Expand Up @@ -5381,6 +5385,10 @@ _zkstack() {
COMPREPLY=($(compgen -W "true false" -- "${cur}"))
return 0
;;
--l1-network)
COMPREPLY=($(compgen -W "localhost sepolia holesky mainnet" -- "${cur}"))
return 0
;;
--start-containers)
COMPREPLY=($(compgen -W "true false" -- "${cur}"))
return 0
Expand Down
50 changes: 40 additions & 10 deletions zkstack_cli/crates/zkstack/src/commands/chain/args/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use serde::{Deserialize, Serialize};
use slugify_rs::slugify;
use strum::{Display, EnumIter, IntoEnumIterator};
use types::{BaseToken, L1BatchCommitmentMode, L1Network, ProverMode, WalletCreation};
use zksync_basic_types::H160;
use xshell::Shell;
use zksync_basic_types::{L2ChainId, H160};

use crate::{
defaults::L2_CHAIN_ID,
Expand All @@ -20,12 +21,13 @@ use crate::{
MSG_CHAIN_ID_PROMPT, MSG_CHAIN_ID_VALIDATOR_ERR, MSG_CHAIN_NAME_PROMPT,
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,
MSG_SET_AS_DEFAULT_PROMPT, MSG_WALLET_CREATION_HELP, MSG_WALLET_CREATION_PROMPT,
MSG_WALLET_CREATION_VALIDATOR_ERR, MSG_WALLET_PATH_HELP, MSG_WALLET_PATH_INVALID_ERR,
MSG_WALLET_PATH_PROMPT,
MSG_L1_NETWORK_HELP, MSG_L1_NETWORK_PROMPT, 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, MSG_SET_AS_DEFAULT_PROMPT, MSG_WALLET_CREATION_HELP,
MSG_WALLET_CREATION_PROMPT, MSG_WALLET_CREATION_VALIDATOR_ERR, MSG_WALLET_PATH_HELP,
MSG_WALLET_PATH_INVALID_ERR, MSG_WALLET_PATH_PROMPT,
},
utils::link_to_code::get_link_to_code,
};

// We need to duplicate it for using enum inside the arguments
Expand Down Expand Up @@ -70,21 +72,30 @@ pub struct ChainCreateArgs {
pub(crate) legacy_bridge: bool,
#[arg(long, help = MSG_EVM_EMULATOR_HELP, default_missing_value = "true", num_args = 0..=1)]
evm_emulator: Option<bool>,
#[clap(long, help = MSG_L1_NETWORK_HELP, value_enum)]
pub l1_network: Option<L1Network>,
}

impl ChainCreateArgs {
#[allow(clippy::too_many_arguments)]
pub fn fill_values_with_prompt(
self,
shell: &Shell,
number_of_chains: u32,
l1_network: &L1Network,
internal_id: u32,
l1_network: Option<L1Network>,
possible_erc20: Vec<Erc20Token>,
link_to_code: String,
link_to_code: Option<String>,
chains_path: Option<PathBuf>,
era_chain_id: L2ChainId,
) -> anyhow::Result<ChainCreateArgsFinal> {
let mut chain_name = self
.chain_name
.unwrap_or_else(|| Prompt::new(MSG_CHAIN_NAME_PROMPT).ask());
chain_name = slugify!(&chain_name, separator = "_");

let chain_path = chains_path.unwrap_or_default().join(&chain_name);

let chain_id = self
.chain_id
.map(|v| match v {
Expand All @@ -97,8 +108,14 @@ impl ChainCreateArgs {
.ask()
});

let l1_network = l1_network.unwrap_or_else(|| {
self.l1_network.unwrap_or_else(|| {
PromptSelect::new(MSG_L1_NETWORK_PROMPT, L1Network::iter()).ask()
})
});

let wallet_creation = if let Some(wallet) = self.wallet_creation {
if wallet == WalletCreation::Localhost && *l1_network != L1Network::Localhost {
if wallet == WalletCreation::Localhost && l1_network != L1Network::Localhost {
bail!(MSG_WALLET_CREATION_VALIDATOR_ERR);
} else {
wallet
Expand All @@ -108,7 +125,7 @@ impl ChainCreateArgs {
MSG_WALLET_CREATION_PROMPT,
WalletCreation::iter().filter(|wallet| {
// Disable localhost wallets for external networks
if *l1_network == L1Network::Localhost {
if l1_network == L1Network::Localhost {
true
} else {
*wallet != WalletCreation::Localhost
Expand Down Expand Up @@ -215,13 +232,18 @@ impl ChainCreateArgs {
}
};

let link_to_code = link_to_code.unwrap_or_else(|| get_link_to_code(shell));

let evm_emulator = self.evm_emulator.unwrap_or_else(|| {
PromptConfirm::new(MSG_EVM_EMULATOR_PROMPT)
.default(false)
.ask()
});

let set_as_default = self.set_as_default.unwrap_or_else(|| {
if number_of_chains == 0 {
return true;
}
PromptConfirm::new(MSG_SET_AS_DEFAULT_PROMPT)
.default(true)
.ask()
Expand All @@ -239,6 +261,10 @@ impl ChainCreateArgs {
legacy_bridge: self.legacy_bridge,
evm_emulator,
link_to_code,
chain_path,
era_chain_id,
internal_id,
l1_network,
})
}
}
Expand All @@ -256,6 +282,10 @@ pub struct ChainCreateArgsFinal {
pub legacy_bridge: bool,
pub evm_emulator: bool,
pub link_to_code: String,
pub chain_path: PathBuf,
pub era_chain_id: L2ChainId,
pub internal_id: u32,
pub l1_network: L1Network,
}

#[derive(Debug, Clone, EnumIter, Display, PartialEq, Eq)]
Expand Down
84 changes: 56 additions & 28 deletions zkstack_cli/crates/zkstack/src/commands/chain/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use std::cell::OnceCell;
use anyhow::Context;
use common::{logger, spinner::Spinner};
use config::{
create_local_configs_dir, create_wallets,
create_local_configs_dir, create_wallets, get_default_era_chain_id,
traits::{ReadConfigWithBasePath, SaveConfigWithBasePath},
zkstack_config::ZkStackConfig,
ChainConfig, EcosystemConfig, GenesisConfig,
ChainConfig, EcosystemConfig, GenesisConfig, LOCAL_ARTIFACTS_PATH, LOCAL_DB_PATH,
};
use xshell::Shell;
use zksync_basic_types::L2ChainId;
Expand All @@ -22,22 +22,49 @@ use crate::{
};

pub fn run(args: ChainCreateArgs, shell: &Shell) -> anyhow::Result<()> {
let mut ecosystem_config = ZkStackConfig::ecosystem(shell)?;
let mut ecosystem_config = ZkStackConfig::ecosystem(shell).ok();
create(args, &mut ecosystem_config, shell)
}

fn create(
args: ChainCreateArgs,
ecosystem_config: &mut EcosystemConfig,
ecosystem: &mut Option<EcosystemConfig>,
shell: &Shell,
) -> anyhow::Result<()> {
let tokens = ecosystem_config.get_erc20_tokens();
let possible_erc20 = ecosystem
.as_ref()
.map(|ecosystem| ecosystem.get_erc20_tokens())
.unwrap_or_default();

let number_of_chains = ecosystem
.as_ref()
.map(|ecosystem| ecosystem.list_of_chains().len() as u32)
.unwrap_or(0);

let internal_id = ecosystem.as_ref().map_or(0, |_| number_of_chains + 1);

let l1_network = ecosystem.as_ref().map(|ecosystem| ecosystem.l1_network);

let chains_path = ecosystem.as_ref().map(|ecosystem| ecosystem.chains.clone());
let era_chain_id = ecosystem
.as_ref()
.map(|ecosystem| ecosystem.era_chain_id)
.unwrap_or(get_default_era_chain_id());

let link_to_code = ecosystem
.as_ref()
.map(|ecosystem| ecosystem.link_to_code.clone().display().to_string());

let args = args
.fill_values_with_prompt(
ecosystem_config.list_of_chains().len() as u32,
&ecosystem_config.l1_network,
tokens,
ecosystem_config.link_to_code.clone().display().to_string(),
shell,
number_of_chains,
internal_id,
l1_network,
possible_erc20,
link_to_code,
chains_path,
era_chain_id,
)
.context(MSG_ARGS_VALIDATOR_ERR)?;

Expand All @@ -47,10 +74,14 @@ fn create(
let spinner = Spinner::new(MSG_CREATING_CHAIN_CONFIGURATIONS_SPINNER);
let name = args.chain_name.clone();
let set_as_default = args.set_as_default;
create_chain_inner(args, ecosystem_config, shell)?;
if set_as_default {
ecosystem_config.default_chain = name;
ecosystem_config.save_with_base_path(shell, ".")?;

create_chain_inner(args, shell)?;

if let Some(ecosystem) = ecosystem.as_mut() {
if set_as_default {
ecosystem.default_chain = name;
ecosystem.save_with_base_path(shell, ".")?;
}
}
spinner.finish();

Expand All @@ -59,24 +90,19 @@ fn create(
Ok(())
}

pub(crate) fn create_chain_inner(
args: ChainCreateArgsFinal,
ecosystem_config: &EcosystemConfig,
shell: &Shell,
) -> anyhow::Result<()> {
pub(crate) fn create_chain_inner(args: ChainCreateArgsFinal, shell: &Shell) -> anyhow::Result<()> {
if args.legacy_bridge {
logger::warn("WARNING!!! You are creating a chain with legacy bridge, use it only for testing compatibility")
}
let default_chain_name = args.chain_name.clone();
let chain_path = ecosystem_config.chains.join(&default_chain_name);
let chain_path = args.chain_path;
let chain_configs_path = create_local_configs_dir(shell, &chain_path)?;
let (chain_id, legacy_bridge) = if args.legacy_bridge {
// Legacy bridge is distinguished by using the same chain id as ecosystem
(ecosystem_config.era_chain_id, Some(true))
(args.era_chain_id, Some(true))
} else {
(L2ChainId::from(args.chain_id), None)
};
let internal_id = ecosystem_config.list_of_chains().len() as u32;
let link_to_code = resolve_link_to_code(shell, chain_path.clone(), args.link_to_code.clone())?;
let default_genesis_config = GenesisConfig::read_with_base_path(
shell,
Expand All @@ -86,16 +112,18 @@ pub(crate) fn create_chain_inner(
if args.evm_emulator && !has_evm_emulation_support {
anyhow::bail!(MSG_EVM_EMULATOR_HASH_MISSING_ERR);
}
let rocks_db_path = chain_path.join(LOCAL_DB_PATH);
let artifacts = chain_path.join(LOCAL_ARTIFACTS_PATH);

let chain_config = ChainConfig {
id: internal_id,
id: args.internal_id,
name: default_chain_name.clone(),
chain_id,
prover_version: args.prover_version,
l1_network: ecosystem_config.l1_network,
link_to_code: ecosystem_config.link_to_code.clone(),
rocks_db_path: ecosystem_config.get_chain_rocks_db_path(&default_chain_name),
artifacts: ecosystem_config.get_chain_artifacts_path(&default_chain_name),
l1_network: args.l1_network,
link_to_code: link_to_code.clone(),
rocks_db_path,
artifacts,
configs: chain_configs_path.clone(),
external_node_config_path: None,
l1_batch_commit_data_generator_mode: args.l1_batch_commit_data_generator_mode,
Expand All @@ -109,8 +137,8 @@ pub(crate) fn create_chain_inner(
create_wallets(
shell,
&chain_config.configs,
&ecosystem_config.link_to_code,
internal_id,
&link_to_code,
args.internal_id,
args.wallet_creation,
args.wallet_path,
)?;
Expand Down
Loading

0 comments on commit 19c46c6

Please sign in to comment.