From 007468286faf790d9cf69af556a9a3ddab90ab3b Mon Sep 17 00:00:00 2001 From: Manuel Mauro Date: Thu, 1 Aug 2024 11:59:42 +0200 Subject: [PATCH 1/6] feat: allow to run `zk_inception chain create` non-interactively --- .../src/commands/chain/args/create.rs | 145 ++++++++++++------ .../crates/zk_inception/src/messages.rs | 1 + 2 files changed, 98 insertions(+), 48 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs b/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs index 63f3a3736cd7..7a1c39086e1e 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs @@ -6,6 +6,7 @@ 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 crate::{ defaults::L2_CHAIN_ID, @@ -13,12 +14,13 @@ use crate::{ MSG_BASE_TOKEN_ADDRESS_HELP, MSG_BASE_TOKEN_ADDRESS_PROMPT, MSG_BASE_TOKEN_PRICE_DENOMINATOR_HELP, 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_PROMPT, MSG_CHAIN_NAME_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_PATH_HELP, MSG_WALLET_PATH_INVALID_ERR, MSG_WALLET_PATH_PROMPT, + MSG_BASE_TOKEN_SELECTION_PROMPT, MSG_CHAIN_ID_HELP, MSG_CHAIN_ID_PROMPT, + MSG_CHAIN_NAME_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_PATH_HELP, MSG_WALLET_PATH_INVALID_ERR, + MSG_WALLET_PATH_PROMPT, }, }; @@ -42,7 +44,7 @@ impl From for L1BatchCommitmentMode { pub struct ChainCreateArgs { #[arg(long)] chain_name: Option, - #[arg(value_parser = clap::value_parser ! (u32).range(1..))] + #[clap(long, help = MSG_CHAIN_ID_HELP)] chain_id: Option, #[clap(long, help = MSG_PROVER_MODE_HELP, value_enum)] prover_mode: Option, @@ -73,26 +75,39 @@ impl ChainCreateArgs { .unwrap_or_else(|| Prompt::new(MSG_CHAIN_NAME_PROMPT).ask()); chain_name = slugify!(&chain_name, separator = "_"); - let chain_id = self.chain_id.unwrap_or_else(|| { - Prompt::new(MSG_CHAIN_ID_PROMPT) - .default(&(L2_CHAIN_ID + number_of_chains).to_string()) - .ask() + let chain_id = self + .chain_id + .map(|v| { + (v == 0) + .then(|| L2_CHAIN_ID + number_of_chains) + .unwrap_or(v) + }) + .unwrap_or_else(|| { + Prompt::new(MSG_CHAIN_ID_PROMPT) + .default(&(L2_CHAIN_ID + number_of_chains).to_string()) + .ask() + }); + + // NOTE: should check if the option submitted is compatible with the network, but with the + // current function signature we can't return an error + let wallet_creation = self.wallet_creation.unwrap_or_else(|| { + PromptSelect::new( + MSG_WALLET_CREATION_PROMPT, + WalletCreation::iter().filter(|wallet| { + // Disable localhost wallets for external networks + if l1_network == &L1Network::Localhost { + true + } else { + wallet != &WalletCreation::Localhost + } + }), + ) + .ask() }); - let wallet_creation = PromptSelect::new( - MSG_WALLET_CREATION_PROMPT, - WalletCreation::iter().filter(|wallet| { - // Disable localhost wallets for external networks - if l1_network == &L1Network::Localhost { - true - } else { - wallet != &WalletCreation::Localhost - } - }), - ) - .ask(); - - let prover_version = PromptSelect::new(MSG_PROVER_VERSION_PROMPT, ProverMode::iter()).ask(); + let prover_version = self.prover_mode.unwrap_or_else(|| { + PromptSelect::new(MSG_PROVER_VERSION_PROMPT, ProverMode::iter()).ask() + }); let l1_batch_commit_data_generator_mode = PromptSelect::new( MSG_L1_BATCH_COMMIT_DATA_GENERATOR_MODE_PROMPT, @@ -114,32 +129,56 @@ impl ChainCreateArgs { None }; - let base_token_selection = - PromptSelect::new(MSG_BASE_TOKEN_SELECTION_PROMPT, BaseTokenSelection::iter()).ask(); - let base_token = match base_token_selection { - BaseTokenSelection::Eth => BaseToken::eth(), - BaseTokenSelection::Custom => { - let number_validator = |val: &String| -> Result<(), String> { - let Ok(val) = val.parse::() else { - return Err(MSG_NUMBER_VALIDATOR_NOT_ZERO_ERR.to_string()); - }; - if val == 0 { - return Err(MSG_NUMBER_VALIDATOR_GREATHER_THAN_ZERO_ERR.to_string()); + let base_token = if self.base_token_address.is_none() + && self.base_token_price_denominator.is_none() + && self.base_token_price_nominator.is_none() + { + let base_token_selection = + PromptSelect::new(MSG_BASE_TOKEN_SELECTION_PROMPT, BaseTokenSelection::iter()) + .ask(); + + match base_token_selection { + BaseTokenSelection::Eth => BaseToken::eth(), + BaseTokenSelection::Custom => { + let address = Prompt::new(MSG_BASE_TOKEN_ADDRESS_PROMPT).ask(); + let nominator = Prompt::new(MSG_BASE_TOKEN_PRICE_NOMINATOR_PROMPT) + .validate_with(number_validator) + .ask(); + let denominator = Prompt::new(MSG_BASE_TOKEN_PRICE_DENOMINATOR_PROMPT) + .validate_with(number_validator) + .ask(); + BaseToken { + address, + nominator, + denominator, } - Ok(()) - }; - let address = Prompt::new(MSG_BASE_TOKEN_ADDRESS_PROMPT).ask(); - let nominator = Prompt::new(MSG_BASE_TOKEN_PRICE_NOMINATOR_PROMPT) + } + } + } else { + let address = self + .base_token_address + .map(|s| { + // NOTE: here would be better to return error, but the current function + // signature does not allow that. + H160::from_str(&s).ok() + }) + .flatten() + .unwrap_or_else(|| Prompt::new(MSG_BASE_TOKEN_ADDRESS_PROMPT).ask()); + let nominator = self.base_token_price_nominator.unwrap_or_else(|| { + Prompt::new(MSG_BASE_TOKEN_PRICE_NOMINATOR_PROMPT) .validate_with(number_validator) - .ask(); - let denominator = Prompt::new(MSG_BASE_TOKEN_PRICE_DENOMINATOR_PROMPT) + .ask() + }); + let denominator = self.base_token_price_denominator.unwrap_or_else(|| { + Prompt::new(MSG_BASE_TOKEN_PRICE_DENOMINATOR_PROMPT) .validate_with(number_validator) - .ask(); - BaseToken { - address, - nominator, - denominator, - } + .ask() + }); + + BaseToken { + address, + nominator, + denominator, } }; @@ -179,3 +218,13 @@ enum BaseTokenSelection { Eth, Custom, } + +fn number_validator(val: &String) -> Result<(), String> { + let Ok(val) = val.parse::() else { + return Err(MSG_NUMBER_VALIDATOR_NOT_ZERO_ERR.to_string()); + }; + if val == 0 { + return Err(MSG_NUMBER_VALIDATOR_GREATHER_THAN_ZERO_ERR.to_string()); + } + Ok(()) +} diff --git a/zk_toolbox/crates/zk_inception/src/messages.rs b/zk_toolbox/crates/zk_inception/src/messages.rs index 6e93aa4d7e9b..2b3435e90d8d 100644 --- a/zk_toolbox/crates/zk_inception/src/messages.rs +++ b/zk_toolbox/crates/zk_inception/src/messages.rs @@ -103,6 +103,7 @@ pub(super) fn msg_chain_doesnt_exist_err(chain_name: &str, chains: &Vec) /// Chain create related messages pub(super) const MSG_PROVER_MODE_HELP: &str = "Prover options"; +pub(super) const MSG_CHAIN_ID_HELP: &str = "Chain ID. [if 0 a default chain id will be generated]"; pub(super) const MSG_WALLET_CREATION_HELP: &str = "Wallet options"; pub(super) const MSG_WALLET_PATH_HELP: &str = "Wallet path"; pub(super) const MSG_L1_COMMIT_DATA_GENERATOR_MODE_HELP: &str = "Commit data generation mode"; From dcfa4c25213253cc5d153d8717c7b16eaa71e29e Mon Sep 17 00:00:00 2001 From: Manuel Mauro Date: Fri, 2 Aug 2024 15:45:16 +0200 Subject: [PATCH 2/6] feat: create custom chain in CI integration test --- .github/workflows/ci-zk-toolbox-reusable.yml | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/ci-zk-toolbox-reusable.yml b/.github/workflows/ci-zk-toolbox-reusable.yml index 7e6ab2df5bb4..0d9ec607873a 100644 --- a/.github/workflows/ci-zk-toolbox-reusable.yml +++ b/.github/workflows/ci-zk-toolbox-reusable.yml @@ -104,6 +104,27 @@ jobs: --prover-db-name=zksync_prover_localhost_era \ --ignore-prerequisites --verbose + - name: Create and initialize chain + run: | + ci_run zk_inception chain create \ + --chain-name chain_rollup \ + --chain-id 0 \ + --prover-mode no-proofs \ + --wallet-creation localhost \ + --l1-batch-commit-data-generator-mode rollup \ + --base-token-address 0x0000000000000000000000000000000000000001 \ + --base-token-price-nominator 1 \ + --base-token-price-denominator 1 \ + --set-as-default true \ + --ignore-prerequisites + ci_run zk_inception chain init \ + --deploy-paymaster \ + --l1-rpc-url=http://reth:8545 \ + --server-db-url=postgres://postgres:notsecurepassword@postgres:5432 \ + --server-db-name=zksync_server_localhost_rollup \ + --prover-db-url=postgres://postgres:notsecurepassword@postgres:5432 \ + --prover-db-name=zksync_prover_localhost_rollup + - name: Run server run: | ci_run zk_inception server --ignore-prerequisites &>server.log & From d6980c47eed8062f1c26e1518adec5df335a1188 Mon Sep 17 00:00:00 2001 From: Manuel Mauro Date: Fri, 2 Aug 2024 15:53:09 +0200 Subject: [PATCH 3/6] fix: fix network naming --- core/tests/ts-integration/src/env.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tests/ts-integration/src/env.ts b/core/tests/ts-integration/src/env.ts index cb2638929d05..6b48387f90d2 100644 --- a/core/tests/ts-integration/src/env.ts +++ b/core/tests/ts-integration/src/env.ts @@ -72,7 +72,7 @@ async function loadTestEnvironmentFromFile(chain: string): Promise Date: Fri, 2 Aug 2024 16:44:07 +0200 Subject: [PATCH 4/6] feat: add ChainId argument type --- .github/workflows/ci-zk-toolbox-reusable.yml | 2 +- .../src/commands/chain/args/create.rs | 55 ++++++++++++------- .../crates/zk_inception/src/messages.rs | 1 + 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci-zk-toolbox-reusable.yml b/.github/workflows/ci-zk-toolbox-reusable.yml index 0d9ec607873a..579260bf57c8 100644 --- a/.github/workflows/ci-zk-toolbox-reusable.yml +++ b/.github/workflows/ci-zk-toolbox-reusable.yml @@ -108,7 +108,7 @@ jobs: run: | ci_run zk_inception chain create \ --chain-name chain_rollup \ - --chain-id 0 \ + --chain-id sequential \ --prover-mode no-proofs \ --wallet-creation localhost \ --l1-batch-commit-data-generator-mode rollup \ diff --git a/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs b/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs index 7a1c39086e1e..b938113c28f5 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs @@ -15,12 +15,12 @@ use crate::{ MSG_BASE_TOKEN_PRICE_DENOMINATOR_HELP, 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_NAME_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_PATH_HELP, MSG_WALLET_PATH_INVALID_ERR, - MSG_WALLET_PATH_PROMPT, + MSG_CHAIN_ID_VALIDATOR_ERR, MSG_CHAIN_NAME_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_PATH_HELP, MSG_WALLET_PATH_INVALID_ERR, MSG_WALLET_PATH_PROMPT, }, }; @@ -45,7 +45,7 @@ pub struct ChainCreateArgs { #[arg(long)] chain_name: Option, #[clap(long, help = MSG_CHAIN_ID_HELP)] - chain_id: Option, + chain_id: Option, #[clap(long, help = MSG_PROVER_MODE_HELP, value_enum)] prover_mode: Option, #[clap(long, help = MSG_WALLET_CREATION_HELP, value_enum)] @@ -77,10 +77,9 @@ impl ChainCreateArgs { let chain_id = self .chain_id - .map(|v| { - (v == 0) - .then(|| L2_CHAIN_ID + number_of_chains) - .unwrap_or(v) + .map(|v| match v { + ChainId::Sequential => L2_CHAIN_ID + number_of_chains, + ChainId::Id(v) => v, }) .unwrap_or_else(|| { Prompt::new(MSG_CHAIN_ID_PROMPT) @@ -129,6 +128,16 @@ impl ChainCreateArgs { None }; + let number_validator = |val: &String| -> Result<(), String> { + let Ok(val) = val.parse::() else { + return Err(MSG_NUMBER_VALIDATOR_NOT_ZERO_ERR.to_string()); + }; + if val == 0 { + return Err(MSG_NUMBER_VALIDATOR_GREATHER_THAN_ZERO_ERR.to_string()); + } + Ok(()) + }; + let base_token = if self.base_token_address.is_none() && self.base_token_price_denominator.is_none() && self.base_token_price_nominator.is_none() @@ -157,12 +166,11 @@ impl ChainCreateArgs { } else { let address = self .base_token_address - .map(|s| { + .and_then(|s| { // NOTE: here would be better to return error, but the current function // signature does not allow that. H160::from_str(&s).ok() }) - .flatten() .unwrap_or_else(|| Prompt::new(MSG_BASE_TOKEN_ADDRESS_PROMPT).ask()); let nominator = self.base_token_price_nominator.unwrap_or_else(|| { Prompt::new(MSG_BASE_TOKEN_PRICE_NOMINATOR_PROMPT) @@ -219,12 +227,19 @@ enum BaseTokenSelection { Custom, } -fn number_validator(val: &String) -> Result<(), String> { - let Ok(val) = val.parse::() else { - return Err(MSG_NUMBER_VALIDATOR_NOT_ZERO_ERR.to_string()); - }; - if val == 0 { - return Err(MSG_NUMBER_VALIDATOR_GREATHER_THAN_ZERO_ERR.to_string()); +#[derive(Clone, Debug, Serialize, Deserialize)] +enum ChainId { + Sequential, + Id(u32), +} + +impl FromStr for ChainId { + type Err = String; + + fn from_str(s: &str) -> Result { + (s == "sequential") + .then(|| ChainId::Sequential) + .or_else(|| s.parse::().ok().map(ChainId::Id)) + .ok_or_else(|| MSG_CHAIN_ID_VALIDATOR_ERR.to_string()) } - Ok(()) } diff --git a/zk_toolbox/crates/zk_inception/src/messages.rs b/zk_toolbox/crates/zk_inception/src/messages.rs index 2b3435e90d8d..be3fab152ae5 100644 --- a/zk_toolbox/crates/zk_inception/src/messages.rs +++ b/zk_toolbox/crates/zk_inception/src/messages.rs @@ -133,6 +133,7 @@ pub(super) const MSG_CREATING_CHAIN: &str = "Creating chain"; pub(super) const MSG_CHAIN_CREATED: &str = "Chain created successfully"; pub(super) const MSG_CREATING_CHAIN_CONFIGURATIONS_SPINNER: &str = "Creating chain configurations..."; +pub(super) const MSG_CHAIN_ID_VALIDATOR_ERR: &str = "Invalid chain id"; /// Chain genesis related messages pub(super) const MSG_L1_SECRETS_MUST_BE_PRESENTED: &str = "L1 secret must be presented"; From 3837851c8a2ff1f8b41ae4497aebc53986072e1a Mon Sep 17 00:00:00 2001 From: Manuel Mauro Date: Fri, 2 Aug 2024 17:32:35 +0200 Subject: [PATCH 5/6] refactor: format --- .github/workflows/ci-zk-toolbox-reusable.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-zk-toolbox-reusable.yml b/.github/workflows/ci-zk-toolbox-reusable.yml index 579260bf57c8..610156a591a7 100644 --- a/.github/workflows/ci-zk-toolbox-reusable.yml +++ b/.github/workflows/ci-zk-toolbox-reusable.yml @@ -117,6 +117,7 @@ jobs: --base-token-price-denominator 1 \ --set-as-default true \ --ignore-prerequisites + ci_run zk_inception chain init \ --deploy-paymaster \ --l1-rpc-url=http://reth:8545 \ From 3bac613bacd434957f23cd0c1a9728d3c776d9b4 Mon Sep 17 00:00:00 2001 From: Manuel Mauro Date: Fri, 2 Aug 2024 17:51:44 +0200 Subject: [PATCH 6/6] feat: make fill_values_with_prompt fallible --- .../src/commands/chain/args/create.rs | 63 ++++++++++--------- .../zk_inception/src/commands/chain/create.rs | 15 +++-- .../src/commands/ecosystem/args/create.rs | 11 ++-- .../src/commands/ecosystem/create.rs | 14 +++-- .../crates/zk_inception/src/messages.rs | 6 +- 5 files changed, 64 insertions(+), 45 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs b/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs index b938113c28f5..3ccc737acc49 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs @@ -1,5 +1,6 @@ use std::{path::PathBuf, str::FromStr}; +use anyhow::{bail, Context}; use clap::{Parser, ValueEnum}; use common::{Prompt, PromptConfirm, PromptSelect}; use serde::{Deserialize, Serialize}; @@ -12,15 +13,16 @@ use crate::{ defaults::L2_CHAIN_ID, messages::{ MSG_BASE_TOKEN_ADDRESS_HELP, MSG_BASE_TOKEN_ADDRESS_PROMPT, - MSG_BASE_TOKEN_PRICE_DENOMINATOR_HELP, 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_BASE_TOKEN_ADDRESS_VALIDATOR_ERR, MSG_BASE_TOKEN_PRICE_DENOMINATOR_HELP, + 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_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_PATH_HELP, MSG_WALLET_PATH_INVALID_ERR, MSG_WALLET_PATH_PROMPT, + MSG_WALLET_CREATION_VALIDATOR_ERR, MSG_WALLET_PATH_HELP, MSG_WALLET_PATH_INVALID_ERR, + MSG_WALLET_PATH_PROMPT, }, }; @@ -69,7 +71,7 @@ impl ChainCreateArgs { self, number_of_chains: u32, l1_network: &L1Network, - ) -> ChainCreateArgsFinal { + ) -> anyhow::Result { let mut chain_name = self .chain_name .unwrap_or_else(|| Prompt::new(MSG_CHAIN_NAME_PROMPT).ask()); @@ -87,32 +89,39 @@ impl ChainCreateArgs { .ask() }); - // NOTE: should check if the option submitted is compatible with the network, but with the - // current function signature we can't return an error - let wallet_creation = self.wallet_creation.unwrap_or_else(|| { + let wallet_creation = if let Some(wallet) = self.wallet_creation { + if wallet == WalletCreation::Localhost && *l1_network != L1Network::Localhost { + bail!(MSG_WALLET_CREATION_VALIDATOR_ERR); + } else { + wallet + } + } else { PromptSelect::new( 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 + *wallet != WalletCreation::Localhost } }), ) .ask() - }); + }; let prover_version = self.prover_mode.unwrap_or_else(|| { PromptSelect::new(MSG_PROVER_VERSION_PROMPT, ProverMode::iter()).ask() }); - let l1_batch_commit_data_generator_mode = PromptSelect::new( - MSG_L1_BATCH_COMMIT_DATA_GENERATOR_MODE_PROMPT, - L1BatchCommitmentModeInternal::iter(), - ) - .ask(); + let l1_batch_commit_data_generator_mode = + self.l1_batch_commit_data_generator_mode.unwrap_or_else(|| { + PromptSelect::new( + MSG_L1_BATCH_COMMIT_DATA_GENERATOR_MODE_PROMPT, + L1BatchCommitmentModeInternal::iter(), + ) + .ask() + }); let wallet_path: Option = if self.wallet_creation == Some(WalletCreation::InFile) { Some(self.wallet_path.unwrap_or_else(|| { @@ -164,14 +173,12 @@ impl ChainCreateArgs { } } } else { - let address = self - .base_token_address - .and_then(|s| { - // NOTE: here would be better to return error, but the current function - // signature does not allow that. - H160::from_str(&s).ok() - }) - .unwrap_or_else(|| Prompt::new(MSG_BASE_TOKEN_ADDRESS_PROMPT).ask()); + let address = if let Some(address) = self.base_token_address { + H160::from_str(&address).context(MSG_BASE_TOKEN_ADDRESS_VALIDATOR_ERR)? + } else { + Prompt::new(MSG_BASE_TOKEN_ADDRESS_PROMPT).ask() + }; + let nominator = self.base_token_price_nominator.unwrap_or_else(|| { Prompt::new(MSG_BASE_TOKEN_PRICE_NOMINATOR_PROMPT) .validate_with(number_validator) @@ -196,7 +203,7 @@ impl ChainCreateArgs { .ask() }); - ChainCreateArgsFinal { + Ok(ChainCreateArgsFinal { chain_name, chain_id, prover_version, @@ -205,7 +212,7 @@ impl ChainCreateArgs { wallet_path, base_token, set_as_default, - } + }) } } @@ -238,7 +245,7 @@ impl FromStr for ChainId { fn from_str(s: &str) -> Result { (s == "sequential") - .then(|| ChainId::Sequential) + .then_some(ChainId::Sequential) .or_else(|| s.parse::().ok().map(ChainId::Id)) .ok_or_else(|| MSG_CHAIN_ID_VALIDATOR_ERR.to_string()) } diff --git a/zk_toolbox/crates/zk_inception/src/commands/chain/create.rs b/zk_toolbox/crates/zk_inception/src/commands/chain/create.rs index 70f4442cca62..7e20ae449a8a 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/chain/create.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/chain/create.rs @@ -1,5 +1,6 @@ use std::cell::OnceCell; +use anyhow::Context; use common::{logger, spinner::Spinner}; use config::{ create_local_configs_dir, create_wallets, traits::SaveConfigWithBasePath, ChainConfig, @@ -11,8 +12,8 @@ use zksync_basic_types::L2ChainId; use crate::{ commands::chain::args::create::{ChainCreateArgs, ChainCreateArgsFinal}, messages::{ - MSG_CHAIN_CREATED, MSG_CREATING_CHAIN, MSG_CREATING_CHAIN_CONFIGURATIONS_SPINNER, - MSG_SELECTED_CONFIG, + MSG_ARGS_VALIDATOR_ERR, MSG_CHAIN_CREATED, MSG_CREATING_CHAIN, + MSG_CREATING_CHAIN_CONFIGURATIONS_SPINNER, MSG_SELECTED_CONFIG, }, }; @@ -26,10 +27,12 @@ fn create( ecosystem_config: &mut EcosystemConfig, shell: &Shell, ) -> anyhow::Result<()> { - let args = args.fill_values_with_prompt( - ecosystem_config.list_of_chains().len() as u32, - &ecosystem_config.l1_network, - ); + let args = args + .fill_values_with_prompt( + ecosystem_config.list_of_chains().len() as u32, + &ecosystem_config.l1_network, + ) + .context(MSG_ARGS_VALIDATOR_ERR)?; logger::note(MSG_SELECTED_CONFIG, logger::object_to_string(&args)); logger::info(MSG_CREATING_CHAIN); diff --git a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs index 746558dd4e97..05fe43dc5e96 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs @@ -38,7 +38,10 @@ pub struct EcosystemCreateArgs { } impl EcosystemCreateArgs { - pub fn fill_values_with_prompt(mut self, shell: &Shell) -> EcosystemCreateArgsFinal { + pub fn fill_values_with_prompt( + mut self, + shell: &Shell, + ) -> anyhow::Result { let mut ecosystem_name = self .ecosystem_name .unwrap_or_else(|| Prompt::new(MSG_ECOSYSTEM_NAME_PROMPT).ask()); @@ -67,7 +70,7 @@ 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); + let chain = self.chain.fill_values_with_prompt(0, &l1_network)?; let start_containers = self.start_containers.unwrap_or_else(|| { PromptConfirm::new(MSG_START_CONTAINERS_PROMPT) @@ -75,7 +78,7 @@ impl EcosystemCreateArgs { .ask() }); - EcosystemCreateArgsFinal { + Ok(EcosystemCreateArgsFinal { ecosystem_name, l1_network, link_to_code, @@ -83,7 +86,7 @@ impl EcosystemCreateArgs { wallet_path: chain.wallet_path.clone(), chain_args: chain, start_containers, - } + }) } } diff --git a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/create.rs b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/create.rs index 2d4f7b3f25d9..f9940c8a9798 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/create.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/create.rs @@ -1,6 +1,6 @@ use std::{path::PathBuf, str::FromStr}; -use anyhow::bail; +use anyhow::{bail, Context}; use common::{git, logger, spinner::Spinner}; use config::{ create_local_configs_dir, create_wallets, get_default_era_chain_id, @@ -19,10 +19,10 @@ use crate::{ }, }, messages::{ - msg_created_ecosystem, MSG_CLONING_ERA_REPO_SPINNER, MSG_CREATING_DEFAULT_CHAIN_SPINNER, - MSG_CREATING_ECOSYSTEM, MSG_CREATING_INITIAL_CONFIGURATIONS_SPINNER, - MSG_ECOSYSTEM_ALREADY_EXISTS_ERR, MSG_ECOSYSTEM_CONFIG_INVALID_ERR, MSG_SELECTED_CONFIG, - MSG_STARTING_CONTAINERS_SPINNER, + msg_created_ecosystem, MSG_ARGS_VALIDATOR_ERR, MSG_CLONING_ERA_REPO_SPINNER, + MSG_CREATING_DEFAULT_CHAIN_SPINNER, MSG_CREATING_ECOSYSTEM, + MSG_CREATING_INITIAL_CONFIGURATIONS_SPINNER, MSG_ECOSYSTEM_ALREADY_EXISTS_ERR, + MSG_ECOSYSTEM_CONFIG_INVALID_ERR, MSG_SELECTED_CONFIG, MSG_STARTING_CONTAINERS_SPINNER, }, }; @@ -39,7 +39,9 @@ pub fn run(args: EcosystemCreateArgs, shell: &Shell) -> anyhow::Result<()> { } fn create(args: EcosystemCreateArgs, shell: &Shell) -> anyhow::Result<()> { - let args = args.fill_values_with_prompt(shell); + let args = args + .fill_values_with_prompt(shell) + .context(MSG_ARGS_VALIDATOR_ERR)?; logger::note(MSG_SELECTED_CONFIG, logger::object_to_string(&args)); logger::info(MSG_CREATING_ECOSYSTEM); diff --git a/zk_toolbox/crates/zk_inception/src/messages.rs b/zk_toolbox/crates/zk_inception/src/messages.rs index be3fab152ae5..b52d7aec2167 100644 --- a/zk_toolbox/crates/zk_inception/src/messages.rs +++ b/zk_toolbox/crates/zk_inception/src/messages.rs @@ -9,6 +9,7 @@ use ethers::{ pub(super) const MSG_SELECTED_CONFIG: &str = "Selected config"; pub(super) const MSG_CHAIN_NOT_INITIALIZED: &str = "Chain not initialized. Please create a chain first"; +pub(super) const MSG_ARGS_VALIDATOR_ERR: &str = "Invalid arguments"; /// Ecosystem create related messages pub(super) const MSG_L1_NETWORK_HELP: &str = "L1 Network"; @@ -103,7 +104,7 @@ pub(super) fn msg_chain_doesnt_exist_err(chain_name: &str, chains: &Vec) /// Chain create related messages pub(super) const MSG_PROVER_MODE_HELP: &str = "Prover options"; -pub(super) const MSG_CHAIN_ID_HELP: &str = "Chain ID. [if 0 a default chain id will be generated]"; +pub(super) const MSG_CHAIN_ID_HELP: &str = "Chain ID"; pub(super) const MSG_WALLET_CREATION_HELP: &str = "Wallet options"; pub(super) const MSG_WALLET_PATH_HELP: &str = "Wallet path"; pub(super) const MSG_L1_COMMIT_DATA_GENERATOR_MODE_HELP: &str = "Commit data generation mode"; @@ -134,6 +135,9 @@ pub(super) const MSG_CHAIN_CREATED: &str = "Chain created successfully"; pub(super) const MSG_CREATING_CHAIN_CONFIGURATIONS_SPINNER: &str = "Creating chain configurations..."; pub(super) const MSG_CHAIN_ID_VALIDATOR_ERR: &str = "Invalid chain id"; +pub(super) const MSG_BASE_TOKEN_ADDRESS_VALIDATOR_ERR: &str = "Invalid base token address"; +pub(super) const MSG_WALLET_CREATION_VALIDATOR_ERR: &str = + "Localhost wallet is not supported for external networks"; /// Chain genesis related messages pub(super) const MSG_L1_SECRETS_MUST_BE_PRESENTED: &str = "L1 secret must be presented";