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 toolbox find Zkstack.yaml in parent dirs #2430

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
20 changes: 0 additions & 20 deletions zk_toolbox/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion zk_toolbox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ futures = "0.3.30"
human-panic = "2.0"
lazy_static = "1.4.0"
once_cell = "1.19.0"
path-absolutize = "3.1.1"
rand = "0.8.5"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand Down
1 change: 0 additions & 1 deletion zk_toolbox/crates/config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ anyhow.workspace = true
clap.workspace = true
common.workspace = true
ethers.workspace = true
path-absolutize.workspace = true
rand.workspace = true
serde.workspace = true
serde_json.workspace = true
Expand Down
103 changes: 62 additions & 41 deletions zk_toolbox/crates/config/src/ecosystem.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use std::{cell::OnceCell, path::PathBuf};
use std::{
cell::OnceCell,
path::{Path, PathBuf},
};

use path_absolutize::Absolutize;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use common::logger;
use serde::{Deserialize, Serialize, Serializer};
use thiserror::Error;
use types::{ChainId, L1Network, ProverMode, WalletCreation};
use xshell::Shell;
Expand Down Expand Up @@ -60,25 +63,17 @@ impl Serialize for EcosystemConfig {
}
}

impl<'de> Deserialize<'de> for EcosystemConfig {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let config: EcosystemConfigInternal = Deserialize::deserialize(deserializer)?;
let bellman_cuda_dir = config.bellman_cuda_dir.map(|dir| {
dir.absolutize()
.expect("Failed to parse bellman-cuda path")
.to_path_buf()
});
impl ReadConfig for EcosystemConfig {
fn read(shell: &Shell, path: impl AsRef<Path>) -> anyhow::Result<Self> {
let config: EcosystemConfigInternal = EcosystemConfigInternal::read(shell, path)?;

let bellman_cuda_dir = config
.bellman_cuda_dir
.map(|dir| shell.current_dir().join(dir));
Ok(EcosystemConfig {
name: config.name.clone(),
l1_network: config.l1_network,
link_to_code: config
.link_to_code
.absolutize()
.expect("Failed to parse zksync-era path")
.to_path_buf(),
link_to_code: shell.current_dir().join(config.link_to_code),
bellman_cuda_dir,
chains: config.chains.clone(),
config: config.config.clone(),
Expand All @@ -101,16 +96,37 @@ impl EcosystemConfig {
}

pub fn from_file(shell: &Shell) -> Result<Self, EcosystemConfigFromFileError> {
let path = PathBuf::from(CONFIG_NAME);
if !shell.path_exists(path) {
let Ok(path) = find_file(shell, shell.current_dir(), CONFIG_NAME) else {
return Err(EcosystemConfigFromFileError::NotExists);
}
};

let mut config = EcosystemConfig::read(shell, CONFIG_NAME)
.map_err(|e| EcosystemConfigFromFileError::InvalidConfig { source: e })?;
config.shell = shell.clone().into();
shell.change_dir(path);

Ok(config)
let ecosystem = match EcosystemConfig::read(shell, CONFIG_NAME) {
Ok(mut config) => {
config.shell = shell.clone().into();
config
}
Err(_) => {
// Try to deserialize with chain config, if it's successful, likely we are in the folder
// with chain and we will find the ecosystem config somewhere in parent directories
let chain_config = ChainConfigInternal::read(shell, CONFIG_NAME)
.map_err(|err| EcosystemConfigFromFileError::InvalidConfig { source: err })?;
logger::info(format!("You are in a directory with chain config, default chain for execution has changed to {}", &chain_config.name));

let current_dir = shell.current_dir();
let Some(parent) = current_dir.parent() else {
return Err(EcosystemConfigFromFileError::NotExists);
};
// Try to find ecosystem somewhere in parent directories
shell.change_dir(parent);
let mut ecosystem_config = EcosystemConfig::from_file(shell)?;
// change the default chain for using it in later executions
ecosystem_config.default_chain = chain_config.name;
ecosystem_config
}
};
Ok(ecosystem)
}

pub fn load_chain(&self, name: Option<String>) -> Option<ChainConfig> {
Expand All @@ -131,11 +147,7 @@ impl EcosystemConfig {
external_node_config_path: config.external_node_config_path,
l1_batch_commit_data_generator_mode: config.l1_batch_commit_data_generator_mode,
l1_network: self.l1_network,
link_to_code: self
.link_to_code
.absolutize()
.expect("Failed to parse zksync-era path")
.into(),
link_to_code: self.get_shell().current_dir().join(&self.link_to_code),
base_token: config.base_token,
rocks_db_path: config.rocks_db_path,
wallet_creation: config.wallet_creation,
Expand Down Expand Up @@ -202,19 +214,14 @@ impl EcosystemConfig {
}

fn get_internal(&self) -> EcosystemConfigInternal {
let bellman_cuda_dir = self.bellman_cuda_dir.clone().map(|dir| {
dir.absolutize()
.expect("Failed to parse bellman-cuda path")
.to_path_buf()
});
let bellman_cuda_dir = self
.bellman_cuda_dir
.clone()
.map(|dir| self.get_shell().current_dir().join(dir));
EcosystemConfigInternal {
name: self.name.clone(),
l1_network: self.l1_network,
link_to_code: self
.link_to_code
.absolutize()
.expect("Failed to parse zksync-era path")
.into(),
link_to_code: self.get_shell().current_dir().join(&self.link_to_code),
bellman_cuda_dir,
chains: self.chains.clone(),
config: self.config.clone(),
Expand All @@ -238,3 +245,17 @@ pub enum EcosystemConfigFromFileError {
pub fn get_default_era_chain_id() -> ChainId {
ERA_CHAIN_ID
}

// Find file in all parents repository and return necessary path or an empty error if nothing has been found
fn find_file(shell: &Shell, path_buf: PathBuf, file_name: &str) -> Result<PathBuf, ()> {
let _dir = shell.push_dir(path_buf);
if shell.path_exists(file_name) {
Ok(shell.current_dir())
} else {
let current_dir = shell.current_dir();
let Some(path) = current_dir.parent() else {
return Err(());
};
find_file(shell, path.to_path_buf(), file_name)
}
}
8 changes: 5 additions & 3 deletions zk_toolbox/crates/config/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ pub trait FileConfigWithDefaultName {

impl<T> FileConfig for T where T: FileConfigWithDefaultName {}

impl<T> ReadConfig for T where T: FileConfig + Clone + DeserializeOwned {}

impl<T> SaveConfig for T where T: FileConfig + Serialize {}

impl<T> SaveConfigWithComment for T where T: FileConfig + Serialize {}
Expand All @@ -31,9 +29,13 @@ impl<T> SaveConfigWithBasePath for T where T: FileConfigWithDefaultName + Serial

impl<T> SaveConfigWithCommentAndBasePath for T where T: FileConfigWithDefaultName + Serialize {}

pub trait ReadConfig: Sized {
fn read(shell: &Shell, path: impl AsRef<Path>) -> anyhow::Result<Self>;
}

/// Reads a config file from a given path, correctly parsing file extension.
/// Supported file extensions are: `yaml`, `yml`, `toml`, `json`.
pub trait ReadConfig: DeserializeOwned + Clone {
impl<T: DeserializeOwned> ReadConfig for T {
fn read(shell: &Shell, path: impl AsRef<Path>) -> anyhow::Result<Self> {
let error_context = || format!("Failed to parse config file {:?}.", path.as_ref());

Expand Down
1 change: 0 additions & 1 deletion zk_toolbox/crates/zk_inception/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ clap.workspace = true
cliclack.workspace = true
config.workspace = true
console.workspace = true
path-absolutize.workspace = true
human-panic.workspace = true
lazy_static.workspace = true
serde_yaml.workspace = true
Expand Down
Loading