Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(zk_toolbox): allow to run zk_inception chain create non-interactively #2579

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/ci-zk-toolbox-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,28 @@ 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 sequential \
--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 &
Expand Down
2 changes: 1 addition & 1 deletion core/tests/ts-integration/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ async function loadTestEnvironmentFromFile(chain: string): Promise<TestEnvironme
let generalConfig = loadConfig({ pathToHome, chain, config: 'general.yaml', configsFolderSuffix });
let secretsConfig = loadConfig({ pathToHome, chain, config: 'secrets.yaml', configsFolderSuffix });

const network = ecosystem.l1_network;
const network = ecosystem.l1_network.toLowerCase();
let mainWalletPK = getMainWalletPk(pathToHome, network);
const l2NodeUrl = generalConfig.api.web3_json_rpc.http_url;

Expand Down
181 changes: 126 additions & 55 deletions zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
use std::{path::PathBuf, str::FromStr};

use anyhow::{bail, Context};
use clap::{Parser, ValueEnum};
use common::{Prompt, PromptConfirm, PromptSelect};
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,
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_PROMPT, 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,
},
};

Expand All @@ -42,8 +46,8 @@ impl From<L1BatchCommitmentModeInternal> for L1BatchCommitmentMode {
pub struct ChainCreateArgs {
#[arg(long)]
chain_name: Option<String>,
#[arg(value_parser = clap::value_parser ! (u32).range(1..))]
chain_id: Option<u32>,
#[clap(long, help = MSG_CHAIN_ID_HELP)]
chain_id: Option<ChainId>,
#[clap(long, help = MSG_PROVER_MODE_HELP, value_enum)]
prover_mode: Option<ProverMode>,
#[clap(long, help = MSG_WALLET_CREATION_HELP, value_enum)]
Expand All @@ -67,38 +71,57 @@ impl ChainCreateArgs {
self,
number_of_chains: u32,
l1_network: &L1Network,
) -> ChainCreateArgsFinal {
) -> 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_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| match v {
ChainId::Sequential => L2_CHAIN_ID + number_of_chains,
ChainId::Id(v) => v,
})
.unwrap_or_else(|| {
Prompt::new(MSG_CHAIN_ID_PROMPT)
.default(&(L2_CHAIN_ID + number_of_chains).to_string())
.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 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 {
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,
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<PathBuf> = if self.wallet_creation == Some(WalletCreation::InFile) {
Some(self.wallet_path.unwrap_or_else(|| {
Expand All @@ -114,32 +137,63 @@ 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::<u64>() 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 number_validator = |val: &String| -> Result<(), String> {
let Ok(val) = val.parse::<u64>() 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()
{
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 = 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)
.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,
}
};

Expand All @@ -149,7 +203,7 @@ impl ChainCreateArgs {
.ask()
});

ChainCreateArgsFinal {
Ok(ChainCreateArgsFinal {
chain_name,
chain_id,
prover_version,
Expand All @@ -158,7 +212,7 @@ impl ChainCreateArgs {
wallet_path,
base_token,
set_as_default,
}
})
}
}

Expand All @@ -179,3 +233,20 @@ enum BaseTokenSelection {
Eth,
Custom,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
enum ChainId {
Sequential,
Id(u32),
}

impl FromStr for ChainId {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
(s == "sequential")
.then_some(ChainId::Sequential)
.or_else(|| s.parse::<u32>().ok().map(ChainId::Id))
.ok_or_else(|| MSG_CHAIN_ID_VALIDATOR_ERR.to_string())
}
}
15 changes: 9 additions & 6 deletions zk_toolbox/crates/zk_inception/src/commands/chain/create.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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,
},
};

Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<EcosystemCreateArgsFinal> {
let mut ecosystem_name = self
.ecosystem_name
.unwrap_or_else(|| Prompt::new(MSG_ECOSYSTEM_NAME_PROMPT).ask());
Expand Down Expand Up @@ -67,23 +70,23 @@ 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)
.default(true)
.ask()
});

EcosystemCreateArgsFinal {
Ok(EcosystemCreateArgsFinal {
ecosystem_name,
l1_network,
link_to_code,
wallet_creation: chain.wallet_creation,
wallet_path: chain.wallet_path.clone(),
chain_args: chain,
start_containers,
}
})
}
}

Expand Down
14 changes: 8 additions & 6 deletions zk_toolbox/crates/zk_inception/src/commands/ecosystem/create.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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,
},
};

Expand All @@ -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);
Expand Down
Loading
Loading