From 2524d1bd5561fec56e2520f4185d053f9665ae82 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 8 Nov 2024 10:45:33 -0500 Subject: [PATCH 01/15] refactor(katana): separate metrics address and port into 2 args (#2537) --- bin/katana/src/cli/node.rs | 63 +++++++++++++++++------- crates/katana/node/src/config/metrics.rs | 18 ++++++- crates/katana/node/src/lib.rs | 5 +- 3 files changed, 63 insertions(+), 23 deletions(-) diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index f06fb84db4..008bf67414 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -11,25 +11,24 @@ //! for more info. use std::collections::HashSet; -use std::net::{IpAddr, SocketAddr}; +use std::net::IpAddr; use std::path::PathBuf; use alloy_primitives::U256; use anyhow::{Context, Result}; use clap::{Args, Parser}; use console::Style; -use dojo_utils::parse::parse_socket_address; use katana_core::constants::DEFAULT_SEQUENCER_ADDRESS; use katana_core::service::messaging::MessagingConfig; use katana_node::config::db::DbConfig; use katana_node::config::dev::{DevConfig, FixedL1GasPriceConfig}; use katana_node::config::execution::{ - ExecutionConfig, DEFAULT_INVOCATION_MAX_STEPS, DEFAULT_VALIDATION_MAX_STEPS, + DEFAULT_INVOCATION_MAX_STEPS, DEFAULT_VALIDATION_MAX_STEPS, ExecutionConfig, }; use katana_node::config::fork::ForkingConfig; -use katana_node::config::metrics::MetricsConfig; +use katana_node::config::metrics::{DEFAULT_METRICS_ADDR, DEFAULT_METRICS_PORT, MetricsConfig}; use katana_node::config::rpc::{ - ApiKind, RpcConfig, DEFAULT_RPC_ADDR, DEFAULT_RPC_MAX_CONNECTIONS, DEFAULT_RPC_PORT, + ApiKind, DEFAULT_RPC_ADDR, DEFAULT_RPC_MAX_CONNECTIONS, DEFAULT_RPC_PORT, RpcConfig, }; use katana_node::config::{Config, SequencingConfig}; use katana_primitives::block::{BlockHashOrNumber, GasPrices}; @@ -37,15 +36,15 @@ use katana_primitives::chain::ChainId; use katana_primitives::chain_spec::{self, ChainSpec}; use katana_primitives::class::ClassHash; use katana_primitives::contract::ContractAddress; +use katana_primitives::genesis::Genesis; use katana_primitives::genesis::allocation::{DevAllocationsGenerator, GenesisAccountAlloc}; use katana_primitives::genesis::constant::{ DEFAULT_LEGACY_ERC20_CLASS_HASH, DEFAULT_LEGACY_UDC_CLASS_HASH, DEFAULT_PREFUNDED_ACCOUNT_BALANCE, DEFAULT_UDC_ADDRESS, }; -use katana_primitives::genesis::Genesis; -use tracing::{info, Subscriber}; +use tracing::{Subscriber, info}; use tracing_log::LogTracer; -use tracing_subscriber::{fmt, EnvFilter}; +use tracing_subscriber::{EnvFilter, fmt}; use url::Url; use crate::utils::{parse_block_hash_or_number, parse_genesis, parse_seed}; @@ -92,12 +91,6 @@ pub struct NodeArgs { #[arg(help = "Output logs in JSON format.")] pub json_log: bool, - /// Enable Prometheus metrics. - /// - /// The metrics will be served at the given interface and port. - #[arg(long, value_name = "SOCKET", value_parser = parse_socket_address, help_heading = "Metrics")] - pub metrics: Option, - #[arg(long)] #[arg(value_name = "PATH")] #[arg(value_parser = katana_core::service::messaging::MessagingConfig::parse)] @@ -108,20 +101,46 @@ pub struct NodeArgs { pub messaging: Option, #[command(flatten)] - #[command(next_help_heading = "Server options")] + pub metrics: MetricsOptions, + + #[command(flatten)] pub server: ServerOptions, #[command(flatten)] - #[command(next_help_heading = "Starknet options")] pub starknet: StarknetOptions, #[cfg(feature = "slot")] #[command(flatten)] - #[command(next_help_heading = "Slot options")] pub slot: SlotOptions, } #[derive(Debug, Args, Clone)] +#[command(next_help_heading = "Metrics options")] +pub struct MetricsOptions { + /// Whether to enable metrics. + /// + /// For now, metrics will still be collected even if this flag is not set. This only + /// controls whether the metrics server is started or not. + #[arg(long)] + pub metrics: bool, + + /// The metrics will be served at the given address. + #[arg(long = "metrics.addr")] + #[arg(value_name = "ADD")] + #[arg(requires = "metrics")] + #[arg(default_value_t = DEFAULT_METRICS_ADDR)] + pub metrics_addr: IpAddr, + + /// The metrics will be served at the given port. + #[arg(long = "metrics.port")] + #[arg(value_name = "PORT")] + #[arg(requires = "metrics")] + #[arg(default_value_t = DEFAULT_METRICS_PORT)] + pub metrics_port: u16, +} + +#[derive(Debug, Args, Clone)] +#[command(next_help_heading = "Server options")] pub struct ServerOptions { #[arg(short, long)] #[arg(default_value_t = DEFAULT_RPC_PORT)] @@ -145,6 +164,7 @@ pub struct ServerOptions { } #[derive(Debug, Args, Clone)] +#[command(next_help_heading = "Starknet options")] pub struct StarknetOptions { #[arg(long)] #[arg(default_value = "0")] @@ -166,7 +186,6 @@ pub struct StarknetOptions { pub disable_validate: bool, #[command(flatten)] - #[command(next_help_heading = "Environment options")] pub environment: EnvironmentOptions, #[arg(long)] @@ -176,6 +195,7 @@ pub struct StarknetOptions { } #[derive(Debug, Args, Clone)] +#[command(next_help_heading = "Environment options")] pub struct EnvironmentOptions { #[arg(long)] #[arg(help = "The chain ID.")] @@ -216,6 +236,7 @@ pub struct EnvironmentOptions { #[cfg(feature = "slot")] #[derive(Debug, Args, Clone)] +#[command(next_help_heading = "Slot options")] pub struct SlotOptions { #[arg(hide = true)] #[arg(long = "slot.controller")] @@ -398,7 +419,11 @@ impl NodeArgs { } fn metrics_config(&self) -> Option { - self.metrics.map(|addr| MetricsConfig { addr }) + if self.metrics.metrics { + Some(MetricsConfig { addr: self.metrics.metrics_addr, port: self.metrics.metrics_port }) + } else { + None + } } } diff --git a/crates/katana/node/src/config/metrics.rs b/crates/katana/node/src/config/metrics.rs index 40a1b234ad..9830660485 100644 --- a/crates/katana/node/src/config/metrics.rs +++ b/crates/katana/node/src/config/metrics.rs @@ -1,8 +1,22 @@ -use std::net::SocketAddr; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + +/// Metrics server default address. +pub const DEFAULT_METRICS_ADDR: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST); +/// Metrics server default port. +pub const DEFAULT_METRICS_PORT: u16 = 9100; /// Node metrics configurations. #[derive(Debug, Clone)] pub struct MetricsConfig { /// The address to bind the metrics server to. - pub addr: SocketAddr, + pub addr: IpAddr, + /// The port to bind the metrics server to. + pub port: u16, +} + +impl MetricsConfig { + /// Returns the [`SocketAddr`] for the metrics server. + pub fn socket_addr(&self) -> SocketAddr { + SocketAddr::new(self.addr, self.port) + } } diff --git a/crates/katana/node/src/lib.rs b/crates/katana/node/src/lib.rs index 294a244718..cf6445ca53 100644 --- a/crates/katana/node/src/lib.rs +++ b/crates/katana/node/src/lib.rs @@ -107,6 +107,7 @@ impl Node { // TODO: maybe move this to the build stage if let Some(ref cfg) = self.metrics_config { + let addr = cfg.socket_addr(); let mut reports: Vec> = Vec::new(); if let Some(ref db) = self.db { @@ -116,8 +117,8 @@ impl Node { let exporter = PrometheusRecorder::current().expect("qed; should exist at this point"); let server = MetricsServer::new(exporter).with_process_metrics().with_reports(reports); - self.task_manager.task_spawner().build_task().spawn(server.start(cfg.addr)); - info!(addr = %cfg.addr, "Metrics server started."); + self.task_manager.task_spawner().build_task().spawn(server.start(addr)); + info!(%addr, "Metrics server started."); } let pool = self.pool.clone(); From 42cc2663e33a3d61f6b6255e8670bb8510c58fa5 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Tue, 15 Oct 2024 14:12:22 -0400 Subject: [PATCH 02/15] refactor(katana-cli): rename server args --- bin/katana/src/cli/node.rs | 36 ++++++++++++------------- crates/dojo/test-utils/src/sequencer.rs | 2 +- crates/katana/node/src/config/rpc.rs | 4 +-- crates/katana/node/src/lib.rs | 27 +++++++++---------- 4 files changed, 33 insertions(+), 36 deletions(-) diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index 008bf67414..74620810fe 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -125,16 +125,14 @@ pub struct MetricsOptions { pub metrics: bool, /// The metrics will be served at the given address. - #[arg(long = "metrics.addr")] - #[arg(value_name = "ADD")] #[arg(requires = "metrics")] + #[arg(long = "metrics.addr", value_name = "ADDRESS")] #[arg(default_value_t = DEFAULT_METRICS_ADDR)] pub metrics_addr: IpAddr, /// The metrics will be served at the given port. - #[arg(long = "metrics.port")] - #[arg(value_name = "PORT")] #[arg(requires = "metrics")] + #[arg(long = "metrics.port", value_name = "PORT")] #[arg(default_value_t = DEFAULT_METRICS_PORT)] pub metrics_port: u16, } @@ -142,25 +140,25 @@ pub struct MetricsOptions { #[derive(Debug, Args, Clone)] #[command(next_help_heading = "Server options")] pub struct ServerOptions { - #[arg(short, long)] + #[arg(long = "http.addr", value_name = "ADDRESS")] + #[arg(default_value_t = DEFAULT_RPC_ADDR)] + #[arg(help = "The IP address the server will listen on.")] + pub http_addr: IpAddr, + + #[arg(long = "http.port", value_name = "PORT")] #[arg(default_value_t = DEFAULT_RPC_PORT)] #[arg(help = "Port number to listen on.")] - pub port: u16, + pub http_port: u16, - #[arg(long)] - #[arg(default_value_t = DEFAULT_RPC_ADDR)] - #[arg(help = "The IP address the server will listen on.")] - pub host: IpAddr, + #[arg(long = "http.corsdomain")] + #[arg(value_delimiter = ',')] + #[arg(help = "Enables the CORS layer and sets the allowed origins, separated by commas.")] + pub http_cors_domain: Option>, - #[arg(long)] + #[arg(long = "rpc.max-connections", value_name = "COUNT")] #[arg(default_value_t = DEFAULT_RPC_MAX_CONNECTIONS)] #[arg(help = "Maximum number of concurrent connections allowed.")] pub max_connections: u32, - - #[arg(long)] - #[arg(value_delimiter = ',')] - #[arg(help = "Enables the CORS layer and sets the allowed origins, separated by commas.")] - pub allowed_origins: Option>, } #[derive(Debug, Args, Clone)] @@ -329,10 +327,10 @@ impl NodeArgs { RpcConfig { apis, - port: self.server.port, - addr: self.server.host, + port: self.server.http_port, + addr: self.server.http_addr, max_connections: self.server.max_connections, - allowed_origins: self.server.allowed_origins.clone(), + cors_domain: self.server.http_cors_domain.clone(), } } diff --git a/crates/dojo/test-utils/src/sequencer.rs b/crates/dojo/test-utils/src/sequencer.rs index 63356be4ad..dbc4f661ef 100644 --- a/crates/dojo/test-utils/src/sequencer.rs +++ b/crates/dojo/test-utils/src/sequencer.rs @@ -118,7 +118,7 @@ pub fn get_default_test_config(sequencing: SequencingConfig) -> Config { chain.genesis.sequencer_address = *DEFAULT_SEQUENCER_ADDRESS; let rpc = RpcConfig { - allowed_origins: None, + cors_domain: None, port: 0, addr: DEFAULT_RPC_ADDR, max_connections: DEFAULT_RPC_MAX_CONNECTIONS, diff --git a/crates/katana/node/src/config/rpc.rs b/crates/katana/node/src/config/rpc.rs index bd1d893d39..a0806847d4 100644 --- a/crates/katana/node/src/config/rpc.rs +++ b/crates/katana/node/src/config/rpc.rs @@ -23,8 +23,8 @@ pub struct RpcConfig { pub addr: IpAddr, pub port: u16, pub max_connections: u32, - pub allowed_origins: Option>, pub apis: HashSet, + pub cors_domain: Option>, } impl RpcConfig { @@ -37,7 +37,7 @@ impl RpcConfig { impl Default for RpcConfig { fn default() -> Self { Self { - allowed_origins: None, + cors_domain: None, addr: DEFAULT_RPC_ADDR, port: DEFAULT_RPC_PORT, max_connections: DEFAULT_RPC_MAX_CONNECTIONS, diff --git a/crates/katana/node/src/lib.rs b/crates/katana/node/src/lib.rs index cf6445ca53..b120701be2 100644 --- a/crates/katana/node/src/lib.rs +++ b/crates/katana/node/src/lib.rs @@ -313,20 +313,19 @@ pub async fn spawn( .allow_methods([Method::POST, Method::GET]) .allow_headers([hyper::header::CONTENT_TYPE, "argent-client".parse().unwrap(), "argent-version".parse().unwrap()]); - let cors = - config.allowed_origins.clone().map(|allowed_origins| match allowed_origins.as_slice() { - [origin] if origin == "*" => cors.allow_origin(AllowOrigin::mirror_request()), - origins => cors.allow_origin( - origins - .iter() - .map(|o| { - let _ = o.parse::().expect("Invalid URI"); - - o.parse().expect("Invalid origin") - }) - .collect::>(), - ), - }); + let cors = config.cors_domain.clone().map(|allowed_origins| match allowed_origins.as_slice() { + [origin] if origin == "*" => cors.allow_origin(AllowOrigin::mirror_request()), + origins => cors.allow_origin( + origins + .iter() + .map(|o| { + let _ = o.parse::().expect("Invalid URI"); + + o.parse().expect("Invalid origin") + }) + .collect::>(), + ), + }); let middleware = tower::ServiceBuilder::new() .option_layer(cors) From 83561b09f0b0d717e8049dfb842be66b864eba23 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Tue, 15 Oct 2024 14:36:10 -0400 Subject: [PATCH 03/15] refactor(katana-cli): explicit development related args --- bin/katana/src/cli/node.rs | 95 +++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 28 deletions(-) diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index 74620810fe..01f2e29a60 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -84,9 +84,6 @@ pub struct NodeArgs { #[arg(value_parser = parse_block_hash_or_number)] pub fork_block: Option, - #[arg(long)] - pub dev: bool, - #[arg(long)] #[arg(help = "Output logs in JSON format.")] pub json_log: bool, @@ -109,6 +106,9 @@ pub struct NodeArgs { #[command(flatten)] pub starknet: StarknetOptions, + #[command(flatten)] + pub development: DevOptions, + #[cfg(feature = "slot")] #[command(flatten)] pub slot: SlotOptions, @@ -164,25 +164,6 @@ pub struct ServerOptions { #[derive(Debug, Args, Clone)] #[command(next_help_heading = "Starknet options")] pub struct StarknetOptions { - #[arg(long)] - #[arg(default_value = "0")] - #[arg(help = "Specify the seed for randomness of accounts to be predeployed.")] - pub seed: String, - - #[arg(long = "accounts")] - #[arg(value_name = "NUM")] - #[arg(default_value_t = 10)] - #[arg(help = "Number of pre-funded accounts to generate.")] - pub total_accounts: u16, - - #[arg(long)] - #[arg(help = "Disable charging fee when executing transactions.")] - pub disable_fee: bool, - - #[arg(long)] - #[arg(help = "Disable validation when executing transactions.")] - pub disable_validate: bool, - #[command(flatten)] pub environment: EnvironmentOptions, @@ -232,6 +213,64 @@ pub struct EnvironmentOptions { pub l1_strk_data_gas_price: Option, } +#[derive(Debug, Args, Clone)] +#[command(next_help_heading = "Development options")] +pub struct DevOptions { + /// Enable development mode. + #[arg(long)] + pub dev: bool, + + /// Specify the seed for randomness of accounts to be predeployed. + #[arg(requires = "dev")] + #[arg(long = "dev.seed", default_value = "0")] + pub seed: String, + + /// Number of pre-funded accounts to generate. + #[arg(requires = "dev")] + #[arg(long = "dev.accounts", value_name = "NUM")] + #[arg(default_value_t = 10)] + pub total_accounts: u16, + + /// Disable charging fee when executing transactions. + #[arg(requires = "dev")] + #[arg(long = "dev.disable-fee")] + pub disable_fee: bool, + + /// Skip account validation when executing transactions. + #[arg(requires = "dev")] + #[arg(long = "dev.disable-account-validation")] + pub disable_validate: bool, +} + +#[derive(Debug, Args, Clone)] +#[command(next_help_heading = "Development options")] +pub struct DevOptions { + /// Enable development mode. + #[arg(long)] + pub dev: bool, + + /// Specify the seed for randomness of accounts to be predeployed. + #[arg(requires = "dev")] + #[arg(long = "dev.seed", default_value = "0")] + pub seed: String, + + /// Number of pre-funded accounts to generate. + #[arg(requires = "dev")] + #[arg(long = "dev.accounts", value_name = "NUM")] + #[arg(default_value_t = 10)] + pub total_accounts: u16, + + /// Disable charging fee when executing transactions. + #[arg(requires = "dev")] + #[arg(long = "dev.disable-fee")] + pub disable_fee: bool, + + /// Skip account validation when executing transactions. + #[arg(requires = "dev")] + #[arg(long = "dev.disable-account-validation")] + pub disable_validate: bool, +} + #[cfg(feature = "slot")] #[derive(Debug, Args, Clone)] #[command(next_help_heading = "Slot options")] @@ -321,7 +360,7 @@ impl NodeArgs { fn rpc_config(&self) -> RpcConfig { let mut apis = HashSet::from([ApiKind::Starknet, ApiKind::Torii, ApiKind::Saya]); // only enable `katana` API in dev mode - if self.dev { + if self.development.dev { apis.insert(ApiKind::Dev); } @@ -348,8 +387,8 @@ impl NodeArgs { } // generate dev accounts - let accounts = DevAllocationsGenerator::new(self.starknet.total_accounts) - .with_seed(parse_seed(&self.starknet.seed)) + let accounts = DevAllocationsGenerator::new(self.development.total_accounts) + .with_seed(parse_seed(&self.development.seed)) .with_balance(U256::from(DEFAULT_PREFUNDED_ACCOUNT_BALANCE)) .generate(); @@ -383,8 +422,8 @@ impl NodeArgs { DevConfig { fixed_gas_prices, - fee: !self.starknet.disable_fee, - account_validation: !self.starknet.disable_validate, + fee: !self.development.disable_fee, + account_validation: !self.development.disable_validate, } } @@ -428,7 +467,7 @@ impl NodeArgs { fn print_intro(args: &NodeArgs, chain: &ChainSpec) { let mut accounts = chain.genesis.accounts().peekable(); let account_class_hash = accounts.peek().map(|e| e.1.class_hash()); - let seed = &args.starknet.seed; + let seed = &args.development.seed; if args.json_log { info!( From 1062c8037f35bccbfe17ae2caeb94e20f33db221 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Tue, 15 Oct 2024 14:41:34 -0400 Subject: [PATCH 04/15] chore(katana-cli): rename var --- bin/katana/src/cli/node.rs | 52 ++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index 01f2e29a60..f9f32c787f 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -51,30 +51,30 @@ use crate::utils::{parse_block_hash_or_number, parse_genesis, parse_seed}; #[derive(Parser, Debug)] pub struct NodeArgs { + /// Don't print anything on startup. #[arg(long)] - #[arg(help = "Don't print anything on startup.")] pub silent: bool, + /// Disable auto and interval mining, and mine on demand instead via an endpoint. #[arg(long)] #[arg(conflicts_with = "block_time")] - #[arg(help = "Disable auto and interval mining, and mine on demand instead via an endpoint.")] pub no_mining: bool, + /// Block time in milliseconds for interval mining. #[arg(short, long)] #[arg(value_name = "MILLISECONDS")] - #[arg(help = "Block time in milliseconds for interval mining.")] pub block_time: Option, + /// Directory path of the database to initialize from. + /// + /// The path must either be an empty directory or a directory which already contains a + /// previously initialized Katana database. #[arg(long)] #[arg(value_name = "PATH")] - #[arg(help = "Directory path of the database to initialize from.")] - #[arg(long_help = "Directory path of the database to initialize from. The path must either \ - be an empty directory or a directory which already contains a previously \ - initialized Katana database.")] pub db_dir: Option, + /// The Starknet RPC provider to fork the network from. #[arg(long = "fork.rpc-url", value_name = "URL", alias = "rpc-url")] - #[arg(help = "The Starknet RPC provider to fork the network from.")] pub fork_rpc_url: Option, #[arg(long = "fork.block", value_name = "BLOCK_ID", alias = "fork-block-number")] @@ -84,17 +84,18 @@ pub struct NodeArgs { #[arg(value_parser = parse_block_hash_or_number)] pub fork_block: Option, + /// Output logs in JSON format. #[arg(long)] - #[arg(help = "Output logs in JSON format.")] pub json_log: bool, + /// Configure the messaging with an other chain. + /// + /// Configure the messaging to allow Katana listening/sending messages on a + /// settlement chain that can be Ethereum or an other Starknet sequencer. + /// The configuration file details and examples can be found here: https://book.dojoengine.org/toolchain/katana/reference#messaging #[arg(long)] #[arg(value_name = "PATH")] #[arg(value_parser = katana_core::service::messaging::MessagingConfig::parse)] - #[arg(help = "Configure the messaging with an other chain.")] - #[arg(long_help = "Configure the messaging to allow Katana listening/sending messages on a \ - settlement chain that can be Ethereum or an other Starknet sequencer. \ - The configuration file details and examples can be found here: https://book.dojoengine.org/toolchain/katana/reference#messaging")] pub messaging: Option, #[command(flatten)] @@ -140,24 +141,24 @@ pub struct MetricsOptions { #[derive(Debug, Args, Clone)] #[command(next_help_heading = "Server options")] pub struct ServerOptions { + /// HTTP-RPC server listening interface. #[arg(long = "http.addr", value_name = "ADDRESS")] #[arg(default_value_t = DEFAULT_RPC_ADDR)] - #[arg(help = "The IP address the server will listen on.")] pub http_addr: IpAddr, + /// HTTP-RPC server listening port. #[arg(long = "http.port", value_name = "PORT")] #[arg(default_value_t = DEFAULT_RPC_PORT)] - #[arg(help = "Port number to listen on.")] pub http_port: u16, + /// Comma separated list of domains from which to accept cross origin requests. #[arg(long = "http.corsdomain")] #[arg(value_delimiter = ',')] - #[arg(help = "Enables the CORS layer and sets the allowed origins, separated by commas.")] pub http_cors_domain: Option>, + /// Maximum number of concurrent connections allowed. #[arg(long = "rpc.max-connections", value_name = "COUNT")] #[arg(default_value_t = DEFAULT_RPC_MAX_CONNECTIONS)] - #[arg(help = "Maximum number of concurrent connections allowed.")] pub max_connections: u32, } @@ -176,30 +177,31 @@ pub struct StarknetOptions { #[derive(Debug, Args, Clone)] #[command(next_help_heading = "Environment options")] pub struct EnvironmentOptions { + /// The chain ID. + /// + /// The chain ID. If a raw hex string (`0x` prefix) is provided, then it'd + /// used as the actual chain ID. Otherwise, it's represented as the raw + /// ASCII values. It must be a valid Cairo short string. #[arg(long)] - #[arg(help = "The chain ID.")] - #[arg(long_help = "The chain ID. If a raw hex string (`0x` prefix) is provided, then it'd \ - used as the actual chain ID. Otherwise, it's represented as the raw \ - ASCII values. It must be a valid Cairo short string.")] #[arg(value_parser = ChainId::parse)] pub chain_id: Option, + /// The maximum number of steps available for the account validation logic. #[arg(long)] - #[arg(help = "The maximum number of steps available for the account validation logic.")] pub validate_max_steps: Option, + /// The maximum number of steps available for the account execution logic. #[arg(long)] - #[arg(help = "The maximum number of steps available for the account execution logic.")] pub invoke_max_steps: Option, + /// The L1 ETH gas price. (denominated in wei) #[arg(long = "l1-eth-gas-price", value_name = "WEI")] - #[arg(help = "The L1 ETH gas price. (denominated in wei)")] #[arg(requires = "l1_strk_gas_price")] pub l1_eth_gas_price: Option, + /// The L1 STRK gas price. (denominated in fri) #[arg(long = "l1-strk-gas-price", value_name = "FRI")] #[arg(requires = "l1_eth_data_gas_price")] - #[arg(help = "The L1 STRK gas price. (denominated in fri)")] pub l1_strk_gas_price: Option, #[arg(long = "l1-eth-data-gas-price", value_name = "WEI")] From 65218017512c5aa8bf034c5f0d42a9dc0e160caf Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 1 Nov 2024 16:41:42 -0400 Subject: [PATCH 05/15] fix --- crates/katana/node/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/katana/node/src/lib.rs b/crates/katana/node/src/lib.rs index b120701be2..f6b4f02fa3 100644 --- a/crates/katana/node/src/lib.rs +++ b/crates/katana/node/src/lib.rs @@ -16,12 +16,12 @@ use config::{Config, SequencingConfig}; use dojo_metrics::exporters::prometheus::PrometheusRecorder; use dojo_metrics::{Report, Server as MetricsServer}; use hyper::{Method, Uri}; +use jsonrpsee::RpcModule; use jsonrpsee::server::middleware::proxy_get_request::ProxyGetRequestLayer; use jsonrpsee::server::{AllowHosts, ServerBuilder, ServerHandle}; -use jsonrpsee::RpcModule; +use katana_core::backend::Backend; use katana_core::backend::gas_oracle::L1GasOracle; use katana_core::backend::storage::Blockchain; -use katana_core::backend::Backend; use katana_core::constants::{ DEFAULT_ETH_L1_DATA_GAS_PRICE, DEFAULT_ETH_L1_GAS_PRICE, DEFAULT_STRK_L1_DATA_GAS_PRICE, DEFAULT_STRK_L1_GAS_PRICE, @@ -32,17 +32,17 @@ use katana_core::service::messaging::MessagingConfig; use katana_db::mdbx::DbEnv; use katana_executor::implementation::blockifier::BlockifierFactory; use katana_executor::{ExecutionFlags, ExecutorFactory}; -use katana_pipeline::{stage, Pipeline}; +use katana_pipeline::{Pipeline, stage}; +use katana_pool::TxPool; use katana_pool::ordering::FiFo; use katana_pool::validation::stateful::TxValidator; -use katana_pool::TxPool; use katana_primitives::block::GasPrices; use katana_primitives::env::{CfgEnv, FeeTokenAddressses}; use katana_rpc::dev::DevApi; use katana_rpc::metrics::RpcServerMetrics; use katana_rpc::saya::SayaApi; -use katana_rpc::starknet::forking::ForkedClient; use katana_rpc::starknet::StarknetApi; +use katana_rpc::starknet::forking::ForkedClient; use katana_rpc::torii::ToriiApi; use katana_rpc_api::dev::DevApiServer; use katana_rpc_api::saya::SayaApiServer; From 40a67d3f602c412ae99c7f4af7c9f2a811d9956b Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 8 Nov 2024 11:51:11 -0500 Subject: [PATCH 06/15] refactor cli --- bin/katana/src/cli/node.rs | 193 ++++++++++++++++++---------------- bin/katana/src/utils.rs | 31 ++++++ crates/katana/node/src/lib.rs | 10 +- 3 files changed, 136 insertions(+), 98 deletions(-) diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index f9f32c787f..df175e1536 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -23,12 +23,12 @@ use katana_core::service::messaging::MessagingConfig; use katana_node::config::db::DbConfig; use katana_node::config::dev::{DevConfig, FixedL1GasPriceConfig}; use katana_node::config::execution::{ - DEFAULT_INVOCATION_MAX_STEPS, DEFAULT_VALIDATION_MAX_STEPS, ExecutionConfig, + ExecutionConfig, DEFAULT_INVOCATION_MAX_STEPS, DEFAULT_VALIDATION_MAX_STEPS, }; use katana_node::config::fork::ForkingConfig; -use katana_node::config::metrics::{DEFAULT_METRICS_ADDR, DEFAULT_METRICS_PORT, MetricsConfig}; +use katana_node::config::metrics::{MetricsConfig, DEFAULT_METRICS_ADDR, DEFAULT_METRICS_PORT}; use katana_node::config::rpc::{ - ApiKind, DEFAULT_RPC_ADDR, DEFAULT_RPC_MAX_CONNECTIONS, DEFAULT_RPC_PORT, RpcConfig, + ApiKind, RpcConfig, DEFAULT_RPC_ADDR, DEFAULT_RPC_MAX_CONNECTIONS, DEFAULT_RPC_PORT, }; use katana_node::config::{Config, SequencingConfig}; use katana_primitives::block::{BlockHashOrNumber, GasPrices}; @@ -36,18 +36,18 @@ use katana_primitives::chain::ChainId; use katana_primitives::chain_spec::{self, ChainSpec}; use katana_primitives::class::ClassHash; use katana_primitives::contract::ContractAddress; -use katana_primitives::genesis::Genesis; use katana_primitives::genesis::allocation::{DevAllocationsGenerator, GenesisAccountAlloc}; use katana_primitives::genesis::constant::{ DEFAULT_LEGACY_ERC20_CLASS_HASH, DEFAULT_LEGACY_UDC_CLASS_HASH, DEFAULT_PREFUNDED_ACCOUNT_BALANCE, DEFAULT_UDC_ADDRESS, }; -use tracing::{Subscriber, info}; +use katana_primitives::genesis::Genesis; +use tracing::{info, Subscriber}; use tracing_log::LogTracer; -use tracing_subscriber::{EnvFilter, fmt}; +use tracing_subscriber::{fmt, EnvFilter}; use url::Url; -use crate::utils::{parse_block_hash_or_number, parse_genesis, parse_seed}; +use crate::utils::{parse_block_hash_or_number, parse_genesis, parse_seed, LogFormat}; #[derive(Parser, Debug)] pub struct NodeArgs { @@ -73,20 +73,14 @@ pub struct NodeArgs { #[arg(value_name = "PATH")] pub db_dir: Option, - /// The Starknet RPC provider to fork the network from. - #[arg(long = "fork.rpc-url", value_name = "URL", alias = "rpc-url")] - pub fork_rpc_url: Option, - - #[arg(long = "fork.block", value_name = "BLOCK_ID", alias = "fork-block-number")] - #[arg(requires = "fork_rpc_url")] - #[arg(help = "Fork the network at a specific block id, can either be a hash (0x-prefixed) \ - or number.")] - #[arg(value_parser = parse_block_hash_or_number)] - pub fork_block: Option, - - /// Output logs in JSON format. - #[arg(long)] - pub json_log: bool, + /// The L1 provider RPC URL. + /// + /// Right now this is optional, required only when `--fork.block` is specified. This will be + /// used later once we make instantiating Katana from valid L1 state, a requirement. This will + /// also be used as the L1 provider in the messaging configuration. Setting this option without + /// `--fork.block` is a no-op. + #[arg(long = "l1.provider", value_name = "URL")] + pub l1_provider: Option, /// Configure the messaging with an other chain. /// @@ -98,6 +92,9 @@ pub struct NodeArgs { #[arg(value_parser = katana_core::service::messaging::MessagingConfig::parse)] pub messaging: Option, + #[command(flatten)] + pub logging: LoggingOptions, + #[command(flatten)] pub metrics: MetricsOptions, @@ -110,6 +107,9 @@ pub struct NodeArgs { #[command(flatten)] pub development: DevOptions, + #[command(flatten)] + pub forking: ForkingOptions, + #[cfg(feature = "slot")] #[command(flatten)] pub slot: SlotOptions, @@ -118,7 +118,7 @@ pub struct NodeArgs { #[derive(Debug, Args, Clone)] #[command(next_help_heading = "Metrics options")] pub struct MetricsOptions { - /// Whether to enable metrics. + /// Enable metrics. /// /// For now, metrics will still be collected even if this flag is not set. This only /// controls whether the metrics server is started or not. @@ -170,7 +170,7 @@ pub struct StarknetOptions { #[arg(long)] #[arg(value_parser = parse_genesis)] - #[arg(conflicts_with_all(["fork_rpc_url", "seed", "total_accounts"]))] + #[arg(conflicts_with_all(["fork", "seed", "total_accounts"]))] pub genesis: Option, } @@ -193,26 +193,6 @@ pub struct EnvironmentOptions { /// The maximum number of steps available for the account execution logic. #[arg(long)] pub invoke_max_steps: Option, - - /// The L1 ETH gas price. (denominated in wei) - #[arg(long = "l1-eth-gas-price", value_name = "WEI")] - #[arg(requires = "l1_strk_gas_price")] - pub l1_eth_gas_price: Option, - - /// The L1 STRK gas price. (denominated in fri) - #[arg(long = "l1-strk-gas-price", value_name = "FRI")] - #[arg(requires = "l1_eth_data_gas_price")] - pub l1_strk_gas_price: Option, - - #[arg(long = "l1-eth-data-gas-price", value_name = "WEI")] - #[arg(requires = "l1_strk_data_gas_price")] - #[arg(help = "The L1 ETH gas price. (denominated in wei)")] - pub l1_eth_data_gas_price: Option, - - #[arg(long = "l1-strk-data-gas-price", value_name = "FRI")] - #[arg(requires = "l1_eth_gas_price")] - #[arg(help = "The L1 STRK gas prick. (denominated in fri)")] - pub l1_strk_data_gas_price: Option, } #[derive(Debug, Args, Clone)] @@ -235,42 +215,58 @@ pub struct DevOptions { /// Disable charging fee when executing transactions. #[arg(requires = "dev")] - #[arg(long = "dev.disable-fee")] - pub disable_fee: bool, + #[arg(long = "dev.no-fee")] + pub no_fee: bool, - /// Skip account validation when executing transactions. + /// Disable account validation when executing transactions. + /// + /// Skipping the transaction sender's account validation function. #[arg(requires = "dev")] - #[arg(long = "dev.disable-account-validation")] - pub disable_validate: bool, -} + #[arg(long = "dev.no-account-validation")] + pub no_account_validation: bool, -#[derive(Debug, Args, Clone)] -#[command(next_help_heading = "Development options")] -pub struct DevOptions { - /// Enable development mode. - #[arg(long)] - pub dev: bool, + /// The L1 ETH gas price. (denominated in wei) + #[arg(requires_all = ["dev", "l1_strk_gas_price"])] + #[arg(long = "dev.l1-eth-gas-price", value_name = "WEI")] + pub l1_eth_gas_price: Option, - /// Specify the seed for randomness of accounts to be predeployed. - #[arg(requires = "dev")] - #[arg(long = "dev.seed", default_value = "0")] - pub seed: String, + /// The L1 STRK gas price. (denominated in fri) + #[arg(requires_all = ["dev", "l1_eth_data_gas_price"])] + #[arg(long = "dev.l1-strk-gas-price", value_name = "FRI")] + pub l1_strk_gas_price: Option, - /// Number of pre-funded accounts to generate. - #[arg(requires = "dev")] - #[arg(long = "dev.accounts", value_name = "NUM")] - #[arg(default_value_t = 10)] - pub total_accounts: u16, + /// The L1 ETH data gas price. (denominated in wei) + #[arg(requires_all = ["dev", "l1_strk_data_gas_price"])] + #[arg(long = "dev.l1-eth-data-gas-price", value_name = "WEI")] + pub l1_eth_data_gas_price: Option, - /// Disable charging fee when executing transactions. - #[arg(requires = "dev")] - #[arg(long = "dev.disable-fee")] - pub disable_fee: bool, + /// The L1 STRK data gas price. (denominated in fri) + #[arg(requires_all = ["dev", "l1_eth_gas_price"])] + #[arg(long = "dev.l1-strk-data-gas-price", value_name = "FRI")] + pub l1_strk_data_gas_price: Option, +} - /// Skip account validation when executing transactions. - #[arg(requires = "dev")] - #[arg(long = "dev.disable-account-validation")] - pub disable_validate: bool, +#[derive(Debug, Args, Clone)] +#[command(next_help_heading = "Forking options")] +pub struct ForkingOptions { + /// Run in forking mode. + #[arg(long, requires = "l1_provider")] + pub fork: bool, + + /// Fork the network at a specific block id, can either be a hash (0x-prefixed) or a block + /// number. + #[arg(long = "fork.block", value_name = "BLOCK", requires_all = ["fork", "l1_provider"])] + #[arg(value_parser = parse_block_hash_or_number)] + pub fork_block: Option, +} + +#[derive(Debug, Args, Clone)] +#[command(next_help_heading = "Logging options")] +pub struct LoggingOptions { + /// Log format to use + #[arg(long = "log.format", value_name = "FORMAT")] + #[arg(default_value_t = LogFormat::Full)] + pub log_format: LogFormat, } #[cfg(feature = "slot")] @@ -323,19 +319,26 @@ impl NodeArgs { fn init_logging(&self) -> Result<()> { const DEFAULT_LOG_FILTER: &str = "info,tasks=debug,executor=trace,forking::backend=trace,\ - server=debug,blockifier=off,jsonrpsee_server=off,\ - hyper=off,messaging=debug,node=error"; + blockifier=off,jsonrpsee_server=off,hyper=off,\ + messaging=debug,node=error"; + + let filter = if self.development.dev { + &format!("{DEFAULT_LOG_FILTER},server=debug") + } else { + DEFAULT_LOG_FILTER + }; LogTracer::init()?; - let builder = fmt::Subscriber::builder().with_env_filter( - EnvFilter::try_from_default_env().or(EnvFilter::try_new(DEFAULT_LOG_FILTER))?, - ); + // If the user has set the `RUST_LOG` environment variable, then we prioritize it. + // Otherwise, we use the default log filter. + // TODO: change env var to `KATANA_LOG`. + let filter = EnvFilter::try_from_default_env().or(EnvFilter::try_new(filter))?; + let builder = fmt::Subscriber::builder().with_env_filter(filter); - let subscriber: Box = if self.json_log { - Box::new(builder.json().finish()) - } else { - Box::new(builder.finish()) + let subscriber: Box = match self.logging.log_format { + LogFormat::Full => Box::new(builder.finish()), + LogFormat::Json => Box::new(builder.json().finish()), }; Ok(tracing::subscriber::set_global_default(subscriber)?) @@ -405,14 +408,14 @@ impl NodeArgs { } fn dev_config(&self) -> DevConfig { - let fixed_gas_prices = if self.starknet.environment.l1_eth_gas_price.is_some() { + let fixed_gas_prices = if self.development.l1_eth_gas_price.is_some() { // It is safe to unwrap all of these here because the CLI parser ensures if one is set, // all must be set. - let eth_gas_price = self.starknet.environment.l1_eth_gas_price.unwrap(); - let strk_gas_price = self.starknet.environment.l1_strk_gas_price.unwrap(); - let eth_data_gas_price = self.starknet.environment.l1_eth_data_gas_price.unwrap(); - let strk_data_gas_price = self.starknet.environment.l1_strk_data_gas_price.unwrap(); + let eth_gas_price = self.development.l1_eth_gas_price.unwrap(); + let strk_gas_price = self.development.l1_strk_gas_price.unwrap(); + let eth_data_gas_price = self.development.l1_eth_data_gas_price.unwrap(); + let strk_data_gas_price = self.development.l1_strk_data_gas_price.unwrap(); let gas_price = GasPrices { eth: eth_gas_price, strk: strk_gas_price }; let data_gas_price = GasPrices { eth: eth_data_gas_price, strk: strk_data_gas_price }; @@ -424,8 +427,8 @@ impl NodeArgs { DevConfig { fixed_gas_prices, - fee: !self.development.disable_fee, - account_validation: !self.development.disable_validate, + fee: !self.development.no_fee, + account_validation: !self.development.no_account_validation, } } @@ -446,11 +449,15 @@ impl NodeArgs { } fn forking_config(&self) -> Result> { - if let Some(url) = self.fork_rpc_url.clone() { - Ok(Some(ForkingConfig { url, block: self.fork_block })) - } else { - Ok(None) + if self.forking.fork { + // L1 provider is optional for now. See comments on the `l1_provider` field above for + // more context. + let url = self.l1_provider.as_ref().expect("should be required by cli"); + let cfg = ForkingConfig { url: url.clone(), block: self.forking.fork_block }; + return Ok(Some(cfg)); } + + Ok(None) } fn db_config(&self) -> DbConfig { @@ -471,7 +478,7 @@ fn print_intro(args: &NodeArgs, chain: &ChainSpec) { let account_class_hash = accounts.peek().map(|e| e.1.class_hash()); let seed = &args.development.seed; - if args.json_log { + if args.logging.log_format == LogFormat::Json { info!( target: LOG_TARGET, "{}", diff --git a/bin/katana/src/utils.rs b/bin/katana/src/utils.rs index 580924962e..d580eada96 100644 --- a/bin/katana/src/utils.rs +++ b/bin/katana/src/utils.rs @@ -1,6 +1,9 @@ +use std::fmt::Display; use std::path::PathBuf; use anyhow::{Context, Result}; +use clap::builder::PossibleValue; +use clap::ValueEnum; use katana_primitives::block::{BlockHash, BlockHashOrNumber, BlockNumber}; use katana_primitives::genesis::json::GenesisJson; use katana_primitives::genesis::Genesis; @@ -34,6 +37,34 @@ pub fn parse_block_hash_or_number(value: &str) -> Result { } } +#[derive(Debug, Clone, PartialEq)] +pub enum LogFormat { + Json, + Full, +} + +impl ValueEnum for LogFormat { + fn value_variants<'a>() -> &'a [Self] { + &[Self::Json, Self::Full] + } + + fn to_possible_value(&self) -> Option { + match self { + Self::Json => Some(PossibleValue::new("json")), + Self::Full => Some(PossibleValue::new("full")), + } + } +} + +impl Display for LogFormat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Json => write!(f, "json"), + Self::Full => write!(f, "full"), + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/katana/node/src/lib.rs b/crates/katana/node/src/lib.rs index f6b4f02fa3..b120701be2 100644 --- a/crates/katana/node/src/lib.rs +++ b/crates/katana/node/src/lib.rs @@ -16,12 +16,12 @@ use config::{Config, SequencingConfig}; use dojo_metrics::exporters::prometheus::PrometheusRecorder; use dojo_metrics::{Report, Server as MetricsServer}; use hyper::{Method, Uri}; -use jsonrpsee::RpcModule; use jsonrpsee::server::middleware::proxy_get_request::ProxyGetRequestLayer; use jsonrpsee::server::{AllowHosts, ServerBuilder, ServerHandle}; -use katana_core::backend::Backend; +use jsonrpsee::RpcModule; use katana_core::backend::gas_oracle::L1GasOracle; use katana_core::backend::storage::Blockchain; +use katana_core::backend::Backend; use katana_core::constants::{ DEFAULT_ETH_L1_DATA_GAS_PRICE, DEFAULT_ETH_L1_GAS_PRICE, DEFAULT_STRK_L1_DATA_GAS_PRICE, DEFAULT_STRK_L1_GAS_PRICE, @@ -32,17 +32,17 @@ use katana_core::service::messaging::MessagingConfig; use katana_db::mdbx::DbEnv; use katana_executor::implementation::blockifier::BlockifierFactory; use katana_executor::{ExecutionFlags, ExecutorFactory}; -use katana_pipeline::{Pipeline, stage}; -use katana_pool::TxPool; +use katana_pipeline::{stage, Pipeline}; use katana_pool::ordering::FiFo; use katana_pool::validation::stateful::TxValidator; +use katana_pool::TxPool; use katana_primitives::block::GasPrices; use katana_primitives::env::{CfgEnv, FeeTokenAddressses}; use katana_rpc::dev::DevApi; use katana_rpc::metrics::RpcServerMetrics; use katana_rpc::saya::SayaApi; -use katana_rpc::starknet::StarknetApi; use katana_rpc::starknet::forking::ForkedClient; +use katana_rpc::starknet::StarknetApi; use katana_rpc::torii::ToriiApi; use katana_rpc_api::dev::DevApiServer; use katana_rpc_api::saya::SayaApiServer; From cf8dbb34bbeff974c30dea312a96b6ec2e60d109 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 8 Nov 2024 12:33:43 -0500 Subject: [PATCH 07/15] move gas price to gas price oracle options --- bin/katana/src/cli/node.rs | 83 +++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index df175e1536..7604f12937 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -104,6 +104,9 @@ pub struct NodeArgs { #[command(flatten)] pub starknet: StarknetOptions, + #[command(flatten)] + pub gpo: GasPriceOracleOptions, + #[command(flatten)] pub development: DevOptions, @@ -224,26 +227,6 @@ pub struct DevOptions { #[arg(requires = "dev")] #[arg(long = "dev.no-account-validation")] pub no_account_validation: bool, - - /// The L1 ETH gas price. (denominated in wei) - #[arg(requires_all = ["dev", "l1_strk_gas_price"])] - #[arg(long = "dev.l1-eth-gas-price", value_name = "WEI")] - pub l1_eth_gas_price: Option, - - /// The L1 STRK gas price. (denominated in fri) - #[arg(requires_all = ["dev", "l1_eth_data_gas_price"])] - #[arg(long = "dev.l1-strk-gas-price", value_name = "FRI")] - pub l1_strk_gas_price: Option, - - /// The L1 ETH data gas price. (denominated in wei) - #[arg(requires_all = ["dev", "l1_strk_data_gas_price"])] - #[arg(long = "dev.l1-eth-data-gas-price", value_name = "WEI")] - pub l1_eth_data_gas_price: Option, - - /// The L1 STRK data gas price. (denominated in fri) - #[arg(requires_all = ["dev", "l1_eth_gas_price"])] - #[arg(long = "dev.l1-strk-data-gas-price", value_name = "FRI")] - pub l1_strk_data_gas_price: Option, } #[derive(Debug, Args, Clone)] @@ -269,6 +252,30 @@ pub struct LoggingOptions { pub log_format: LogFormat, } +#[derive(Debug, Args, Clone)] +#[command(next_help_heading = "Gas Price Oracle Options")] +pub struct GasPriceOracleOptions { + /// The L1 ETH gas price. (denominated in wei) + #[arg(requires_all = ["l1_strk_gas_price"])] + #[arg(long = "gpo.l1-eth-gas-price", value_name = "WEI")] + pub l1_eth_gas_price: Option, + + /// The L1 STRK gas price. (denominated in fri) + #[arg(requires_all = ["l1_eth_data_gas_price"])] + #[arg(long = "gpo.l1-strk-gas-price", value_name = "FRI")] + pub l1_strk_gas_price: Option, + + /// The L1 ETH data gas price. (denominated in wei) + #[arg(requires_all = ["l1_strk_data_gas_price"])] + #[arg(long = "gpo.l1-eth-data-gas-price", value_name = "WEI")] + pub l1_eth_data_gas_price: Option, + + /// The L1 STRK data gas price. (denominated in fri) + #[arg(requires_all = ["l1_eth_gas_price"])] + #[arg(long = "gpo.l1-strk-data-gas-price", value_name = "FRI")] + pub l1_strk_data_gas_price: Option, +} + #[cfg(feature = "slot")] #[derive(Debug, Args, Clone)] #[command(next_help_heading = "Slot options")] @@ -408,14 +415,14 @@ impl NodeArgs { } fn dev_config(&self) -> DevConfig { - let fixed_gas_prices = if self.development.l1_eth_gas_price.is_some() { + let fixed_gas_prices = if self.gpo.l1_eth_gas_price.is_some() { // It is safe to unwrap all of these here because the CLI parser ensures if one is set, // all must be set. - let eth_gas_price = self.development.l1_eth_gas_price.unwrap(); - let strk_gas_price = self.development.l1_strk_gas_price.unwrap(); - let eth_data_gas_price = self.development.l1_eth_data_gas_price.unwrap(); - let strk_data_gas_price = self.development.l1_strk_data_gas_price.unwrap(); + let eth_gas_price = self.gpo.l1_eth_gas_price.unwrap(); + let strk_gas_price = self.gpo.l1_strk_gas_price.unwrap(); + let eth_data_gas_price = self.gpo.l1_eth_data_gas_price.unwrap(); + let strk_data_gas_price = self.gpo.l1_strk_data_gas_price.unwrap(); let gas_price = GasPrices { eth: eth_gas_price, strk: strk_gas_price }; let data_gas_price = GasPrices { eth: eth_data_gas_price, strk: strk_data_gas_price }; @@ -611,8 +618,9 @@ mod test { fn test_starknet_config_custom() { let args = NodeArgs::parse_from([ "katana", - "--disable-fee", - "--disable-validate", + "--dev", + "--dev.no-fee", + "--dev.no-account-validation", "--chain-id", "SN_GOERLI", "--invoke-max-steps", @@ -637,8 +645,9 @@ mod test { fn custom_fixed_gas_prices() { let args = NodeArgs::parse_from([ "katana", - "--disable-fee", - "--disable-validate", + "--dev", + "--dev.no-fee", + "--dev.no-account-validation", "--chain-id", "SN_GOERLI", "--invoke-max-steps", @@ -647,13 +656,13 @@ mod test { "100", "--db-dir", "/path/to/db", - "--l1-eth-gas-price", + "--gpo.l1-eth-gas-price", "10", - "--l1-strk-gas-price", + "--gpo.l1-strk-gas-price", "20", - "--l1-eth-data-gas-price", + "--gpo.l1-eth-data-gas-price", "1", - "--l1-strk-data-gas-price", + "--gpo.l1-strk-data-gas-price", "2", ]); let config = args.config().unwrap(); @@ -678,13 +687,13 @@ mod test { "katana", "--genesis", "./tests/test-data/genesis.json", - "--l1-eth-gas-price", + "--gpo.l1-eth-gas-price", "100", - "--l1-strk-gas-price", + "--gpo.l1-strk-gas-price", "200", - "--l1-eth-data-gas-price", + "--gpo.l1-eth-data-gas-price", "111", - "--l1-strk-data-gas-price", + "--gpo.l1-strk-data-gas-price", "222", ]) .config() From a184016918e2cd6986de91a8fa80fe41f37cf879 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 8 Nov 2024 13:00:49 -0500 Subject: [PATCH 08/15] update node bindings to new cli args --- crates/katana/node-bindings/src/lib.rs | 139 +++++++++++++++++-------- crates/katana/runner/src/lib.rs | 2 +- 2 files changed, 95 insertions(+), 46 deletions(-) diff --git a/crates/katana/node-bindings/src/lib.rs b/crates/katana/node-bindings/src/lib.rs index f270e0d384..e5d52324e8 100644 --- a/crates/katana/node-bindings/src/lib.rs +++ b/crates/katana/node-bindings/src/lib.rs @@ -176,20 +176,21 @@ pub struct Katana { json_log: bool, block_time: Option, db_dir: Option, - rpc_url: Option, + l1_provider: Option, fork_block_number: Option, messaging: Option, // Metrics options - metrics: Option, + metrics_addr: Option, + metrics_port: Option, // Server options - port: Option, - host: Option, - max_connections: Option, - allowed_origins: Option, + http_addr: Option, + http_port: Option, + rpc_max_connections: Option, + http_cors_domain: Option, - // Starknet options + // Dev options seed: Option, accounts: Option, disable_fee: bool, @@ -253,7 +254,7 @@ impl Katana { /// Sets the port which will be used when the `katana` instance is launched. pub fn port>(mut self, port: T) -> Self { - self.port = Some(port.into()); + self.http_port = Some(port.into()); self } @@ -271,8 +272,8 @@ impl Katana { } /// Sets the RPC URL to fork the network from. - pub fn rpc_url>(mut self, rpc_url: T) -> Self { - self.rpc_url = Some(rpc_url.into()); + pub fn l1_provider>(mut self, rpc_url: T) -> Self { + self.l1_provider = Some(rpc_url.into()); self } @@ -301,27 +302,33 @@ impl Katana { self } - /// Enables Prometheus metrics and sets the socket address. - pub fn metrics>(mut self, metrics: T) -> Self { - self.metrics = Some(metrics.into()); + /// Enables Prometheus metrics and sets the metrics server address. + pub fn metrics_addr>(mut self, addr: T) -> Self { + self.metrics_addr = Some(addr.into()); + self + } + + /// Enables Prometheus metrics and sets the metrics server port. + pub fn metrics_port>(mut self, port: T) -> Self { + self.metrics_port = Some(port.into()); self } /// Sets the host IP address the server will listen on. - pub fn host>(mut self, host: T) -> Self { - self.host = Some(host.into()); + pub fn http_addr>(mut self, addr: T) -> Self { + self.http_addr = Some(addr.into()); self } /// Sets the maximum number of concurrent connections allowed. - pub const fn max_connections(mut self, max_connections: u64) -> Self { - self.max_connections = Some(max_connections); + pub const fn rpc_max_connections(mut self, max_connections: u64) -> Self { + self.rpc_max_connections = Some(max_connections); self } /// Enables the CORS layer and sets the allowed origins, separated by commas. - pub fn allowed_origins>(mut self, allowed_origins: T) -> Self { - self.allowed_origins = Some(allowed_origins.into()); + pub fn http_cors_domain>(mut self, allowed_origins: T) -> Self { + self.http_cors_domain = Some(allowed_origins.into()); self } @@ -414,8 +421,14 @@ impl Katana { let mut cmd = self.program.as_ref().map_or_else(|| Command::new("katana"), Command::new); cmd.stdout(std::process::Stdio::piped()).stderr(std::process::Stdio::inherit()); - let mut port = self.port.unwrap_or(0); - cmd.arg("--port").arg(port.to_string()); + if let Some(host) = self.http_addr { + cmd.arg("--http.addr").arg(host.to_string()); + } + + // In the case where port 0 is set, we will need to extract the actual port number + // from the logs. + let mut port = self.http_port.unwrap_or(5050); + cmd.arg("--http.port").arg(port.to_string()); if self.no_mining { cmd.arg("--no-mining"); @@ -428,56 +441,92 @@ impl Katana { if let Some(db_dir) = self.db_dir { cmd.arg("--db-dir").arg(db_dir); } - if let Some(rpc_url) = self.rpc_url { - cmd.arg("--rpc-url").arg(rpc_url); + + if let Some(url) = self.l1_provider { + cmd.arg("--l1.provider").arg(url); } + // Need to make sure that the `--dev` is not being set twice. + let mut is_dev = false; + if self.dev { cmd.arg("--dev"); + is_dev = true; } - if self.json_log { - cmd.arg("--json-log"); + if let Some(seed) = self.seed { + if !is_dev { + cmd.arg("--dev"); + is_dev = true; + } + + cmd.arg("--dev.seed").arg(seed.to_string()); } - if let Some(fork_block_number) = self.fork_block_number { - cmd.arg("--fork-block-number").arg(fork_block_number.to_string()); + if let Some(accounts) = self.accounts { + if !is_dev { + cmd.arg("--dev"); + is_dev = true; + } + + cmd.arg("--dev.accounts").arg(accounts.to_string()); } - if let Some(messaging) = self.messaging { - cmd.arg("--messaging").arg(messaging); + if self.disable_fee { + if !is_dev { + cmd.arg("--dev"); + is_dev = true; + } + + cmd.arg("--dev.no-fee"); } - if let Some(metrics) = self.metrics { - cmd.arg("--metrics").arg(metrics); + if self.disable_validate { + if !is_dev { + cmd.arg("--dev"); + } + + cmd.arg("--dev.no-account-validation"); } - if let Some(host) = self.host { - cmd.arg("--host").arg(host); + if self.json_log { + cmd.args(["--log.format", "json"]); } - if let Some(max_connections) = self.max_connections { - cmd.arg("--max-connections").arg(max_connections.to_string()); + if let Some(fork_block_number) = self.fork_block_number { + cmd.args(["--fork", "--fork.block"]).arg(fork_block_number.to_string()); } - if let Some(allowed_origins) = self.allowed_origins { - cmd.arg("--allowed-origins").arg(allowed_origins); + if let Some(messaging) = self.messaging { + cmd.arg("--messaging").arg(messaging); } - if let Some(seed) = self.seed { - cmd.arg("--seed").arg(seed.to_string()); + // Need to make sure that the `--metrics` is not being set twice. + let mut metrics_enabled = false; + + if let Some(addr) = self.metrics_addr { + if !metrics_enabled { + cmd.arg("--metrics"); + metrics_enabled = true; + } + + cmd.arg("--metrics.addr").arg(addr.to_string()); } - if let Some(accounts) = self.accounts { - cmd.arg("--accounts").arg(accounts.to_string()); + if let Some(port) = self.metrics_port { + if !metrics_enabled { + cmd.arg("--metrics"); + } + + cmd.arg("--metrics.port").arg(port.to_string()); } - if self.disable_fee { - cmd.arg("--disable-fee"); + if let Some(max_connections) = self.rpc_max_connections { + cmd.arg("--rpc.max-connections").arg(max_connections.to_string()); } - if self.disable_validate { - cmd.arg("--disable-validate"); + if let Some(allowed_origins) = self.http_cors_domain { + cmd.arg("--http.corsdomain").arg(allowed_origins); } if let Some(chain_id) = self.chain_id { diff --git a/crates/katana/runner/src/lib.rs b/crates/katana/runner/src/lib.rs index 816c3b490e..f771e28511 100644 --- a/crates/katana/runner/src/lib.rs +++ b/crates/katana/runner/src/lib.rs @@ -121,7 +121,7 @@ impl KatanaRunner { .port(port) .accounts(n_accounts) .json_log(true) - .max_connections(10000) + .rpc_max_connections(10000) .dev(config.dev) .fee(!config.disable_fee); From f7789331586f8d6d46d64d238d4ab07a30730ed3 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 8 Nov 2024 14:13:14 -0500 Subject: [PATCH 09/15] update ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c7ba11e6f..d2565695cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -193,7 +193,7 @@ jobs: sudo apt update && sudo apt install ./hurl_3.0.0_amd64.deb chmod +x /tmp/bins/katana chmod +x /tmp/bins/sozo - nohup /tmp/bins/katana --accounts 2 --disable-fee & + nohup /tmp/bins/katana --dev.accounts 2 --dev.no-fee & - run: | /tmp/bins/sozo --manifest-path examples/spawn-and-move/Scarb.toml build /tmp/bins/sozo --manifest-path examples/spawn-and-move/Scarb.toml migrate From a75150cf1a30af4c14bec55aedc7d1ea011dcbb1 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 8 Nov 2024 14:15:28 -0500 Subject: [PATCH 10/15] revert to free port --- crates/katana/node-bindings/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/katana/node-bindings/src/lib.rs b/crates/katana/node-bindings/src/lib.rs index e5d52324e8..dec102f63b 100644 --- a/crates/katana/node-bindings/src/lib.rs +++ b/crates/katana/node-bindings/src/lib.rs @@ -427,7 +427,7 @@ impl Katana { // In the case where port 0 is set, we will need to extract the actual port number // from the logs. - let mut port = self.http_port.unwrap_or(5050); + let mut port = self.http_port.unwrap_or(0); cmd.arg("--http.port").arg(port.to_string()); if self.no_mining { From cc33f625c9bdda3aca041da38bf4773bd27caf0b Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 8 Nov 2024 14:16:38 -0500 Subject: [PATCH 11/15] fmt --- bin/katana/src/cli/node.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index 7604f12937..892a704e54 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -86,7 +86,7 @@ pub struct NodeArgs { /// /// Configure the messaging to allow Katana listening/sending messages on a /// settlement chain that can be Ethereum or an other Starknet sequencer. - /// The configuration file details and examples can be found here: https://book.dojoengine.org/toolchain/katana/reference#messaging + /// The configuration file details and examples can be found here: #[arg(long)] #[arg(value_name = "PATH")] #[arg(value_parser = katana_core::service::messaging::MessagingConfig::parse)] From f27fd57c2a193654813efeae8acf5c1abcdd3b69 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 8 Nov 2024 14:38:48 -0500 Subject: [PATCH 12/15] remove l1.provider --- .github/workflows/ci.yml | 2 +- bin/katana/src/cli/node.rs | 21 +++++++-------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2565695cd..81b6f52e9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -193,7 +193,7 @@ jobs: sudo apt update && sudo apt install ./hurl_3.0.0_amd64.deb chmod +x /tmp/bins/katana chmod +x /tmp/bins/sozo - nohup /tmp/bins/katana --dev.accounts 2 --dev.no-fee & + nohup /tmp/bins/katana --dev --dev.accounts 2 --dev.no-fee & - run: | /tmp/bins/sozo --manifest-path examples/spawn-and-move/Scarb.toml build /tmp/bins/sozo --manifest-path examples/spawn-and-move/Scarb.toml migrate diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index 892a704e54..4a61a1e754 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -73,15 +73,6 @@ pub struct NodeArgs { #[arg(value_name = "PATH")] pub db_dir: Option, - /// The L1 provider RPC URL. - /// - /// Right now this is optional, required only when `--fork.block` is specified. This will be - /// used later once we make instantiating Katana from valid L1 state, a requirement. This will - /// also be used as the L1 provider in the messaging configuration. Setting this option without - /// `--fork.block` is a no-op. - #[arg(long = "l1.provider", value_name = "URL")] - pub l1_provider: Option, - /// Configure the messaging with an other chain. /// /// Configure the messaging to allow Katana listening/sending messages on a @@ -233,12 +224,16 @@ pub struct DevOptions { #[command(next_help_heading = "Forking options")] pub struct ForkingOptions { /// Run in forking mode. - #[arg(long, requires = "l1_provider")] + #[arg(long, requires = "fork_provider")] pub fork: bool, + /// The RPC URL of the network to fork from. + #[arg(long = "fork.provider", value_name = "URL", requires = "fork")] + pub fork_provider: Option, + /// Fork the network at a specific block id, can either be a hash (0x-prefixed) or a block /// number. - #[arg(long = "fork.block", value_name = "BLOCK", requires_all = ["fork", "l1_provider"])] + #[arg(long = "fork.block", value_name = "BLOCK", requires = "fork")] #[arg(value_parser = parse_block_hash_or_number)] pub fork_block: Option, } @@ -457,9 +452,7 @@ impl NodeArgs { fn forking_config(&self) -> Result> { if self.forking.fork { - // L1 provider is optional for now. See comments on the `l1_provider` field above for - // more context. - let url = self.l1_provider.as_ref().expect("should be required by cli"); + let url = self.forking.fork_provider.as_ref().expect("should be required by cli"); let cfg = ForkingConfig { url: url.clone(), block: self.forking.fork_block }; return Ok(Some(cfg)); } From 758f46fec80ac43b22e1ca8050112d59642f74ec Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 8 Nov 2024 14:48:31 -0500 Subject: [PATCH 13/15] update --- bin/katana/src/cli/node.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index 4a61a1e754..ee239082b4 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -99,10 +99,10 @@ pub struct NodeArgs { pub gpo: GasPriceOracleOptions, #[command(flatten)] - pub development: DevOptions, + pub forking: ForkingOptions, #[command(flatten)] - pub forking: ForkingOptions, + pub development: DevOptions, #[cfg(feature = "slot")] #[command(flatten)] @@ -164,7 +164,7 @@ pub struct StarknetOptions { #[arg(long)] #[arg(value_parser = parse_genesis)] - #[arg(conflicts_with_all(["fork", "seed", "total_accounts"]))] + #[arg(conflicts_with_all(["seed", "total_accounts"]))] pub genesis: Option, } @@ -223,17 +223,16 @@ pub struct DevOptions { #[derive(Debug, Args, Clone)] #[command(next_help_heading = "Forking options")] pub struct ForkingOptions { - /// Run in forking mode. - #[arg(long, requires = "fork_provider")] - pub fork: bool, - /// The RPC URL of the network to fork from. - #[arg(long = "fork.provider", value_name = "URL", requires = "fork")] + /// + /// This will operate Katana in forked mode. Continuing from the tip of the forked network, or + /// at a specific block if `fork.block` is provided. + #[arg(long = "fork.provider", value_name = "URL", conflicts_with = "genesis")] pub fork_provider: Option, /// Fork the network at a specific block id, can either be a hash (0x-prefixed) or a block /// number. - #[arg(long = "fork.block", value_name = "BLOCK", requires = "fork")] + #[arg(long = "fork.block", value_name = "BLOCK", requires = "fork_provider")] #[arg(value_parser = parse_block_hash_or_number)] pub fork_block: Option, } @@ -451,8 +450,7 @@ impl NodeArgs { } fn forking_config(&self) -> Result> { - if self.forking.fork { - let url = self.forking.fork_provider.as_ref().expect("should be required by cli"); + if let Some(ref url) = self.forking.fork_provider { let cfg = ForkingConfig { url: url.clone(), block: self.forking.fork_block }; return Ok(Some(cfg)); } From 468e514558c916ef2e1e85d84423f0166b2e2bbc Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 8 Nov 2024 15:15:49 -0500 Subject: [PATCH 14/15] make fixed gpo sovereign --- bin/katana/src/cli/node.rs | 123 ++++++++++++++++++--------- crates/katana/node/src/config/dev.rs | 16 ++++ 2 files changed, 101 insertions(+), 38 deletions(-) diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index ee239082b4..d86bd92d94 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -31,7 +31,7 @@ use katana_node::config::rpc::{ ApiKind, RpcConfig, DEFAULT_RPC_ADDR, DEFAULT_RPC_MAX_CONNECTIONS, DEFAULT_RPC_PORT, }; use katana_node::config::{Config, SequencingConfig}; -use katana_primitives::block::{BlockHashOrNumber, GasPrices}; +use katana_primitives::block::BlockHashOrNumber; use katana_primitives::chain::ChainId; use katana_primitives::chain_spec::{self, ChainSpec}; use katana_primitives::class::ClassHash; @@ -250,22 +250,18 @@ pub struct LoggingOptions { #[command(next_help_heading = "Gas Price Oracle Options")] pub struct GasPriceOracleOptions { /// The L1 ETH gas price. (denominated in wei) - #[arg(requires_all = ["l1_strk_gas_price"])] #[arg(long = "gpo.l1-eth-gas-price", value_name = "WEI")] pub l1_eth_gas_price: Option, /// The L1 STRK gas price. (denominated in fri) - #[arg(requires_all = ["l1_eth_data_gas_price"])] #[arg(long = "gpo.l1-strk-gas-price", value_name = "FRI")] pub l1_strk_gas_price: Option, /// The L1 ETH data gas price. (denominated in wei) - #[arg(requires_all = ["l1_strk_data_gas_price"])] #[arg(long = "gpo.l1-eth-data-gas-price", value_name = "WEI")] pub l1_eth_data_gas_price: Option, /// The L1 STRK data gas price. (denominated in fri) - #[arg(requires_all = ["l1_eth_gas_price"])] #[arg(long = "gpo.l1-strk-data-gas-price", value_name = "FRI")] pub l1_strk_data_gas_price: Option, } @@ -409,22 +405,27 @@ impl NodeArgs { } fn dev_config(&self) -> DevConfig { - let fixed_gas_prices = if self.gpo.l1_eth_gas_price.is_some() { - // It is safe to unwrap all of these here because the CLI parser ensures if one is set, - // all must be set. + let mut fixed_gas_prices = None; - let eth_gas_price = self.gpo.l1_eth_gas_price.unwrap(); - let strk_gas_price = self.gpo.l1_strk_gas_price.unwrap(); - let eth_data_gas_price = self.gpo.l1_eth_data_gas_price.unwrap(); - let strk_data_gas_price = self.gpo.l1_strk_data_gas_price.unwrap(); + if let Some(price) = self.gpo.l1_eth_gas_price { + let prices = fixed_gas_prices.get_or_insert(FixedL1GasPriceConfig::default()); + prices.gas_price.eth = price; + } - let gas_price = GasPrices { eth: eth_gas_price, strk: strk_gas_price }; - let data_gas_price = GasPrices { eth: eth_data_gas_price, strk: strk_data_gas_price }; + if let Some(price) = self.gpo.l1_strk_gas_price { + let prices = fixed_gas_prices.get_or_insert(FixedL1GasPriceConfig::default()); + prices.gas_price.strk = price; + } - Some(FixedL1GasPriceConfig { gas_price, data_gas_price }) - } else { - None - }; + if let Some(price) = self.gpo.l1_eth_data_gas_price { + let prices = fixed_gas_prices.get_or_insert(FixedL1GasPriceConfig::default()); + prices.data_gas_price.eth = price; + } + + if let Some(price) = self.gpo.l1_strk_data_gas_price { + let prices = fixed_gas_prices.get_or_insert(FixedL1GasPriceConfig::default()); + prices.data_gas_price.strk = price; + } DevConfig { fixed_gas_prices, @@ -586,6 +587,10 @@ PREFUNDED ACCOUNTS #[cfg(test)] mod test { use assert_matches::assert_matches; + use katana_core::constants::{ + DEFAULT_ETH_L1_DATA_GAS_PRICE, DEFAULT_ETH_L1_GAS_PRICE, DEFAULT_STRK_L1_DATA_GAS_PRICE, + DEFAULT_STRK_L1_GAS_PRICE, + }; use katana_primitives::{address, felt}; use super::*; @@ -634,19 +639,66 @@ mod test { #[test] fn custom_fixed_gas_prices() { - let args = NodeArgs::parse_from([ + let config = NodeArgs::parse_from(["katana"]).config().unwrap(); + assert!(config.dev.fixed_gas_prices.is_none()); + + let config = + NodeArgs::parse_from(["katana", "--gpo.l1-eth-gas-price", "10"]).config().unwrap(); + assert_matches!(config.dev.fixed_gas_prices, Some(prices) => { + assert_eq!(prices.gas_price.eth, 10); + assert_eq!(prices.gas_price.strk, DEFAULT_STRK_L1_GAS_PRICE); + assert_eq!(prices.data_gas_price.eth, DEFAULT_ETH_L1_DATA_GAS_PRICE); + assert_eq!(prices.data_gas_price.strk, DEFAULT_STRK_L1_DATA_GAS_PRICE); + }); + + let config = + NodeArgs::parse_from(["katana", "--gpo.l1-strk-gas-price", "20"]).config().unwrap(); + assert_matches!(config.dev.fixed_gas_prices, Some(prices) => { + assert_eq!(prices.gas_price.eth, DEFAULT_ETH_L1_GAS_PRICE); + assert_eq!(prices.gas_price.strk, 20); + assert_eq!(prices.data_gas_price.eth, DEFAULT_ETH_L1_DATA_GAS_PRICE); + assert_eq!(prices.data_gas_price.strk, DEFAULT_STRK_L1_DATA_GAS_PRICE); + }); + + let config = + NodeArgs::parse_from(["katana", "--gpo.l1-eth-data-gas-price", "1"]).config().unwrap(); + assert_matches!(config.dev.fixed_gas_prices, Some(prices) => { + assert_eq!(prices.gas_price.eth, DEFAULT_ETH_L1_GAS_PRICE); + assert_eq!(prices.gas_price.strk, DEFAULT_STRK_L1_GAS_PRICE); + assert_eq!(prices.data_gas_price.eth, 1); + assert_eq!(prices.data_gas_price.strk, DEFAULT_STRK_L1_DATA_GAS_PRICE); + }); + + let config = + NodeArgs::parse_from(["katana", "--gpo.l1-strk-data-gas-price", "2"]).config().unwrap(); + assert_matches!(config.dev.fixed_gas_prices, Some(prices) => { + assert_eq!(prices.gas_price.eth, DEFAULT_ETH_L1_GAS_PRICE); + assert_eq!(prices.gas_price.strk, DEFAULT_STRK_L1_GAS_PRICE); + assert_eq!(prices.data_gas_price.eth, DEFAULT_ETH_L1_DATA_GAS_PRICE); + assert_eq!(prices.data_gas_price.strk, 2); + }); + + let config = NodeArgs::parse_from([ + "katana", + "--gpo.l1-eth-gas-price", + "10", + "--gpo.l1-strk-data-gas-price", + "2", + ]) + .config() + .unwrap(); + + assert_matches!(config.dev.fixed_gas_prices, Some(prices) => { + assert_eq!(prices.gas_price.eth, 10); + assert_eq!(prices.gas_price.strk, DEFAULT_STRK_L1_GAS_PRICE); + assert_eq!(prices.data_gas_price.eth, DEFAULT_ETH_L1_DATA_GAS_PRICE); + assert_eq!(prices.data_gas_price.strk, 2); + }); + + // Set all the gas prices options + + let config = NodeArgs::parse_from([ "katana", - "--dev", - "--dev.no-fee", - "--dev.no-account-validation", - "--chain-id", - "SN_GOERLI", - "--invoke-max-steps", - "200", - "--validate-max-steps", - "100", - "--db-dir", - "/path/to/db", "--gpo.l1-eth-gas-price", "10", "--gpo.l1-strk-gas-price", @@ -655,15 +707,10 @@ mod test { "1", "--gpo.l1-strk-data-gas-price", "2", - ]); - let config = args.config().unwrap(); + ]) + .config() + .unwrap(); - assert!(!config.dev.fee); - assert!(!config.dev.account_validation); - assert_eq!(config.execution.invocation_max_steps, 200); - assert_eq!(config.execution.validation_max_steps, 100); - assert_eq!(config.db.dir, Some(PathBuf::from("/path/to/db"))); - assert_eq!(config.chain.id, ChainId::GOERLI); assert_matches!(config.dev.fixed_gas_prices, Some(prices) => { assert_eq!(prices.gas_price.eth, 10); assert_eq!(prices.gas_price.strk, 20); diff --git a/crates/katana/node/src/config/dev.rs b/crates/katana/node/src/config/dev.rs index cddd6bf64a..5ae4b73193 100644 --- a/crates/katana/node/src/config/dev.rs +++ b/crates/katana/node/src/config/dev.rs @@ -1,3 +1,7 @@ +use katana_core::constants::{ + DEFAULT_ETH_L1_DATA_GAS_PRICE, DEFAULT_ETH_L1_GAS_PRICE, DEFAULT_STRK_L1_DATA_GAS_PRICE, + DEFAULT_STRK_L1_GAS_PRICE, +}; use katana_primitives::block::GasPrices; /// Development configuration. @@ -36,6 +40,18 @@ pub struct FixedL1GasPriceConfig { pub data_gas_price: GasPrices, } +impl std::default::Default for FixedL1GasPriceConfig { + fn default() -> Self { + Self { + gas_price: GasPrices { eth: DEFAULT_ETH_L1_GAS_PRICE, strk: DEFAULT_STRK_L1_GAS_PRICE }, + data_gas_price: GasPrices { + eth: DEFAULT_ETH_L1_DATA_GAS_PRICE, + strk: DEFAULT_STRK_L1_DATA_GAS_PRICE, + }, + } + } +} + impl std::default::Default for DevConfig { fn default() -> Self { Self { fee: true, account_validation: true, fixed_gas_prices: None } From 26c6a2b99008aa1f3e96fe7c57940cacbe53a68f Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Fri, 8 Nov 2024 22:19:31 -0500 Subject: [PATCH 15/15] remove broken link --- bin/katana/src/cli/node.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index d86bd92d94..60387c1882 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -77,7 +77,6 @@ pub struct NodeArgs { /// /// Configure the messaging to allow Katana listening/sending messages on a /// settlement chain that can be Ethereum or an other Starknet sequencer. - /// The configuration file details and examples can be found here: #[arg(long)] #[arg(value_name = "PATH")] #[arg(value_parser = katana_core::service::messaging::MessagingConfig::parse)]