From dede7e1323706e6b876b0ecef81488bc29e527c7 Mon Sep 17 00:00:00 2001 From: Andrei Silviu Dragnea Date: Thu, 14 Sep 2023 09:29:22 +0300 Subject: [PATCH 1/2] Remove #[allow(dead_code)] --- evm_loader/lib/src/types/tracer_ch_db.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/evm_loader/lib/src/types/tracer_ch_db.rs b/evm_loader/lib/src/types/tracer_ch_db.rs index fce66629e..2380063e4 100644 --- a/evm_loader/lib/src/types/tracer_ch_db.rs +++ b/evm_loader/lib/src/types/tracer_ch_db.rs @@ -129,7 +129,6 @@ impl TryInto for AccountRow { } } -#[allow(dead_code)] impl ClickHouseDb { pub fn new(config: &ChDbConfig) -> Self { let url_id = rand::thread_rng().gen_range(0..config.clickhouse_url.len()); From 1a8229b599bdc0a6af7c0b9b336d9357d278581c Mon Sep 17 00:00:00 2001 From: Andrei Silviu Dragnea Date: Thu, 14 Sep 2023 09:57:03 +0300 Subject: [PATCH 2/2] NDEV-2184: Report error when requested too early slot --- .../api/src/api_server/handlers/emulate.rs | 2 +- .../handlers/get_ether_account_data.rs | 2 +- .../src/api_server/handlers/get_storage_at.rs | 2 +- evm_loader/api/src/api_server/handlers/mod.rs | 2 ++ evm_loader/api/src/api_server/handlers/trace.rs | 2 +- .../src/api_server/handlers/trace_next_block.rs | 4 ++-- evm_loader/cli/src/context.rs | 11 +++++++---- evm_loader/lib/src/context.rs | 11 +++++++---- evm_loader/lib/src/errors.rs | 12 +++++++++--- evm_loader/lib/src/rpc/db_call_client.rs | 16 +++++++++++++--- evm_loader/lib/src/types/tracer_ch_db.rs | 17 +++++++++++++++++ 11 files changed, 61 insertions(+), 20 deletions(-) diff --git a/evm_loader/api/src/api_server/handlers/emulate.rs b/evm_loader/api/src/api_server/handlers/emulate.rs index 962cdaa20..84d5d89f5 100644 --- a/evm_loader/api/src/api_server/handlers/emulate.rs +++ b/evm_loader/api/src/api_server/handlers/emulate.rs @@ -15,7 +15,7 @@ pub async fn emulate( ) -> (StatusCode, Json) { let tx = emulate_request.tx_params.into(); - let rpc_client = match context::build_rpc_client(&state.config, emulate_request.slot) { + let rpc_client = match context::build_rpc_client(&state.config, emulate_request.slot).await { Ok(rpc_client) => rpc_client, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; diff --git a/evm_loader/api/src/api_server/handlers/get_ether_account_data.rs b/evm_loader/api/src/api_server/handlers/get_ether_account_data.rs index 2ab577298..d26a02c73 100644 --- a/evm_loader/api/src/api_server/handlers/get_ether_account_data.rs +++ b/evm_loader/api/src/api_server/handlers/get_ether_account_data.rs @@ -14,7 +14,7 @@ pub async fn get_ether_account_data( Query(req_params): Query, State(state): State, ) -> (StatusCode, Json) { - let rpc_client = match context::build_rpc_client(&state.config, req_params.slot) { + let rpc_client = match context::build_rpc_client(&state.config, req_params.slot).await { Ok(rpc_client) => rpc_client, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; diff --git a/evm_loader/api/src/api_server/handlers/get_storage_at.rs b/evm_loader/api/src/api_server/handlers/get_storage_at.rs index 57559cc4f..2ebb11e33 100644 --- a/evm_loader/api/src/api_server/handlers/get_storage_at.rs +++ b/evm_loader/api/src/api_server/handlers/get_storage_at.rs @@ -15,7 +15,7 @@ pub async fn get_storage_at( Query(req_params): Query, State(state): State, ) -> (StatusCode, Json) { - let rpc_client = match context::build_rpc_client(&state.config, req_params.slot) { + let rpc_client = match context::build_rpc_client(&state.config, req_params.slot).await { Ok(rpc_client) => rpc_client, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; diff --git a/evm_loader/api/src/api_server/handlers/mod.rs b/evm_loader/api/src/api_server/handlers/mod.rs index 6ba074f6c..9887388d7 100644 --- a/evm_loader/api/src/api_server/handlers/mod.rs +++ b/evm_loader/api/src/api_server/handlers/mod.rs @@ -14,6 +14,7 @@ use crate::{Config, Context, NeonApiResult}; use crate::types::request_models::EmulationParamsRequestModel; use std::net::AddrParseError; use std::str::FromStr; +use tracing::error; pub mod emulate; pub mod emulate_hash; @@ -133,6 +134,7 @@ fn process_result( } fn process_error(status_code: StatusCode, e: &NeonError) -> (StatusCode, Json) { + error!("NeonError: {e}"); ( status_code, Json(json!({ diff --git a/evm_loader/api/src/api_server/handlers/trace.rs b/evm_loader/api/src/api_server/handlers/trace.rs index 06cb4974e..1c792f775 100644 --- a/evm_loader/api/src/api_server/handlers/trace.rs +++ b/evm_loader/api/src/api_server/handlers/trace.rs @@ -14,7 +14,7 @@ pub async fn trace( let tx = trace_request.emulate_request.tx_params.into(); let rpc_client = - match context::build_rpc_client(&state.config, trace_request.emulate_request.slot) { + match context::build_rpc_client(&state.config, trace_request.emulate_request.slot).await { Ok(rpc_client) => rpc_client, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; diff --git a/evm_loader/api/src/api_server/handlers/trace_next_block.rs b/evm_loader/api/src/api_server/handlers/trace_next_block.rs index 67d483ec4..454d867ee 100644 --- a/evm_loader/api/src/api_server/handlers/trace_next_block.rs +++ b/evm_loader/api/src/api_server/handlers/trace_next_block.rs @@ -17,7 +17,7 @@ pub async fn trace_next_block( Json(trace_next_block_request): Json, ) -> (StatusCode, Json) { let rpc_client = - match context::build_call_db_client(&state.config, trace_next_block_request.slot) { + match context::build_call_db_client(&state.config, trace_next_block_request.slot).await { Ok(rpc_client) => rpc_client, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; @@ -49,7 +49,7 @@ pub async fn trace_next_block( Err(e) => { return process_error( StatusCode::INTERNAL_SERVER_ERROR, - &errors::NeonError::PostgreError(e), + &errors::NeonError::PostgresError(e), ) } }; diff --git a/evm_loader/cli/src/context.rs b/evm_loader/cli/src/context.rs index 2933f5ca8..eb7cecc59 100644 --- a/evm_loader/cli/src/context.rs +++ b/evm_loader/cli/src/context.rs @@ -34,10 +34,13 @@ pub async fn create_from_config_and_options<'a>( } _ => { if let Some(slot) = slot { - Arc::new(CallDbClient::new( - config.db_config.as_ref().expect("db-config not found"), - *slot, - )) + Arc::new( + CallDbClient::new( + config.db_config.as_ref().expect("db-config not found"), + *slot, + ) + .await?, + ) } else { Arc::new(RpcClient::new_with_commitment( config.json_rpc_url.clone(), diff --git a/evm_loader/lib/src/context.rs b/evm_loader/lib/src/context.rs index d9ff8f729..2eb38090c 100644 --- a/evm_loader/lib/src/context.rs +++ b/evm_loader/lib/src/context.rs @@ -69,12 +69,12 @@ pub fn build_signer(config: &Config) -> Result, NeonError> { } /// # Errors -pub fn build_rpc_client( +pub async fn build_rpc_client( config: &Config, slot: Option, ) -> Result, NeonError> { if let Some(slot) = slot { - return build_call_db_client(config, slot); + return build_call_db_client(config, slot).await; } Ok(Arc::new(RpcClient::new_with_commitment( @@ -84,10 +84,13 @@ pub fn build_rpc_client( } /// # Errors -pub fn build_call_db_client(config: &Config, slot: u64) -> Result, NeonError> { +pub async fn build_call_db_client( + config: &Config, + slot: u64, +) -> Result, NeonError> { let config = config .db_config .clone() .ok_or(NeonError::InvalidChDbConfig)?; - Ok(Arc::new(CallDbClient::new(&config, slot))) + Ok(Arc::new(CallDbClient::new(&config, slot).await?)) } diff --git a/evm_loader/lib/src/errors.rs b/evm_loader/lib/src/errors.rs index 0ba461db0..207624186 100644 --- a/evm_loader/lib/src/errors.rs +++ b/evm_loader/lib/src/errors.rs @@ -13,7 +13,7 @@ use solana_sdk::signer::SignerError as SolanaSignerError; use thiserror::Error; use crate::commands::init_environment::EnvironmentError; -use crate::types::PgError; +use crate::types::{ChError, PgError}; /// Errors that may be returned by the neon-cli program. #[derive(Debug, Error)] @@ -94,9 +94,13 @@ pub enum NeonError { #[error("Hex Error. {0}")] FromHexError(#[from] hex::FromHexError), #[error("PostgreSQL Error: {0}")] - PostgreError(#[from] PgError), + PostgresError(#[from] PgError), #[error("Panic: {0}")] Panic(String), + #[error("ClickHouse: {0}")] + ClickHouse(ChError), + #[error("Slot {0} is less than earliest_rooted_slot={1}")] + EarlySlot(u64, u64), } impl NeonError { @@ -131,7 +135,9 @@ impl NeonError { NeonError::IncorrectAddress(_) => 248, NeonError::IncorrectIndex(_) => 249, NeonError::TxParametersParsingError(_) => 250, - NeonError::PostgreError(_) => 251, + NeonError::PostgresError(_) => 251, + NeonError::ClickHouse(_) => 252, + NeonError::EarlySlot(_, _) => 253, } } } diff --git a/evm_loader/lib/src/rpc/db_call_client.rs b/evm_loader/lib/src/rpc/db_call_client.rs index 2dc75e27d..7f54f5d19 100644 --- a/evm_loader/lib/src/rpc/db_call_client.rs +++ b/evm_loader/lib/src/rpc/db_call_client.rs @@ -1,5 +1,6 @@ use super::{e, Rpc}; use crate::types::{ChDbConfig, TracerDb, TxParams}; +use crate::NeonError; use async_trait::async_trait; use solana_client::{ client_error::Result as ClientResult, @@ -27,12 +28,21 @@ pub struct CallDbClient { } impl CallDbClient { - pub fn new(config: &ChDbConfig, slot: u64) -> Self { + pub async fn new(config: &ChDbConfig, slot: u64) -> Result { let db = TracerDb::new(config); - Self { + + let earliest_rooted_slot = db + .get_earliest_rooted_slot() + .await + .map_err(NeonError::ClickHouse)?; + if slot < earliest_rooted_slot { + return Err(NeonError::EarlySlot(slot, earliest_rooted_slot)); + } + + Ok(Self { slot, tracer_db: db, - } + }) } } diff --git a/evm_loader/lib/src/types/tracer_ch_db.rs b/evm_loader/lib/src/types/tracer_ch_db.rs index 2380063e4..2b653c4f9 100644 --- a/evm_loader/lib/src/types/tracer_ch_db.rs +++ b/evm_loader/lib/src/types/tracer_ch_db.rs @@ -168,6 +168,23 @@ impl ClickHouseDb { result } + pub async fn get_earliest_rooted_slot(&self) -> ChResult { + let time_start = Instant::now(); + let query = "SELECT min(slot) FROM events.rooted_slots"; + let result = self + .client + .query(query) + .fetch_one::() + .await + .map_err(std::convert::Into::into); + let execution_time = Instant::now().duration_since(time_start); + info!( + "get_earliest_rooted_slot sql returned {result:?}, time: {} sec", + execution_time.as_secs_f64() + ); + result + } + pub async fn get_latest_block(&self) -> ChResult { let time_start = Instant::now(); let query = "SELECT max(slot) FROM events.update_slot";