Skip to content

Commit

Permalink
feat(zk_toolbox): allow to run zk_inception chain create non-intera…
Browse files Browse the repository at this point in the history
…ctively (#2579)

## 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) -->
Allow to run `zk_inception chain create` non-interactively and create
custom chains within CI integration tests.

## 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. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted via `zk fmt` and `zk lint`.
  • Loading branch information
manuelmauro authored Aug 2, 2024
1 parent b2e1fe5 commit 555fcf7
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 72 deletions.
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

0 comments on commit 555fcf7

Please sign in to comment.