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

chore: refactors configuration and cli structure / usage #384

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
32 changes: 32 additions & 0 deletions src/config/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use crate::config::constants::DEFAULT_DISK_CACHE_DIR;
use clap::ValueEnum;
use serde::Deserialize;

/// Cache type for the node.
#[derive(ValueEnum, Deserialize, Default, Debug, Copy, Clone)]
pub enum CacheType {
None,
Memory,
#[default]
Disk,
}

/// Cache configuration options.
#[derive(Deserialize, Debug, Clone)]
pub enum CacheConfig {
#[serde(rename = "none")]
None,
#[serde(rename = "memory")]
Memory,
#[serde(rename = "disk")]
Disk { dir: String, reset: bool },
}

impl Default for CacheConfig {
fn default() -> Self {
Self::Disk {
dir: String::from(DEFAULT_DISK_CACHE_DIR),
reset: false,
}
}
}
240 changes: 166 additions & 74 deletions src/config/cli.rs
Original file line number Diff line number Diff line change
@@ -1,114 +1,132 @@
use clap::{arg, command, Parser, Subcommand, ValueEnum};
use serde::Deserialize;
use clap::{arg, command, Parser, Subcommand};
use zksync_types::H256;

use crate::config::{
CacheConfig, CacheType, ShowCalls, ShowGasDetails, ShowStorageLogs, ShowVMDetails,
TestNodeConfig,
};
use crate::observability::LogLevel;
use crate::system_contracts::Options as SystemContractsOptions;

use super::node::{ShowCalls, ShowGasDetails, ShowStorageLogs, ShowVMDetails};

/// Cache type config for the node.
#[derive(ValueEnum, Deserialize, Default, Debug, Copy, Clone)]
pub enum CacheType {
None,
Memory,
#[default]
Disk,
}

/// System contract options.
#[derive(ValueEnum, Debug, Clone)]
pub enum DevSystemContracts {
BuiltIn,
BuiltInNoVerify,
Local,
}
use super::DEFAULT_DISK_CACHE_DIR;

#[derive(Debug, Parser)]
#[command(author = "Matter Labs", version, about = "Test Node", long_about = None)]
#[command(
author = "Matter Labs",
version,
about = "A fast and extensible local ZKsync test node.",
long_about = "Era Test Node\n\nA developer-friendly ZKsync local node for testing."
)]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Command>,
#[arg(short, long)]
/// The file path to the config file. If not supplied, defaults will be used.

// General Options
#[arg(short, long, help_heading = "General Options")]
/// Path to the configuration file. If not supplied, defaults will be used.
pub config: Option<String>,

#[arg(short, long)]
/// Enable default settings for debugging contracts
#[arg(long, default_value = "8011", help_heading = "Network Options")]
/// Port to listen on (default: 8011).
pub port: Option<u16>,

#[arg(long, help_heading = "Network Options")]
/// Specify chain ID (default: 260).
pub chain_id: Option<u32>,

#[arg(long, help_heading = "General Options")]
/// Run in offline mode (disables all network requests).
pub offline: bool,

#[arg(short, long, help_heading = "Debugging Options")]
/// Enable default settings for debugging contracts.
pub debug_mode: bool,

#[arg(long)]
/// Port to listen on - default: 8011
pub port: Option<u16>,
#[arg(long)]
/// Show call debug information
// Debugging Options
#[arg(long, help_heading = "Debugging Options")]
/// Show call debug information.
pub show_calls: Option<ShowCalls>,
#[arg(long)]
/// Show call output

#[arg(long, help_heading = "Debugging Options")]
/// Show call output information.
pub show_outputs: Option<bool>,
#[arg(long)]
/// Show storage log information

#[arg(long, help_heading = "Debugging Options")]
/// Show storage log information.
pub show_storage_logs: Option<ShowStorageLogs>,
#[arg(long)]
/// Show VM details information

#[arg(long, help_heading = "Debugging Options")]
/// Show VM details information.
pub show_vm_details: Option<ShowVMDetails>,

#[arg(long)]
/// Show Gas details information
#[arg(long, help_heading = "Debugging Options")]
/// Show gas details information.
pub show_gas_details: Option<ShowGasDetails>,

#[arg(long)]
/// If provided, uses a custom value as the L1 gas price.
#[arg(long, help_heading = "Debugging Options")]
/// If true, the tool will try to resolve ABI and topic names for better readability.
/// May decrease performance.
pub resolve_hashes: Option<bool>,

// Gas Configuration
#[arg(long, help_heading = "Gas Configuration")]
/// Custom L1 gas price (in wei).
pub l1_gas_price: Option<u64>,

#[arg(long)]
/// If provided, uses a custom value as the L2 gas price.
#[arg(long, help_heading = "Gas Configuration")]
/// Custom L2 gas price (in wei).
pub l2_gas_price: Option<u64>,

#[arg(long)]
/// If true, the tool will try to contact openchain to resolve the ABI & topic names.
/// It will make debug log more readable, but will decrease the performance.
pub resolve_hashes: Option<bool>,
#[arg(long, help_heading = "Gas Configuration")]
/// Custom L1 pubdata price (in wei).
pub l1_pubdata_price: Option<u64>,

/// Specifies the option for the system contracts (use compiled built-in with or without signature verification, or load locally).
/// Default: built-in
#[arg(long)]
pub dev_system_contracts: Option<DevSystemContracts>,
#[arg(long, help_heading = "Gas Configuration")]
/// Gas price estimation scale factor.
pub price_scale_factor: Option<f64>,

/// Enables EVM emulation. Currently, this requires local system contracts because there is no canonical EVM interpreter released yet.
#[arg(long, requires = "dev_system_contracts")]
#[arg(long, help_heading = "Gas Configuration")]
/// Gas limit estimation scale factor.
pub limit_scale_factor: Option<f32>,

#[arg(long, help_heading = "System Configuration")]
/// Directory to override bytecodes.
pub override_bytecodes_dir: Option<String>,

// System Configuration
#[arg(long, help_heading = "System Configuration")]
/// Option for system contracts (default: built-in).
pub dev_system_contracts: Option<SystemContractsOptions>,

#[arg(
long,
requires = "dev_system_contracts",
help_heading = "System Configuration"
)]
/// Enables EVM emulation. Requires local system contracts.
pub emulate_evm: bool,

/// Log filter level - default: info
#[arg(long)]
// Logging Configuration
#[arg(long, help_heading = "Logging Configuration")]
/// Log level (default: info).
pub log: Option<LogLevel>,

/// Log file path - default: era_test_node.log
#[arg(long)]
#[arg(long, help_heading = "Logging Configuration")]
/// Log file path (default: era_test_node.log).
pub log_file_path: Option<String>,

/// Cache type, can be one of `none`, `memory`, or `disk` - default: "disk"
#[arg(long)]
// Cache Options
#[arg(long, help_heading = "Cache Options")]
/// Cache type (none, memory, or disk). Default: "disk".
pub cache: Option<CacheType>,

/// If true, will reset the local `disk` cache.
#[arg(long)]
#[arg(long, help_heading = "Cache Options")]
/// Reset the local disk cache.
pub reset_cache: Option<bool>,

/// Cache directory location for `disk` cache - default: ".cache"
#[arg(long)]
#[arg(long, help_heading = "Cache Options")]
/// Cache directory location for disk cache (default: .cache).
pub cache_dir: Option<String>,

#[arg(long)]
pub override_bytecodes_dir: Option<String>,

/// Use a given chain id. If not set uses 260 (or the one from the forked network).
#[arg(long)]
pub chain_id: Option<u32>,

/// Run the node in offline mode. This will disable all network requests.
/// Can only be run alongside `run` command.
#[arg(long)]
pub offline: bool,
}

#[derive(Debug, Subcommand)]
Expand All @@ -132,6 +150,10 @@ pub struct ForkArgs {
/// - mainnet
/// - sepolia-testnet
/// - http://XXX:YY
#[arg(
long,
help = "Network to fork from (e.g., mainnet, sepolia-testnet, etc.)."
)]
pub network: String,
// Fork at a given L2 miniblock height.
// If not set - will use the current finalized block from the network.
Expand All @@ -153,7 +175,77 @@ pub struct ReplayArgs {
/// - sepolia-testnet
/// - goerli-testnet
/// - http://XXX:YY
#[arg(
long,
help = "Network to fork from (e.g., mainnet, sepolia-testnet, etc.)."
)]
pub network: String,
/// Transaction hash to replay.
#[arg(help = "Transaction hash to replay.")]
pub tx: H256,
}

impl Cli {
/// Converts the CLI arguments into a `TestNodeConfig`.
pub fn into_test_node_config(self) -> eyre::Result<TestNodeConfig> {
let vm_log_detail = if let Some(output) = self.show_outputs {
if output {
Some(ShowVMDetails::All)
} else {
Some(ShowVMDetails::None)
}
} else if let Some(logs) = self.show_storage_logs {
match logs {
ShowStorageLogs::None => Some(ShowVMDetails::None),
_ => Some(ShowVMDetails::All),
}
} else {
None
};

let config = TestNodeConfig::default()
.with_port(self.port)
.with_l1_gas_price(self.l1_gas_price)
.with_l2_gas_price(self.l2_gas_price)
.with_l1_pubdata_price(self.l1_pubdata_price)
.with_show_calls(self.show_calls)
.with_vm_log_detail(vm_log_detail)
.with_gas_limit_scale(self.limit_scale_factor)
.with_price_scale(self.price_scale_factor)
.with_resolve_hashes(self.resolve_hashes)
.with_system_contracts(self.dev_system_contracts)
.with_override_bytecodes_dir(self.override_bytecodes_dir.clone()) // Added
.with_log_level(self.log)
.with_log_file_path(self.log_file_path.clone())
.with_cache_config(self.cache.map(|cache_type| {
match cache_type {
CacheType::None => CacheConfig::None,
CacheType::Memory => CacheConfig::Memory,
CacheType::Disk => CacheConfig::Disk {
dir: self
.cache_dir
.clone()
.unwrap_or_else(|| DEFAULT_DISK_CACHE_DIR.to_string()),
reset: self.reset_cache.unwrap_or(false),
},
}
}))
.with_chain_id(self.chain_id)
.with_evm_emulator(if self.emulate_evm { Some(true) } else { None });

if self.emulate_evm && self.dev_system_contracts != Some(SystemContractsOptions::Local) {
return Err(eyre::eyre!(
"EVM emulation requires the 'local' system contracts option."
));
}

if self.debug_mode {
Ok(config
.with_show_calls(Some(ShowCalls::All))
.with_vm_log_detail(Some(ShowVMDetails::All))
.with_resolve_hashes(Some(true)))
} else {
Ok(config)
}
}
}
22 changes: 22 additions & 0 deletions src/constants.rs → src/config/constants.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
/// Directory where configuration files are stored
pub const CONFIG_DIR: &str = ".era_test_node";
/// Default name of the configuration file
pub const CONFIG_FILE_NAME: &str = "config.toml";
/// Default directory for disk cache
pub const DEFAULT_DISK_CACHE_DIR: &str = ".cache";
/// Default L1 gas price for transactions
pub const DEFAULT_L1_GAS_PRICE: u64 = 14_932_364_075;
/// Default L2 gas price for transactions if not provided via CLI
pub const DEFAULT_L2_GAS_PRICE: u64 = 45_250_000;
/// Default price for fair pubdata based on predefined value
pub const DEFAULT_FAIR_PUBDATA_PRICE: u64 = 13_607_659_111;
/// Scale factor for estimating L1 gas prices
pub const DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR: f64 = 2.0;
/// Scale factor for estimating gas limits
pub const DEFAULT_ESTIMATE_GAS_SCALE_FACTOR: f32 = 1.3;
/// Default port for the test node server
pub const NODE_PORT: u16 = 8011;
/// Network ID for the test node
pub const TEST_NODE_NETWORK_ID: u32 = 260;
/// Default log file path for the test node
pub const DEFAULT_LOG_FILE_PATH: &str = "era_test_node.log";
// List of wallets (address, private key, mnemonic) that we seed with tokens at start.
pub const RICH_WALLETS: [(&str, &str, &str); 10] = [
(
Expand Down
Loading
Loading