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

NDEV-2184: Report error when requested too early slot #195

Merged
merged 2 commits into from
Sep 15, 2023
Merged
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
2 changes: 1 addition & 1 deletion evm_loader/api/src/api_server/handlers/emulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub async fn emulate(
) -> (StatusCode, Json<serde_json::Value>) {
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),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub async fn get_ether_account_data(
Query(req_params): Query<GetEtherRequest>,
State(state): State<NeonApiState>,
) -> (StatusCode, Json<serde_json::Value>) {
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),
};
Expand Down
2 changes: 1 addition & 1 deletion evm_loader/api/src/api_server/handlers/get_storage_at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub async fn get_storage_at(
Query(req_params): Query<GetStorageAtRequest>,
State(state): State<NeonApiState>,
) -> (StatusCode, Json<serde_json::Value>) {
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),
};
Expand Down
2 changes: 2 additions & 0 deletions evm_loader/api/src/api_server/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -133,6 +134,7 @@ fn process_result<T: Serialize>(
}

fn process_error(status_code: StatusCode, e: &NeonError) -> (StatusCode, Json<Value>) {
error!("NeonError: {e}");
(
status_code,
Json(json!({
Expand Down
2 changes: 1 addition & 1 deletion evm_loader/api/src/api_server/handlers/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
};
Expand Down
4 changes: 2 additions & 2 deletions evm_loader/api/src/api_server/handlers/trace_next_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub async fn trace_next_block(
Json(trace_next_block_request): Json<TraceNextBlockRequestModel>,
) -> (StatusCode, Json<serde_json::Value>) {
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),
};
Expand Down Expand Up @@ -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),
)
}
};
Expand Down
11 changes: 7 additions & 4 deletions evm_loader/cli/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
11 changes: 7 additions & 4 deletions evm_loader/lib/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ pub fn build_signer(config: &Config) -> Result<Box<dyn Signer>, NeonError> {
}

/// # Errors
pub fn build_rpc_client(
pub async fn build_rpc_client(
config: &Config,
slot: Option<u64>,
) -> Result<Arc<dyn rpc::Rpc>, 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(
Expand All @@ -84,10 +84,13 @@ pub fn build_rpc_client(
}

/// # Errors
pub fn build_call_db_client(config: &Config, slot: u64) -> Result<Arc<dyn rpc::Rpc>, NeonError> {
pub async fn build_call_db_client(
config: &Config,
slot: u64,
) -> Result<Arc<dyn rpc::Rpc>, 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?))
}
12 changes: 9 additions & 3 deletions evm_loader/lib/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
}
}
}
Expand Down
16 changes: 13 additions & 3 deletions evm_loader/lib/src/rpc/db_call_client.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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<Self, NeonError> {
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,
}
})
}
}

Expand Down
18 changes: 17 additions & 1 deletion evm_loader/lib/src/types/tracer_ch_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ impl TryInto<Account> 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());
Expand Down Expand Up @@ -169,6 +168,23 @@ impl ClickHouseDb {
result
}

pub async fn get_earliest_rooted_slot(&self) -> ChResult<u64> {
let time_start = Instant::now();
let query = "SELECT min(slot) FROM events.rooted_slots";
let result = self
.client
.query(query)
.fetch_one::<u64>()
.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<u64> {
let time_start = Instant::now();
let query = "SELECT max(slot) FROM events.update_slot";
Expand Down