diff --git a/Cargo.lock b/Cargo.lock index e0c55b74..cda07a6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2500,12 +2500,10 @@ dependencies = [ "schemars", "serde", "serde_json", - "sha3 0.10.8", "tempdir", "test-log", "time", "tokio", - "toml 0.8.13", "tracing", "tracing-subscriber", "zksync-web3-rs", diff --git a/Cargo.toml b/Cargo.toml index 71effade..cd31d99a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,6 @@ zksync_utils = { git = "https://github.com/matter-labs/zksync-era.git", rev = "6 zksync_web3_decl = { git = "https://github.com/matter-labs/zksync-era.git", rev = "6c034f6e180cc92e99766f14c8840c90efa56cec", features = [ "server", ] } -sha3 = "0.10.6" # alloy alloy-signer-local = { version = "0.5.4", features = ["mnemonic"] } @@ -59,7 +58,6 @@ rustc-hash = "1.1.0" indexmap = "2.0.1" chrono = { version = "0.4.31", default-features = false } time = "0.3.36" -toml = "0.8.13" rand = "0.8" [dev-dependencies] diff --git a/src/config/cli.rs b/src/config/cli.rs index b72e32bc..75c18309 100644 --- a/src/config/cli.rs +++ b/src/config/cli.rs @@ -31,6 +31,12 @@ pub struct Cli { /// Run in offline mode (disables all network requests). pub offline: bool, + #[arg(long, help_heading = "General Options")] + /// Enable health check endpoint. + /// It will be available for GET requests at /health. + /// The endpoint will return 200 OK if the node is healthy. + pub health_check_endpoint: bool, + /// Writes output of `era-test-node` as json to user-specified file. #[arg(long, value_name = "OUT_FILE", help_heading = "General Options")] pub config_out: Option, @@ -293,7 +299,12 @@ impl Cli { })) .with_chain_id(self.chain_id) .set_config_out(self.config_out) - .with_evm_emulator(if self.emulate_evm { Some(true) } else { None }); + .with_evm_emulator(if self.emulate_evm { Some(true) } else { None }) + .with_health_check_endpoint(if self.health_check_endpoint { + Some(true) + } else { + None + }); if self.emulate_evm && self.dev_system_contracts != Some(SystemContractsOptions::Local) { return Err(eyre::eyre!( diff --git a/src/config/mod.rs b/src/config/mod.rs index c6ddb896..1831429b 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -99,6 +99,8 @@ pub struct TestNodeConfig { pub signer_accounts: Vec, /// Whether the node operates in offline mode pub offline: bool, + /// Whether we need to enable the health check endpoint. + pub health_check_endpoint: bool, } impl Default for TestNodeConfig { @@ -143,6 +145,7 @@ impl Default for TestNodeConfig { // Offline mode disabled by default offline: false, + health_check_endpoint: false, } } } @@ -287,6 +290,14 @@ impl TestNodeConfig { "Disabled".red() } ); + tracing::info!( + "Health Check Endpoint: {}", + if self.health_check_endpoint { + "Enabled".green() + } else { + "Disabled".red() + } + ); println!("\n"); tracing::info!("========================================"); tracing::info!( @@ -623,6 +634,20 @@ impl TestNodeConfig { pub fn is_offline(&self) -> bool { self.offline } + + /// Set the health check endpoint mode + #[must_use] + pub fn with_health_check_endpoint(mut self, health_check_endpoint: Option) -> Self { + if let Some(health_check_endpoint) = health_check_endpoint { + self.health_check_endpoint = health_check_endpoint; + } + self + } + + /// Get the health check endpoint mode status + pub fn is_health_check_endpoint_endpoint_enabled(&self) -> bool { + self.health_check_endpoint + } } /// Account Generator diff --git a/src/main.rs b/src/main.rs index c9ad8c10..c6b83689 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,6 +62,7 @@ async fn build_json_http< addr: SocketAddr, log_level_filter: LevelFilter, node: InMemoryNode, + enable_health_api: bool, ) -> tokio::task::JoinHandle<()> { let (sender, recv) = oneshot::channel::<()>(); @@ -88,11 +89,15 @@ async fn build_json_http< .build() .unwrap(); - let server = jsonrpc_http_server::ServerBuilder::new(io_handler) + let mut builder = jsonrpc_http_server::ServerBuilder::new(io_handler) .threads(1) - .event_loop_executor(runtime.handle().clone()) - .start_http(&addr) - .unwrap(); + .event_loop_executor(runtime.handle().clone()); + + if enable_health_api { + builder = builder.health_api(("/health", "web3_clientVersion")); + } + + let server = builder.start_http(&addr).unwrap(); server.wait(); let _ = sender; @@ -293,6 +298,7 @@ async fn main() -> anyhow::Result<()> { SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), config.port), log_level_filter, node, + config.health_check_endpoint, ) .await;