diff --git a/evm_loader/Cargo.lock b/evm_loader/Cargo.lock index 072bdc8f4..34163a487 100644 --- a/evm_loader/Cargo.lock +++ b/evm_loader/Cargo.lock @@ -1735,6 +1735,18 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "enum_dispatch" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e" +dependencies = [ + "once_cell", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.28", +] + [[package]] name = "env_logger" version = "0.9.3" @@ -2876,8 +2888,8 @@ dependencies = [ "num-traits", "shank", "solana-program", - "spl-associated-token-account 1.1.3", - "spl-token 3.5.0", + "spl-associated-token-account 2.2.0", + "spl-token 4.0.0", "thiserror", ] @@ -2988,6 +3000,7 @@ dependencies = [ "build-info", "build-info-build", "clickhouse", + "enum_dispatch", "ethnum", "evm-loader", "goblin 0.6.1", diff --git a/evm_loader/api/src/api_context.rs b/evm_loader/api/src/api_context.rs deleted file mode 100644 index 1d040a2d1..000000000 --- a/evm_loader/api/src/api_context.rs +++ /dev/null @@ -1,26 +0,0 @@ -use crate::NeonApiState; -use neon_lib::rpc::CallDbClient; -use neon_lib::{rpc, NeonError}; -use std::sync::Arc; - -pub async fn build_rpc_client( - state: &NeonApiState, - slot: Option, - tx_index_in_block: Option, -) -> Result, NeonError> { - if let Some(slot) = slot { - build_call_db_client(state, slot, tx_index_in_block).await - } else { - Ok(state.rpc_client.clone()) - } -} - -pub async fn build_call_db_client( - state: &NeonApiState, - slot: u64, - tx_index_in_block: Option, -) -> Result, NeonError> { - Ok(Arc::new( - CallDbClient::new(state.tracer_db.clone(), slot, tx_index_in_block).await?, - )) -} diff --git a/evm_loader/api/src/api_server/handlers/emulate.rs b/evm_loader/api/src/api_server/handlers/emulate.rs index fc5f583a3..d3483efd5 100644 --- a/evm_loader/api/src/api_server/handlers/emulate.rs +++ b/evm_loader/api/src/api_server/handlers/emulate.rs @@ -3,9 +3,7 @@ use actix_web::{http::StatusCode, post, web::Json, Responder}; use std::convert::Into; use crate::api_server::handlers::process_error; -use crate::{ - api_context, commands::emulate as EmulateCommand, types::EmulateApiRequest, NeonApiState, -}; +use crate::{commands::emulate as EmulateCommand, types::EmulateApiRequest, NeonApiState}; use super::process_result; @@ -19,19 +17,14 @@ pub async fn emulate( let slot = emulate_request.slot; let index = emulate_request.tx_index_in_block; - let rpc_client = match api_context::build_rpc_client(&state, slot, index).await { - Ok(rpc_client) => rpc_client, + let rpc = match state.build_rpc(slot, index).await { + Ok(rpc) => rpc, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; process_result( - &EmulateCommand::execute( - rpc_client.as_ref(), - state.config.evm_loader, - emulate_request.body, - None, - ) - .await - .map_err(Into::into), + &EmulateCommand::execute(&rpc, state.config.evm_loader, emulate_request.body, None) + .await + .map_err(Into::into), ) } diff --git a/evm_loader/api/src/api_server/handlers/get_balance.rs b/evm_loader/api/src/api_server/handlers/get_balance.rs index ef2574582..1c7fca2b5 100644 --- a/evm_loader/api/src/api_server/handlers/get_balance.rs +++ b/evm_loader/api/src/api_server/handlers/get_balance.rs @@ -1,6 +1,6 @@ use crate::api_server::handlers::process_error; use crate::commands::get_balance as GetBalanceCommand; -use crate::{api_context, types::GetBalanceRequest, NeonApiState}; +use crate::{types::GetBalanceRequest, NeonApiState}; use actix_request_identifier::RequestId; use actix_web::web::Json; use actix_web::{http::StatusCode, post, Responder}; @@ -15,18 +15,14 @@ pub async fn get_balance( request_id: RequestId, Json(req_params): Json, ) -> impl Responder { - let rpc_client = match api_context::build_rpc_client(&state, req_params.slot, None).await { - Ok(rpc_client) => rpc_client, + let rpc = match state.build_rpc(req_params.slot, None).await { + Ok(rpc) => rpc, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; process_result( - &GetBalanceCommand::execute( - rpc_client.as_ref(), - &state.config.evm_loader, - &req_params.account, - ) - .await - .map_err(Into::into), + &GetBalanceCommand::execute(&rpc, &state.config.evm_loader, &req_params.account) + .await + .map_err(Into::into), ) } diff --git a/evm_loader/api/src/api_server/handlers/get_config.rs b/evm_loader/api/src/api_server/handlers/get_config.rs index 34aedb8e5..ce0fdf7b3 100644 --- a/evm_loader/api/src/api_server/handlers/get_config.rs +++ b/evm_loader/api/src/api_server/handlers/get_config.rs @@ -1,5 +1,5 @@ use crate::api_server::handlers::process_error; -use crate::{api_context, NeonApiState}; +use crate::NeonApiState; use actix_request_identifier::RequestId; use actix_web::routes; use actix_web::{http::StatusCode, Responder}; @@ -14,13 +14,13 @@ use super::process_result; #[post("/config")] #[get("/config")] pub async fn get_config(state: NeonApiState, request_id: RequestId) -> impl Responder { - let rpc_client = match api_context::build_rpc_client(&state, None, None).await { - Ok(rpc_client) => rpc_client, + let rpc = match state.build_rpc(None, None).await { + Ok(rpc) => rpc, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; process_result( - &GetConfigCommand::execute(rpc_client.as_ref(), state.config.evm_loader) + &GetConfigCommand::execute(&rpc, state.config.evm_loader) .await .map_err(Into::into), ) diff --git a/evm_loader/api/src/api_server/handlers/get_contract.rs b/evm_loader/api/src/api_server/handlers/get_contract.rs index ab5294196..e8e96d686 100644 --- a/evm_loader/api/src/api_server/handlers/get_contract.rs +++ b/evm_loader/api/src/api_server/handlers/get_contract.rs @@ -1,6 +1,6 @@ use crate::api_server::handlers::process_error; use crate::commands::get_contract as GetContractCommand; -use crate::{api_context, types::GetContractRequest, NeonApiState}; +use crate::{types::GetContractRequest, NeonApiState}; use actix_request_identifier::RequestId; use actix_web::post; use actix_web::web::Json; @@ -16,18 +16,14 @@ pub async fn get_contract( request_id: RequestId, Json(req_params): Json, ) -> impl Responder { - let rpc_client = match api_context::build_rpc_client(&state, req_params.slot, None).await { - Ok(rpc_client) => rpc_client, + let rpc = match state.build_rpc(req_params.slot, None).await { + Ok(rpc) => rpc, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; process_result( - &GetContractCommand::execute( - rpc_client.as_ref(), - &state.config.evm_loader, - &req_params.contract, - ) - .await - .map_err(Into::into), + &GetContractCommand::execute(&rpc, &state.config.evm_loader, &req_params.contract) + .await + .map_err(Into::into), ) } diff --git a/evm_loader/api/src/api_server/handlers/get_holder.rs b/evm_loader/api/src/api_server/handlers/get_holder.rs index 36385b1a6..f9dc34400 100644 --- a/evm_loader/api/src/api_server/handlers/get_holder.rs +++ b/evm_loader/api/src/api_server/handlers/get_holder.rs @@ -1,6 +1,6 @@ use crate::api_server::handlers::process_error; use crate::commands::get_holder as GetHolderCommand; -use crate::{api_context, types::GetHolderRequest, NeonApiState}; +use crate::{types::GetHolderRequest, NeonApiState}; use actix_request_identifier::RequestId; use actix_web::post; use actix_web::web::Json; @@ -16,18 +16,14 @@ pub async fn get_holder_account_data( request_id: RequestId, Json(req_params): Json, ) -> impl Responder { - let rpc_client = match api_context::build_rpc_client(&state, req_params.slot, None).await { - Ok(rpc_client) => rpc_client, + let rpc = match state.build_rpc(req_params.slot, None).await { + Ok(rpc) => rpc, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; process_result( - &GetHolderCommand::execute( - rpc_client.as_ref(), - &state.config.evm_loader, - req_params.pubkey, - ) - .await - .map_err(Into::into), + &GetHolderCommand::execute(&rpc, &state.config.evm_loader, req_params.pubkey) + .await + .map_err(Into::into), ) } 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 71440e49b..c1ed2b5d0 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 @@ -1,5 +1,5 @@ use crate::api_server::handlers::process_error; -use crate::{api_context, types::GetStorageAtRequest, NeonApiState}; +use crate::{types::GetStorageAtRequest, NeonApiState}; use actix_request_identifier::RequestId; use actix_web::post; use actix_web::web::Json; @@ -17,14 +17,14 @@ pub async fn get_storage_at( request_id: RequestId, Json(req_params): Json, ) -> impl Responder { - let rpc_client = match api_context::build_rpc_client(&state, req_params.slot, None).await { - Ok(rpc_client) => rpc_client, + let rpc = match state.build_rpc(req_params.slot, None).await { + Ok(rpc) => rpc, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; process_result( &GetStorageAtCommand::execute( - rpc_client.as_ref(), + &rpc, &state.config.evm_loader, req_params.contract, req_params.index, diff --git a/evm_loader/api/src/api_server/handlers/trace.rs b/evm_loader/api/src/api_server/handlers/trace.rs index 586811a56..d766a03b5 100644 --- a/evm_loader/api/src/api_server/handlers/trace.rs +++ b/evm_loader/api/src/api_server/handlers/trace.rs @@ -4,7 +4,7 @@ use std::convert::Into; use crate::api_server::handlers::process_error; use crate::commands::trace::trace_transaction; -use crate::{api_context, types::EmulateApiRequest, NeonApiState}; +use crate::{types::EmulateApiRequest, NeonApiState}; use super::process_result; @@ -18,18 +18,14 @@ pub async fn trace( let slot = trace_request.slot; let index = trace_request.tx_index_in_block; - let rpc_client = match api_context::build_rpc_client(&state, slot, index).await { - Ok(rpc_client) => rpc_client, + let rpc = match state.build_rpc(slot, index).await { + Ok(rpc) => rpc, Err(e) => return process_error(StatusCode::BAD_REQUEST, &e), }; process_result( - &trace_transaction( - rpc_client.as_ref(), - state.config.evm_loader, - trace_request.body, - ) - .await - .map_err(Into::into), + &trace_transaction(&rpc, state.config.evm_loader, trace_request.body) + .await + .map_err(Into::into), ) } diff --git a/evm_loader/api/src/api_server/state.rs b/evm_loader/api/src/api_server/state.rs index 1205a9b00..9c9f60fc3 100644 --- a/evm_loader/api/src/api_server/state.rs +++ b/evm_loader/api/src/api_server/state.rs @@ -1,24 +1,34 @@ use crate::Config; +use neon_lib::rpc::{CallDbClient, CloneRpcClient, RpcEnum}; use neon_lib::types::TracerDb; -use solana_client::nonblocking::rpc_client::RpcClient; -use std::sync::Arc; +use neon_lib::NeonError; pub struct State { pub tracer_db: TracerDb, - pub rpc_client: Arc, + pub rpc_client: CloneRpcClient, pub config: Config, } impl State { pub fn new(config: Config) -> Self { - let db_config = config.db_config.as_ref().expect("db-config not found"); Self { - tracer_db: TracerDb::new(db_config), - rpc_client: Arc::new(RpcClient::new_with_commitment( - config.json_rpc_url.clone(), - config.commitment, - )), + tracer_db: TracerDb::new(&config), + rpc_client: config.build_clone_solana_rpc_client(), config, } } + + pub async fn build_rpc( + &self, + slot: Option, + tx_index_in_block: Option, + ) -> Result { + Ok(if let Some(slot) = slot { + RpcEnum::CallDbClient( + CallDbClient::new(self.tracer_db.clone(), slot, tx_index_in_block).await?, + ) + } else { + RpcEnum::CloneRpcClient(self.rpc_client.clone()) + }) + } } diff --git a/evm_loader/api/src/main.rs b/evm_loader/api/src/main.rs index 5aebb4978..eb2f84368 100644 --- a/evm_loader/api/src/main.rs +++ b/evm_loader/api/src/main.rs @@ -1,6 +1,5 @@ #![deny(warnings)] #![deny(clippy::all, clippy::pedantic)] -mod api_context; mod api_options; mod api_server; #[allow(clippy::module_name_repetitions)] @@ -12,7 +11,6 @@ use actix_web::HttpServer; use api_server::handlers::NeonApiError; pub use neon_lib::commands; pub use neon_lib::config; -pub use neon_lib::context; pub use neon_lib::errors; pub use neon_lib::types; use tracing_appender::non_blocking::NonBlockingBuilder; @@ -31,7 +29,6 @@ use crate::api_server::handlers::get_storage_at::get_storage_at; use crate::api_server::handlers::trace::trace; use crate::build_info::get_build_info; pub use config::Config; -pub use context::Context; use tracing::info; type NeonApiResult = Result; diff --git a/evm_loader/cli/src/main.rs b/evm_loader/cli/src/main.rs index 73b12a703..4f26347b8 100644 --- a/evm_loader/cli/src/main.rs +++ b/evm_loader/cli/src/main.rs @@ -12,197 +12,208 @@ use neon_lib::{ cancel_trx, collect_treasury, emulate, get_balance, get_config, get_contract, get_holder, get_neon_elf, get_storage_at, init_environment, trace, }, - errors, rpc, types::{BalanceAddress, EmulateRequest}, + Config, }; use clap::ArgMatches; -pub use config::Config; use std::io::Read; use ethnum::U256; use log::debug; use serde_json::json; use solana_clap_utils::input_parsers::{pubkey_of, value_of}; -use solana_client::nonblocking::rpc_client::RpcClient; use tokio::time::Instant; -pub use neon_lib::context::*; -use neon_lib::rpc::CallDbClient; - use crate::build_info::get_build_info; -use crate::errors::NeonError; use evm_loader::types::Address; +use neon_lib::errors::NeonError; +use neon_lib::rpc::{CallDbClient, RpcEnum}; use neon_lib::types::TracerDb; +use solana_clap_utils::keypair::signer_from_path; +use solana_sdk::signature::Signer; type NeonCliResult = Result; -async fn run<'a>(options: &'a ArgMatches<'a>) -> NeonCliResult { - let slot: Option = options - .value_of("slot") - .map(|slot_str| slot_str.parse().expect("slot parse error")); - - let config = config::create(options)?; - - let (cmd, params) = options.subcommand(); - - let rpc_client: Box = if let Some(slot) = slot { - Box::new( - CallDbClient::new( - TracerDb::new(config.db_config.as_ref().expect("db-config not found")), - slot, - None, - ) - .await?, - ) - } else { - Box::new(RpcClient::new_with_commitment( - config.json_rpc_url.clone(), - config.commitment, - )) - }; - - let context = Context::new(&*rpc_client, &config); - - execute(cmd, params, &config, &context).await -} - -fn print_result(result: &NeonCliResult) { - let logs = { - let context = logs::CONTEXT.lock().unwrap(); - context.clone() - }; - - let result = match result { - Ok(value) => serde_json::json!({ - "result": "success", - "value": value, - "logs": logs - }), - Err(e) => serde_json::json!({ - "result": "error", - "error": e.to_string(), - "logs": logs - }), - }; - - println!("{}", serde_json::to_string_pretty(&result).unwrap()); -} - -#[tokio::main(flavor = "current_thread")] -async fn main() { - let time_start = Instant::now(); - - let options = program_options::parse(); - - logs::init(&options).expect("logs init error"); - std::panic::set_hook(Box::new(|info| { - let message = std::format!("Panic: {info}"); - print_result(&Err(NeonError::Panic(message))); - })); - - debug!("{}", get_build_info()); - - let result = run(&options).await; - - let execution_time = Instant::now().duration_since(time_start); - log::info!("execution time: {} sec", execution_time.as_secs_f64()); - print_result(&result); - if let Err(e) = result { - std::process::exit(e.error_code()); - }; -} - #[allow(clippy::too_many_lines)] -async fn execute<'a>( - cmd: &str, - params: Option<&'a ArgMatches<'a>>, - config: &'a Config, - context: &'a Context<'_>, -) -> NeonCliResult { - match (cmd, params) { +async fn run(options: &ArgMatches<'_>) -> NeonCliResult { + let config = &config::create(options)?; + + match options.subcommand() { ("emulate", Some(_)) => { + let rpc = build_rpc(options, config).await?; + let request = read_tx_from_stdin()?; - emulate::execute(context.rpc_client, config.evm_loader, request, None) + emulate::execute(&rpc, config.evm_loader, request, None) .await .map(|result| json!(result)) } ("trace", Some(_)) => { + let rpc = build_rpc(options, config).await?; + let request = read_tx_from_stdin()?; - trace::trace_transaction(context.rpc_client, config.evm_loader, request) + trace::trace_transaction(&rpc, config.evm_loader, request) .await .map(|trace| json!(trace)) } ("get-ether-account-data", Some(params)) => { + let rpc = build_rpc(options, config).await?; + let address = address_of(params, "ether").unwrap(); let chain_id = value_of(params, "chain_id").unwrap(); let account = BalanceAddress { address, chain_id }; let accounts = std::slice::from_ref(&account); - get_balance::execute(context.rpc_client, &config.evm_loader, accounts) + get_balance::execute(&rpc, &config.evm_loader, accounts) .await .map(|result| json!(result)) } ("get-contract-account-data", Some(params)) => { + let rpc = build_rpc(options, config).await?; + let account = address_of(params, "address").unwrap(); let accounts = std::slice::from_ref(&account); - get_contract::execute(context.rpc_client, &config.evm_loader, accounts) + get_contract::execute(&rpc, &config.evm_loader, accounts) .await .map(|result| json!(result)) } ("get-holder-account-data", Some(params)) => { + let rpc = build_rpc(options, config).await?; + let account = pubkey_of(params, "account").unwrap(); - get_holder::execute(context.rpc_client, &config.evm_loader, account) + get_holder::execute(&rpc, &config.evm_loader, account) .await .map(|result| json!(result)) } ("cancel-trx", Some(params)) => { + let rpc_client = config.build_solana_rpc_client(); + let signer = build_signer(config)?; + let storage_account = pubkey_of(params, "storage_account").expect("storage_account parse error"); - cancel_trx::execute( - context.rpc_client, - context.signer()?.as_ref(), - config.evm_loader, - &storage_account, - ) - .await - .map(|result| json!(result)) + cancel_trx::execute(&rpc_client, &*signer, config.evm_loader, &storage_account) + .await + .map(|result| json!(result)) } ("neon-elf-params", Some(params)) => { + let rpc = build_rpc(options, config).await?; + let program_location = params.value_of("program_location"); - get_neon_elf::execute(config, context, program_location) + get_neon_elf::execute(config, &rpc, program_location) + .await + .map(|result| json!(result)) + } + ("collect-treasury", Some(_)) => { + let rpc_client = config.build_clone_solana_rpc_client(); + let signer = build_signer(config)?; + + collect_treasury::execute(config, &rpc_client, &*signer) .await .map(|result| json!(result)) } - ("collect-treasury", Some(_)) => collect_treasury::execute(config, context) - .await - .map(|result| json!(result)), ("init-environment", Some(params)) => { + let rpc_client = config.build_clone_solana_rpc_client(); + let signer = build_signer(config)?; + let file = params.value_of("file"); let send_trx = params.is_present("send-trx"); let force = params.is_present("force"); let keys_dir = params.value_of("keys-dir"); - init_environment::execute(config, context, send_trx, force, keys_dir, file) - .await - .map(|result| json!(result)) + + init_environment::execute( + config, + &rpc_client, + &*signer, + send_trx, + force, + keys_dir, + file, + ) + .await + .map(|result| json!(result)) } ("get-storage-at", Some(params)) => { + let rpc = build_rpc(options, config).await?; + let contract_id = address_of(params, "contract_id").expect("contract_it parse error"); let index = u256_of(params, "index").expect("index parse error"); - get_storage_at::execute(context.rpc_client, &config.evm_loader, contract_id, index) + + get_storage_at::execute(&rpc, &config.evm_loader, contract_id, index) .await .map(|hash| json!(hex::encode(hash.0))) } - ("config", Some(_)) => get_config::execute(context.rpc_client, config.evm_loader) - .await - .map(|result| json!(result)), + ("config", Some(_)) => { + let rpc = build_rpc(options, config).await?; + + get_config::execute(&rpc, config.evm_loader) + .await + .map(|result| json!(result)) + } _ => unreachable!(), } } +async fn build_rpc(options: &ArgMatches<'_>, config: &Config) -> Result { + let slot: Option = options + .value_of("slot") + .map(|slot_str| slot_str.parse().expect("slot parse error")); + + Ok(if let Some(slot) = slot { + RpcEnum::CallDbClient(CallDbClient::new(TracerDb::new(config), slot, None).await?) + } else { + RpcEnum::CloneRpcClient(config.build_clone_solana_rpc_client()) + }) +} + +fn print_result(result: &NeonCliResult) { + let logs = { + let context = logs::CONTEXT.lock().unwrap(); + context.clone() + }; + + let result = match result { + Ok(value) => json!({ + "result": "success", + "value": value, + "logs": logs + }), + Err(e) => json!({ + "result": "error", + "error": e.to_string(), + "logs": logs + }), + }; + + println!("{}", serde_json::to_string_pretty(&result).unwrap()); +} + +#[tokio::main(flavor = "current_thread")] +async fn main() { + let time_start = Instant::now(); + + let options = program_options::parse(); + + logs::init(&options).expect("logs init error"); + std::panic::set_hook(Box::new(|info| { + let message = std::format!("Panic: {info}"); + print_result(&Err(NeonError::Panic(message))); + })); + + debug!("{}", get_build_info()); + + let result = run(&options).await; + + let execution_time = Instant::now().duration_since(time_start); + log::info!("execution time: {} sec", execution_time.as_secs_f64()); + print_result(&result); + if let Err(e) = result { + std::process::exit(e.error_code()); + }; +} + fn read_tx_from_stdin() -> Result { let mut stdin_buffer = String::new(); std::io::stdin().read_to_string(&mut stdin_buffer)?; @@ -225,3 +236,18 @@ fn u256_of(matches: &ArgMatches<'_>, name: &str) -> Option { U256::from_str_prefixed(value).unwrap() }) } + +/// # Errors +fn build_signer(config: &Config) -> Result, NeonError> { + let mut wallet_manager = None; + + let signer = signer_from_path( + &ArgMatches::default(), + &config.keypair_path, + "keypair", + &mut wallet_manager, + ) + .map_err(|_| NeonError::KeypairNotSpecified)?; + + Ok(signer) +} diff --git a/evm_loader/lib/Cargo.toml b/evm_loader/lib/Cargo.toml index 5de90dcd3..f4a1d6a32 100644 --- a/evm_loader/lib/Cargo.toml +++ b/evm_loader/lib/Cargo.toml @@ -35,6 +35,7 @@ clickhouse = "0.11.5" tracing = "0.1" async-trait = "0.1.73" build-info = "0.0.31" +enum_dispatch = "0.3.12" [build-dependencies] build-info-build = "0.0.31" diff --git a/evm_loader/lib/src/account_storage.rs b/evm_loader/lib/src/account_storage.rs index 9b3694fd1..499b0f8df 100644 --- a/evm_loader/lib/src/account_storage.rs +++ b/evm_loader/lib/src/account_storage.rs @@ -26,6 +26,7 @@ use solana_client::client_error; use solana_sdk::{account::Account, account_info::AccountInfo, pubkey, pubkey::Pubkey}; use crate::commands::get_config::ChainInfo; +use crate::rpc::RpcEnum; use crate::tracing::{AccountOverride, AccountOverrides, BlockOverrides}; use serde_with::{serde_as, DisplayFromStr}; @@ -46,7 +47,7 @@ pub struct SolanaAccount { pub struct EmulatorAccountStorage<'rpc> { pub accounts: RefCell>, pub gas: u64, - rpc_client: &'rpc dyn Rpc, + rpc: &'rpc RpcEnum, program_id: Pubkey, chains: Vec, block_number: u64, @@ -56,7 +57,7 @@ pub struct EmulatorAccountStorage<'rpc> { impl<'rpc> EmulatorAccountStorage<'rpc> { pub async fn new( - rpc_client: &'rpc dyn Rpc, + rpc: &'rpc RpcEnum, program_id: Pubkey, chains: Option>, block_overrides: Option, @@ -65,17 +66,17 @@ impl<'rpc> EmulatorAccountStorage<'rpc> { trace!("backend::new"); let block_number = match block_overrides.as_ref().and_then(|o| o.number) { - None => rpc_client.get_slot().await?, + None => rpc.get_slot().await?, Some(number) => number, }; let block_timestamp = match block_overrides.as_ref().and_then(|o| o.time) { - None => rpc_client.get_block_time(block_number).await?, + None => rpc.get_block_time(block_number).await?, Some(time) => time, }; let chains = match chains { - None => crate::commands::get_config::read_chains(rpc_client, program_id).await?, + None => crate::commands::get_config::read_chains(rpc, program_id).await?, Some(chains) => chains, }; @@ -84,7 +85,7 @@ impl<'rpc> EmulatorAccountStorage<'rpc> { program_id, chains, gas: 0, - rpc_client, + rpc, block_number, block_timestamp, state_overrides, @@ -92,21 +93,14 @@ impl<'rpc> EmulatorAccountStorage<'rpc> { } pub async fn with_accounts( - rpc_client: &'rpc dyn Rpc, + rpc: &'rpc RpcEnum, program_id: Pubkey, accounts: &[Pubkey], chains: Option>, block_overrides: Option, state_overrides: Option, ) -> Result, NeonError> { - let storage = Self::new( - rpc_client, - program_id, - chains, - block_overrides, - state_overrides, - ) - .await?; + let storage = Self::new(rpc, program_id, chains, block_overrides, state_overrides).await?; storage.download_accounts(accounts).await?; @@ -114,7 +108,7 @@ impl<'rpc> EmulatorAccountStorage<'rpc> { } async fn download_accounts(&self, pubkeys: &[Pubkey]) -> Result<(), NeonError> { - let accounts = self.rpc_client.get_multiple_accounts(pubkeys).await?; + let accounts = self.rpc.get_multiple_accounts(pubkeys).await?; let mut cache = self.accounts.borrow_mut(); @@ -146,7 +140,7 @@ impl<'rpc> EmulatorAccountStorage<'rpc> { return Ok(account.data.clone()); } - let response = self.rpc_client.get_account(&pubkey).await?; + let response = self.rpc.get_account(&pubkey).await?; let account = response.value; self.accounts.borrow_mut().insert( diff --git a/evm_loader/lib/src/commands/cancel_trx.rs b/evm_loader/lib/src/commands/cancel_trx.rs index b7663eeec..22e288c41 100644 --- a/evm_loader/lib/src/commands/cancel_trx.rs +++ b/evm_loader/lib/src/commands/cancel_trx.rs @@ -2,6 +2,7 @@ use evm_loader::account::StateAccount; use log::info; use serde::{Deserialize, Serialize}; +use solana_client::nonblocking::rpc_client::RpcClient; use solana_sdk::{ instruction::{AccountMeta, Instruction}, pubkey::Pubkey, @@ -9,9 +10,7 @@ use solana_sdk::{ signer::Signer, }; -use crate::{ - account_storage::account_info, commands::send_transaction, rpc::Rpc, NeonError, NeonResult, -}; +use crate::{account_storage::account_info, commands::send_transaction, NeonResult}; #[derive(Debug, Serialize, Deserialize)] pub struct CancelTrxReturn { @@ -19,14 +18,12 @@ pub struct CancelTrxReturn { } pub async fn execute( - rpc_client: &dyn Rpc, + rpc_client: &RpcClient, signer: &dyn Signer, evm_loader: Pubkey, storage_account: &Pubkey, ) -> NeonResult { - let Some(mut acc) = rpc_client.get_account(storage_account).await?.value else { - return Err(NeonError::AccountNotFound(*storage_account)) - }; + let mut acc = rpc_client.get_account(storage_account).await?; let storage_info = account_info(storage_account, &mut acc); let storage = StateAccount::from_account(&evm_loader, storage_info)?; diff --git a/evm_loader/lib/src/commands/collect_treasury.rs b/evm_loader/lib/src/commands/collect_treasury.rs index 8938e15d8..2059ed187 100644 --- a/evm_loader/lib/src/commands/collect_treasury.rs +++ b/evm_loader/lib/src/commands/collect_treasury.rs @@ -1,12 +1,11 @@ -use crate::rpc::check_account_for_fee; +use crate::rpc::{check_account_for_fee, CloneRpcClient, Rpc}; use crate::{ - commands::get_neon_elf::read_elf_parameters_from_account, errors::NeonError, Config, Context, - NeonResult, + commands::get_neon_elf::read_elf_parameters_from_account, errors::NeonError, Config, NeonResult, }; use evm_loader::account::{MainTreasury, Treasury}; use log::{info, warn}; use serde::{Deserialize, Serialize}; -use solana_client::nonblocking::rpc_client::RpcClient; +use solana_sdk::signature::Signer; use solana_sdk::{ instruction::{AccountMeta, Instruction}, message::Message, @@ -14,6 +13,7 @@ use solana_sdk::{ transaction::Transaction, }; use spl_token::instruction::sync_native; +use std::ops::Deref; #[derive(Debug, Serialize, Deserialize)] pub struct CollectTreasuryReturn { @@ -21,9 +21,12 @@ pub struct CollectTreasuryReturn { pub balance: u64, } -pub async fn execute(config: &Config, context: &Context<'_>) -> NeonResult { - let neon_params = read_elf_parameters_from_account(config, context).await?; - let signer = context.signer()?; +pub async fn execute( + config: &Config, + rpc_client: &CloneRpcClient, + signer: &dyn Signer, +) -> NeonResult { + let neon_params = read_elf_parameters_from_account(config, &rpc_client.clone().into()).await?; let pool_count: u32 = neon_params .get("NEON_TREASURY_POOL_COUNT") @@ -34,23 +37,15 @@ pub async fn execute(config: &Config, context: &Context<'_>) -> NeonResult() - .expect("cast to solana_client::rpc_client::RpcClient error"); - for i in 0..pool_count { let (aux_balance_address, _) = Treasury::address(&config.evm_loader, i); - if let Some(aux_balance_account) = context - .rpc_client + if let Some(aux_balance_account) = rpc_client .get_account_with_commitment(&aux_balance_address, config.commitment) .await? .value { - let minimal_balance = context - .rpc_client + let minimal_balance = rpc_client .get_minimum_balance_for_rent_exemption(aux_balance_account.data.len()) .await?; let available_lamports = aux_balance_account.lamports.saturating_sub(minimal_balance); @@ -71,15 +66,14 @@ pub async fn execute(config: &Config, context: &Context<'_>) -> NeonResult) -> NeonResult, @@ -65,7 +65,7 @@ pub async fn execute( .and_then(|t| t.state_overrides.clone()); let mut storage = EmulatorAccountStorage::with_accounts( - rpc_client, + rpc, program_id, &config.accounts, config.chains, @@ -76,7 +76,7 @@ pub async fn execute( let step_limit = config.step_limit.unwrap_or(100000); - setup_emulator_syscall_stubs(rpc_client).await?; + setup_emulator_syscall_stubs(rpc).await?; emulate_trx(config.tx, &mut storage, step_limit, tracer).await } diff --git a/evm_loader/lib/src/commands/get_balance.rs b/evm_loader/lib/src/commands/get_balance.rs index 760018ee9..e1d0da6c5 100644 --- a/evm_loader/lib/src/commands/get_balance.rs +++ b/evm_loader/lib/src/commands/get_balance.rs @@ -6,6 +6,7 @@ use solana_sdk::{account::Account, pubkey::Pubkey}; use crate::{account_storage::account_info, rpc::Rpc, types::BalanceAddress, NeonResult}; +use crate::rpc::RpcEnum; use serde_with::{serde_as, DisplayFromStr}; use super::get_config::ChainInfo; @@ -91,14 +92,14 @@ fn is_legacy_chain_id(id: u64, chains: &[ChainInfo]) -> bool { } pub async fn execute( - rpc_client: &dyn Rpc, + rpc: &RpcEnum, program_id: &Pubkey, address: &[BalanceAddress], ) -> NeonResult> { - let chain_ids = super::get_config::read_chains(rpc_client, *program_id).await?; + let chain_ids = super::get_config::read_chains(rpc, *program_id).await?; let pubkeys: Vec<_> = address.iter().map(|a| a.find_pubkey(program_id)).collect(); - let accounts = rpc_client.get_multiple_accounts(&pubkeys).await?; + let accounts = rpc.get_multiple_accounts(&pubkeys).await?; let mut result = Vec::with_capacity(accounts.len()); for (key, account) in address.iter().zip(accounts) { @@ -106,7 +107,7 @@ pub async fn execute( read_account(program_id, key, account)? } else if is_legacy_chain_id(key.chain_id, &chain_ids) { let contract_pubkey = key.find_contract_pubkey(program_id); - if let Some(contract_account) = rpc_client.get_account(&contract_pubkey).await?.value { + if let Some(contract_account) = rpc.get_account(&contract_pubkey).await?.value { read_legacy_account(program_id, key, contract_account)? } else { GetBalanceResponse::empty(program_id, key) diff --git a/evm_loader/lib/src/commands/get_config.rs b/evm_loader/lib/src/commands/get_config.rs index 5c70e85e8..0a642cc0c 100644 --- a/evm_loader/lib/src/commands/get_config.rs +++ b/evm_loader/lib/src/commands/get_config.rs @@ -18,7 +18,9 @@ use solana_sdk::{ use crate::{rpc::Rpc, NeonError, NeonResult}; +use crate::rpc::{CallDbClient, RpcEnum, SolanaRpc}; use serde_with::{serde_as, DisplayFromStr}; +use solana_client::nonblocking::rpc_client::RpcClient; #[derive(Debug, Serialize)] pub enum Status { @@ -50,10 +52,10 @@ pub struct GetConfigResponse { static PROGRAM_TEST: OnceCell> = OnceCell::const_new(); async fn read_program_data_from_account( - rpc_client: &dyn Rpc, + rpc: &CallDbClient, program_id: Pubkey, ) -> NeonResult> { - let Some(account) = rpc_client.get_account(&program_id).await?.value else { + let Some(account) = rpc.get_account(&program_id).await?.value else { return Err(NeonError::AccountNotFound(program_id)); }; @@ -69,7 +71,7 @@ async fn read_program_data_from_account( programdata_address, }) = account.state() { - let Some(programdata_account) = rpc_client.get_account(&programdata_address).await?.value else { + let Some(programdata_account) = rpc.get_account(&programdata_address).await?.value else { return Err(NeonError::AssociatedPdaNotFound(programdata_address, program_id)); }; @@ -113,26 +115,26 @@ async fn lock_program_test( } enum ConfigSimulator<'r> { - Rpc(Pubkey, &'r dyn Rpc), + Rpc(Pubkey, &'r RpcClient), ProgramTest(MutexGuard<'static, ProgramTestContext>), } impl<'r> ConfigSimulator<'r> { - pub async fn new( - rpc_client: &'r dyn Rpc, - program_id: Pubkey, - ) -> NeonResult> { - let simulator = if rpc_client.can_simulate_transaction() { - let identity = rpc_client.get_account_with_sol().await?; - Self::Rpc(identity, rpc_client) - } else { - let program_data = read_program_data_from_account(rpc_client, program_id).await?; - let mut program_test = lock_program_test(program_id, program_data).await; - program_test.get_new_latest_blockhash().await?; - - Self::ProgramTest(program_test) + pub async fn new(rpc: &'r RpcEnum, program_id: Pubkey) -> NeonResult> { + let simulator = match rpc { + RpcEnum::CloneRpcClient(clone_rpc_client) => Self::Rpc( + clone_rpc_client.get_account_with_sol().await?, + clone_rpc_client, + ), + RpcEnum::CallDbClient(call_db_client) => { + let program_data = + read_program_data_from_account(call_db_client, program_id).await?; + let mut program_test = lock_program_test(program_id, program_data).await; + program_test.get_new_latest_blockhash().await?; + + Self::ProgramTest(program_test) + } }; - Ok(simulator) } @@ -151,7 +153,7 @@ impl<'r> ConfigSimulator<'r> { let logs = match self { ConfigSimulator::Rpc(signer, rpc) => { let result = rpc - .simulate_transaction( + .simulate_transaction_with_instructions( Some(*signer), &[Instruction::new_with_bytes(program_id, &input, vec![])], ) @@ -266,8 +268,8 @@ async fn get_properties( Ok(result) } -pub async fn execute(rpc_client: &dyn Rpc, program_id: Pubkey) -> NeonResult { - let mut simulator = ConfigSimulator::new(rpc_client, program_id).await?; +pub async fn execute(rpc: &RpcEnum, program_id: Pubkey) -> NeonResult { + let mut simulator = ConfigSimulator::new(rpc, program_id).await?; let (version, revision) = get_version(&mut simulator, program_id).await?; @@ -281,8 +283,8 @@ pub async fn execute(rpc_client: &dyn Rpc, program_id: Pubkey) -> NeonResult NeonResult> { - let mut simulator = ConfigSimulator::new(rpc_client, program_id).await?; +pub async fn read_chains(rpc: &RpcEnum, program_id: Pubkey) -> NeonResult> { + let mut simulator = ConfigSimulator::new(rpc, program_id).await?; let chains = get_chains(&mut simulator, program_id).await?; Ok(chains) diff --git a/evm_loader/lib/src/commands/get_contract.rs b/evm_loader/lib/src/commands/get_contract.rs index 4d275d634..842bebb52 100644 --- a/evm_loader/lib/src/commands/get_contract.rs +++ b/evm_loader/lib/src/commands/get_contract.rs @@ -7,6 +7,7 @@ use solana_sdk::{account::Account, pubkey::Pubkey}; use crate::{account_storage::account_info, rpc::Rpc, NeonResult}; +use crate::rpc::RpcEnum; use serde_with::{hex::Hex, serde_as, DisplayFromStr}; use super::get_config::ChainInfo; @@ -74,11 +75,11 @@ fn read_account( } pub async fn execute( - rpc_client: &dyn Rpc, + rpc: &RpcEnum, program_id: &Pubkey, accounts: &[Address], ) -> NeonResult> { - let chain_ids = super::get_config::read_chains(rpc_client, *program_id).await?; + let chain_ids = super::get_config::read_chains(rpc, *program_id).await?; let legacy_chain_id = find_legacy_chain_id(&chain_ids); let pubkeys: Vec<_> = accounts @@ -86,7 +87,7 @@ pub async fn execute( .map(|a| a.find_solana_address(program_id).0) .collect(); - let accounts = rpc_client.get_multiple_accounts(&pubkeys).await?; + let accounts = rpc.get_multiple_accounts(&pubkeys).await?; let mut result = Vec::with_capacity(accounts.len()); for (key, account) in pubkeys.into_iter().zip(accounts) { diff --git a/evm_loader/lib/src/commands/get_holder.rs b/evm_loader/lib/src/commands/get_holder.rs index fc3db7cbc..13fa2bcd1 100644 --- a/evm_loader/lib/src/commands/get_holder.rs +++ b/evm_loader/lib/src/commands/get_holder.rs @@ -12,6 +12,7 @@ use std::fmt::Display; use crate::{account_storage::account_info, rpc::Rpc, NeonResult}; +use crate::rpc::RpcEnum; use serde_with::{hex::Hex, serde_as, skip_serializing_none, DisplayFromStr}; #[derive(Debug, Default, Serialize)] @@ -140,11 +141,11 @@ pub fn read_holder(program_id: &Pubkey, info: AccountInfo) -> NeonResult NeonResult { - let response = rpc_client.get_account(&address).await?; + let response = rpc.get_account(&address).await?; let Some(mut account) = response.value else { return Ok(GetHolderResponse::empty()) }; diff --git a/evm_loader/lib/src/commands/get_neon_elf.rs b/evm_loader/lib/src/commands/get_neon_elf.rs index 882a96a98..a710656ee 100644 --- a/evm_loader/lib/src/commands/get_neon_elf.rs +++ b/evm_loader/lib/src/commands/get_neon_elf.rs @@ -7,7 +7,8 @@ use solana_sdk::{ }; use std::{collections::HashMap, convert::TryFrom, fs::File, io::Read}; -use crate::{context::Context, errors::NeonError, Config, NeonResult}; +use crate::rpc::{Rpc, RpcEnum}; +use crate::{errors::NeonError, Config, NeonResult}; pub type GetNeonElfReturn = HashMap; @@ -16,9 +17,9 @@ pub struct CachedElfParams { } impl CachedElfParams { - pub async fn new(config: &Config, context: &Context<'_>) -> Self { + pub async fn new(config: &Config, rpc: &RpcEnum) -> Self { Self { - elf_params: read_elf_parameters_from_account(config, context) + elf_params: read_elf_parameters_from_account(config, rpc) .await .expect("read elf_params error"), } @@ -143,20 +144,18 @@ pub fn get_elf_parameter(data: &[u8], elf_parameter: &str) -> Result { pub async fn read_elf_parameters_from_account( config: &Config, - context: &Context<'_>, + rpc: &RpcEnum, ) -> Result { - let (_, program_data) = - read_program_data_from_account(config, context, &config.evm_loader).await?; + let (_, program_data) = read_program_data_from_account(config, rpc, &config.evm_loader).await?; Ok(read_elf_parameters(config, &program_data)) } pub async fn read_program_data_from_account( config: &Config, - context: &Context<'_>, + rpc: &RpcEnum, evm_loader: &Pubkey, ) -> Result<(Option, Vec), NeonError> { - let account = context - .rpc_client + let account = rpc .get_account_with_commitment(evm_loader, config.commitment) .await? .value @@ -169,8 +168,7 @@ pub async fn read_program_data_from_account( programdata_address, }) = account.state() { - let programdata_account = context - .rpc_client + let programdata_account = rpc .get_account_with_commitment(&programdata_address, config.commitment) .await? .value @@ -226,19 +224,19 @@ fn read_program_params_from_file( async fn read_program_params_from_account( config: &Config, - context: &Context<'_>, + rpc: &RpcEnum, ) -> NeonResult { - read_elf_parameters_from_account(config, context).await + read_elf_parameters_from_account(config, rpc).await } pub async fn execute( config: &Config, - context: &Context<'_>, + rpc: &RpcEnum, program_location: Option<&str>, ) -> NeonResult { if let Some(program_location) = program_location { read_program_params_from_file(config, program_location) } else { - read_program_params_from_account(config, context).await + read_program_params_from_account(config, rpc).await } } diff --git a/evm_loader/lib/src/commands/get_storage_at.rs b/evm_loader/lib/src/commands/get_storage_at.rs index 83dd0cee3..feaf4dc79 100644 --- a/evm_loader/lib/src/commands/get_storage_at.rs +++ b/evm_loader/lib/src/commands/get_storage_at.rs @@ -4,18 +4,19 @@ use solana_sdk::pubkey::Pubkey; use evm_loader::{account_storage::AccountStorage, types::Address}; -use crate::{account_storage::EmulatorAccountStorage, rpc::Rpc, NeonResult}; +use crate::rpc::RpcEnum; +use crate::{account_storage::EmulatorAccountStorage, NeonResult}; #[derive(Debug, Default, Serialize, Deserialize)] pub struct GetStorageAtReturn(pub [u8; 32]); pub async fn execute( - rpc_client: &dyn Rpc, + rpc: &RpcEnum, program_id: &Pubkey, address: Address, index: U256, ) -> NeonResult { - let value = EmulatorAccountStorage::new(rpc_client, *program_id, None, None, None) + let value = EmulatorAccountStorage::new(rpc, *program_id, None, None, None) .await? .storage(address, index) .await; diff --git a/evm_loader/lib/src/commands/init_environment.rs b/evm_loader/lib/src/commands/init_environment.rs index 11bb8e6a6..fdcb02aee 100644 --- a/evm_loader/lib/src/commands/init_environment.rs +++ b/evm_loader/lib/src/commands/init_environment.rs @@ -2,8 +2,9 @@ use std::rc::Rc; use serde::{Deserialize, Serialize}; -use crate::{context::Context, NeonResult}; +use crate::NeonResult; +use crate::rpc::CloneRpcClient; use { crate::{ commands::{ @@ -103,29 +104,24 @@ fn read_keys_dir(keys_dir: &str) -> Result, NeonError> #[allow(clippy::too_many_lines)] pub async fn execute( config: &Config, - context: &Context<'_>, + client: &CloneRpcClient, + signer: &dyn Signer, send_trx: bool, force: bool, keys_dir: Option<&str>, file: Option<&str>, ) -> NeonResult { - let signer = context.signer()?; info!( "Signer: {}, send_trx: {}, force: {}", signer.pubkey(), send_trx, force ); - let second_signer: &dyn Signer = &*context.signer()?; let fee_payer: &dyn Signer = match config.fee_payer.as_ref() { Some(fee_payer) => fee_payer, - None => second_signer, + None => signer, }; - let executor = Rc::new(TransactionExecutor::new( - context.rpc_client, - fee_payer, - send_trx, - )); + let executor = Rc::new(TransactionExecutor::new(client, fee_payer, send_trx)); let keys = keys_dir.map_or(Ok(HashMap::new()), read_keys_dir)?; let program_data_address = Pubkey::find_program_address( @@ -133,8 +129,9 @@ pub async fn execute( &bpf_loader_upgradeable::id(), ) .0; + let rpc_enum = client.clone().into(); let (program_upgrade_authority, program_data) = - read_program_data_from_account(config, context, &config.evm_loader).await?; + read_program_data_from_account(config, &rpc_enum, &config.evm_loader).await?; let data = file.map_or(Ok(program_data), read_program_data)?; let program_parameters = Parameters::new(read_elf_parameters(config, &data)); @@ -154,14 +151,12 @@ pub async fn execute( //====================== Create NEON-token mint =================================================================== let executor_clone = executor.clone(); - let second_signer = context.signer()?; let create_token = move |mint: Pubkey, decimals: u8| async move { let mint_signer = keys .get(&mint) .ok_or(EnvironmentError::MissingPrivateKey(mint))?; let data_len = spl_token::state::Mint::LEN; - let lamports = context - .rpc_client + let lamports = client .get_minimum_balance_for_rent_exemption(data_len) .await?; let parameters = &[ @@ -175,7 +170,7 @@ pub async fn execute( spl_token::instruction::initialize_mint2( &spl_token::id(), &mint, - &second_signer.pubkey(), + &signer.pubkey(), None, decimals, )?, @@ -209,7 +204,7 @@ pub async fn execute( //====================== Create 'Deposit' NEON-token balance ====================================================== let (deposit_authority, _) = Pubkey::find_program_address(&[b"Deposit"], &config.evm_loader); - let chains = super::get_config::read_chains(context.rpc_client, config.evm_loader).await?; + let chains = super::get_config::read_chains(&rpc_enum, config.evm_loader).await?; for chain in chains { let pool = get_associated_token_address(&deposit_authority, &chain.token); @@ -277,7 +272,7 @@ pub async fn execute( AccountMeta::new(executor.fee_payer.pubkey(), true), ], )], - &[&*signer], + &[signer], ) .await?; Ok(Some(transaction)) @@ -288,10 +283,7 @@ pub async fn execute( //====================== Create auxiliary treasury balances ======================================================= let treasury_pool_count = program_parameters.get::("NEON_TREASURY_POOL_COUNT")?; for i in 0..treasury_pool_count { - let minimum_balance = context - .rpc_client - .get_minimum_balance_for_rent_exemption(0) - .await?; + let minimum_balance = client.get_minimum_balance_for_rent_exemption(0).await?; let aux_balance_address = Treasury::address(&config.evm_loader, i).0; let executor_clone = executor.clone(); executor @@ -326,7 +318,7 @@ pub async fn execute( .await?; } - executor.checkpoint(context.rpc_client.commitment()).await?; + executor.checkpoint(client.commitment()).await?; { let stats = executor.stats.borrow(); diff --git a/evm_loader/lib/src/commands/mod.rs b/evm_loader/lib/src/commands/mod.rs index 805071eb1..801b7b7c7 100644 --- a/evm_loader/lib/src/commands/mod.rs +++ b/evm_loader/lib/src/commands/mod.rs @@ -1,4 +1,4 @@ -use crate::rpc::Rpc; +use solana_client::nonblocking::rpc_client::RpcClient; use solana_client::{ client_error::Result as SolanaClientResult, rpc_config::RpcSendTransactionConfig, }; @@ -25,7 +25,7 @@ pub mod trace; mod transaction_executor; pub async fn send_transaction( - rpc_client: &dyn Rpc, + rpc_client: &RpcClient, signer: &dyn Signer, instructions: &[Instruction], ) -> SolanaClientResult { diff --git a/evm_loader/lib/src/commands/trace.rs b/evm_loader/lib/src/commands/trace.rs index 8dcc48d20..1496f41d9 100644 --- a/evm_loader/lib/src/commands/trace.rs +++ b/evm_loader/lib/src/commands/trace.rs @@ -3,12 +3,13 @@ use std::rc::Rc; use serde_json::Value; use solana_sdk::pubkey::Pubkey; +use crate::errors::NeonError; +use crate::rpc::RpcEnum; use crate::tracing::tracers::new_tracer; use crate::types::EmulateRequest; -use crate::{errors::NeonError, rpc::Rpc}; pub async fn trace_transaction( - rpc_client: &dyn Rpc, + rpc: &RpcEnum, program_id: Pubkey, config: EmulateRequest, ) -> Result { @@ -21,7 +22,7 @@ pub async fn trace_transaction( let tracer = new_tracer(&trace_config)?; let emulation_tracer = Some(Rc::clone(&tracer)); - let r = super::emulate::execute(rpc_client, program_id, config, emulation_tracer).await?; + let r = super::emulate::execute(rpc, program_id, config, emulation_tracer).await?; let mut traces = Rc::try_unwrap(tracer) .expect("There is must be only one reference") diff --git a/evm_loader/lib/src/commands/transaction_executor.rs b/evm_loader/lib/src/commands/transaction_executor.rs index b57ec31e5..158b89874 100644 --- a/evm_loader/lib/src/commands/transaction_executor.rs +++ b/evm_loader/lib/src/commands/transaction_executor.rs @@ -2,9 +2,10 @@ use std::cell::RefCell; use std::future::Future; use serde::{Deserialize, Serialize}; +use solana_client::nonblocking::rpc_client::RpcClient; use { - crate::{errors::NeonError, rpc}, + crate::errors::NeonError, log::{debug, error, info, warn}, solana_sdk::{ account::Account, @@ -46,7 +47,7 @@ impl Stats { } } pub struct TransactionExecutor<'a, 'b> { - pub client: &'a dyn rpc::Rpc, + pub client: &'a RpcClient, pub send_trx: bool, pub signatures: RefCell>, pub stats: RefCell, @@ -54,7 +55,7 @@ pub struct TransactionExecutor<'a, 'b> { } impl<'a, 'b> TransactionExecutor<'a, 'b> { - pub fn new(client: &'a dyn rpc::Rpc, fee_payer: &'b dyn Signer, send_trx: bool) -> Self { + pub fn new(client: &'a RpcClient, fee_payer: &'b dyn Signer, send_trx: bool) -> Self { Self { client, send_trx, diff --git a/evm_loader/lib/src/config.rs b/evm_loader/lib/src/config.rs index ab12bc955..ae1c5fa72 100644 --- a/evm_loader/lib/src/config.rs +++ b/evm_loader/lib/src/config.rs @@ -1,11 +1,13 @@ use std::{env, str::FromStr}; +use crate::rpc::CloneRpcClient; use crate::{types::ChDbConfig, NeonError}; use serde::{Deserialize, Serialize}; use solana_clap_utils::{ input_validators::normalize_to_url_if_moniker, keypair::keypair_from_path, }; use solana_cli_config::Config as SolanaConfig; +use solana_client::nonblocking::rpc_client::RpcClient; use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey, signature::Keypair}; #[derive(Debug)] @@ -19,11 +21,15 @@ pub struct Config { pub keypair_path: String, } -// impl Debug for Config { -// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -// write!(f, "evm_loader={:?}", self.evm_loader) -// } -// } +impl Config { + pub fn build_solana_rpc_client(&self) -> RpcClient { + RpcClient::new_with_commitment(self.json_rpc_url.clone(), self.commitment) + } + + pub fn build_clone_solana_rpc_client(&self) -> CloneRpcClient { + CloneRpcClient::new(self.build_solana_rpc_client()) + } +} /// # Errors pub fn create_from_api_config(api_config: &APIOptions) -> Result { diff --git a/evm_loader/lib/src/context.rs b/evm_loader/lib/src/context.rs deleted file mode 100644 index 91793531e..000000000 --- a/evm_loader/lib/src/context.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::{ - rpc::{self}, - Config, NeonError, -}; -use solana_clap_utils::keypair::signer_from_path; -use solana_sdk::signature::Signer; - -pub fn truncate_0x(in_str: &str) -> &str { - if &in_str[..2] == "0x" { - &in_str[2..] - } else { - in_str - } -} - -pub struct Context<'a> { - pub rpc_client: &'a dyn rpc::Rpc, - signer_config: &'a Config, -} - -impl<'a> Context<'a> { - pub fn signer(&self) -> Result, NeonError> { - build_signer(self.signer_config) - } - - pub fn new(rpc_client: &'a dyn rpc::Rpc, signer_config: &'a Config) -> Context<'a> { - Self { - rpc_client, - signer_config, - } - } -} - -/// # Errors -pub fn build_signer(config: &Config) -> Result, NeonError> { - let mut wallet_manager = None; - - let signer = signer_from_path( - &Default::default(), - &config.keypair_path, - "keypair", - &mut wallet_manager, - ) - .map_err(|_| NeonError::KeypairNotSpecified)?; - - Ok(signer) -} diff --git a/evm_loader/lib/src/lib.rs b/evm_loader/lib/src/lib.rs index 3cea4c495..eb80c7e78 100644 --- a/evm_loader/lib/src/lib.rs +++ b/evm_loader/lib/src/lib.rs @@ -3,7 +3,6 @@ pub mod build_info; pub mod build_info_common; pub mod commands; pub mod config; -pub mod context; pub mod errors; pub mod rpc; pub mod syscall_stubs; @@ -11,7 +10,6 @@ pub mod tracing; pub mod types; pub use config::Config; -pub use context::Context; pub use errors::NeonError; pub type NeonResult = Result; diff --git a/evm_loader/lib/src/rpc/db_call_client.rs b/evm_loader/lib/src/rpc/db_call_client.rs index 605676dd4..b16fc9944 100644 --- a/evm_loader/lib/src/rpc/db_call_client.rs +++ b/evm_loader/lib/src/rpc/db_call_client.rs @@ -5,23 +5,14 @@ use async_trait::async_trait; use solana_client::{ client_error::Result as ClientResult, client_error::{ClientError, ClientErrorKind}, - rpc_config::{RpcSendTransactionConfig, RpcTransactionConfig}, - rpc_response::{Response, RpcResponseContext, RpcResult, RpcSimulateTransactionResult}, + rpc_response::{Response, RpcResponseContext, RpcResult}, }; use solana_sdk::{ account::Account, clock::{Slot, UnixTimestamp}, commitment_config::CommitmentConfig, - hash::Hash, - instruction::Instruction, pubkey::Pubkey, - signature::Signature, - transaction::Transaction, }; -use solana_transaction_status::{ - EncodedConfirmedBlock, EncodedConfirmedTransactionWithStatusMeta, TransactionStatus, -}; -use std::any::Any; pub struct CallDbClient { tracer_db: TracerDb, @@ -49,28 +40,29 @@ impl CallDbClient { tx_index_in_block, }) } -} -#[async_trait(?Send)] -impl Rpc for CallDbClient { - fn commitment(&self) -> CommitmentConfig { - CommitmentConfig::default() + async fn get_account(&self, key: &Pubkey) -> RpcResult> { + Ok(Response { + context: RpcResponseContext { + slot: self.slot, + api_version: None, + }, + value: self.get_account_at(key).await?, + }) } - async fn confirm_transaction_with_spinner( - &self, - _signature: &Signature, - _recent_blockhash: &Hash, - _commitment_config: CommitmentConfig, - ) -> ClientResult<()> { - Err(e!( - "confirm_transaction_with_spinner() not implemented for db_call_client" - )) + async fn get_account_at(&self, key: &Pubkey) -> ClientResult> { + self.tracer_db + .get_account_at(key, self.slot, self.tx_index_in_block) + .await + .map_err(|e| e!("load account error", key, e)) } +} +#[async_trait(?Send)] +impl Rpc for CallDbClient { async fn get_account(&self, key: &Pubkey) -> RpcResult> { - self.get_account_with_commitment(key, self.commitment()) - .await + self.get_account(key).await } async fn get_account_with_commitment( @@ -78,20 +70,7 @@ impl Rpc for CallDbClient { key: &Pubkey, _: CommitmentConfig, ) -> RpcResult> { - let account = self - .tracer_db - .get_account_at(key, self.slot, self.tx_index_in_block) - .await - .map_err(|e| e!("load account error", key, e))?; - - let context = RpcResponseContext { - slot: self.slot, - api_version: None, - }; - Ok(Response { - context, - value: account, - }) + self.get_account(key).await } async fn get_multiple_accounts( @@ -100,29 +79,11 @@ impl Rpc for CallDbClient { ) -> ClientResult>> { let mut result = Vec::new(); for key in pubkeys { - let account = self - .tracer_db - .get_account_at(key, self.slot, self.tx_index_in_block) - .await - .map_err(|e| e!("load account error", key, e))?; - result.push(account); + result.push(self.get_account_at(key).await?); } Ok(result) } - async fn get_account_data(&self, key: &Pubkey) -> ClientResult> { - let response = self.get_account(key).await?; - if let Some(account) = response.value { - Ok(account.data) - } else { - Ok(Vec::new()) - } - } - - async fn get_block(&self, _slot: Slot) -> ClientResult { - Err(e!("get_block() not implemented for db_call_client")) - } - async fn get_block_time(&self, slot: Slot) -> ClientResult { self.tracer_db .get_block_time(slot) @@ -130,101 +91,7 @@ impl Rpc for CallDbClient { .map_err(|e| e!("get_block_time error", slot, e)) } - async fn get_latest_blockhash(&self) -> ClientResult { - Err(e!( - "get_latest_blockhash() not implemented for db_call_client" - )) - } - - async fn get_minimum_balance_for_rent_exemption(&self, _data_len: usize) -> ClientResult { - Err(e!( - "get_minimum_balance_for_rent_exemption() not implemented for db_call_client" - )) - } - async fn get_slot(&self) -> ClientResult { Ok(self.slot) } - - async fn get_signature_statuses( - &self, - _signatures: &[Signature], - ) -> RpcResult>> { - Err(e!( - "get_signature_statuses() not implemented for db_call_client" - )) - } - - async fn get_transaction_with_config( - &self, - _signature: &Signature, - _config: RpcTransactionConfig, - ) -> ClientResult { - Err(e!( - "get_transaction_with_config() not implemented for db_call_client" - )) - } - - async fn send_transaction(&self, _transaction: &Transaction) -> ClientResult { - Err(e!("send_transaction() not implemented for db_call_client")) - } - - async fn send_and_confirm_transaction_with_spinner( - &self, - _transaction: &Transaction, - ) -> ClientResult { - Err(e!( - "send_and_confirm_transaction_with_spinner() not implemented for db_call_client" - )) - } - - async fn send_and_confirm_transaction_with_spinner_and_commitment( - &self, - _transaction: &Transaction, - _commitment: CommitmentConfig, - ) -> ClientResult { - Err(e!("send_and_confirm_transaction_with_spinner_and_commitment() not implemented for db_call_client")) - } - - async fn send_and_confirm_transaction_with_spinner_and_config( - &self, - _transaction: &Transaction, - _commitment: CommitmentConfig, - _config: RpcSendTransactionConfig, - ) -> ClientResult { - Err(e!("send_and_confirm_transaction_with_spinner_and_config() not implemented for db_call_client")) - } - - async fn get_latest_blockhash_with_commitment( - &self, - _commitment: CommitmentConfig, - ) -> ClientResult<(Hash, u64)> { - Err(e!( - "get_latest_blockhash_with_commitment() not implemented for db_call_client" - )) - } - - fn can_simulate_transaction(&self) -> bool { - false - } - - async fn simulate_transaction( - &self, - _signer: Option, - _instructions: &[Instruction], - ) -> RpcResult { - Err(e!( - "simulate_transaction() not implemented for db_call_client" - )) - } - - async fn get_account_with_sol(&self) -> ClientResult { - Err(e!( - "get_account_with_sol() not implemented for db_call_client" - )) - } - - fn as_any(&self) -> &dyn Any { - self - } } diff --git a/evm_loader/lib/src/rpc/mod.rs b/evm_loader/lib/src/rpc/mod.rs index 8b6dd1c89..799305ce4 100644 --- a/evm_loader/lib/src/rpc/mod.rs +++ b/evm_loader/lib/src/rpc/mod.rs @@ -2,41 +2,26 @@ mod db_call_client; mod validator_client; pub use db_call_client::CallDbClient; +pub use validator_client::CloneRpcClient; +pub use validator_client::SolanaRpc; use crate::{NeonError, NeonResult}; use async_trait::async_trait; +use enum_dispatch::enum_dispatch; use solana_cli::cli::CliError; -use solana_client::{ - client_error::Result as ClientResult, - nonblocking::rpc_client::RpcClient, - rpc_config::{RpcSendTransactionConfig, RpcTransactionConfig}, - rpc_response::{RpcResult, RpcSimulateTransactionResult}, -}; +use solana_client::{client_error::Result as ClientResult, rpc_response::RpcResult}; +use solana_sdk::message::Message; use solana_sdk::native_token::lamports_to_sol; use solana_sdk::{ account::Account, clock::{Slot, UnixTimestamp}, commitment_config::CommitmentConfig, - hash::Hash, pubkey::Pubkey, - signature::Signature, - transaction::Transaction, -}; -use solana_sdk::{instruction::Instruction, message::Message}; -use solana_transaction_status::{ - EncodedConfirmedBlock, EncodedConfirmedTransactionWithStatusMeta, TransactionStatus, }; -use std::any::Any; #[async_trait(?Send)] +#[enum_dispatch] pub trait Rpc { - fn commitment(&self) -> CommitmentConfig; - async fn confirm_transaction_with_spinner( - &self, - signature: &Signature, - recent_blockhash: &Hash, - commitment_config: CommitmentConfig, - ) -> ClientResult<()>; async fn get_account(&self, key: &Pubkey) -> RpcResult>; async fn get_account_with_commitment( &self, @@ -45,53 +30,14 @@ pub trait Rpc { ) -> RpcResult>; async fn get_multiple_accounts(&self, pubkeys: &[Pubkey]) -> ClientResult>>; - async fn get_account_data(&self, key: &Pubkey) -> ClientResult>; - async fn get_block(&self, slot: Slot) -> ClientResult; async fn get_block_time(&self, slot: Slot) -> ClientResult; - async fn get_latest_blockhash(&self) -> ClientResult; - async fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> ClientResult; async fn get_slot(&self) -> ClientResult; - async fn get_signature_statuses( - &self, - signatures: &[Signature], - ) -> RpcResult>>; - async fn get_transaction_with_config( - &self, - signature: &Signature, - config: RpcTransactionConfig, - ) -> ClientResult; - async fn send_transaction(&self, transaction: &Transaction) -> ClientResult; - async fn send_and_confirm_transaction_with_spinner( - &self, - transaction: &Transaction, - ) -> ClientResult; - async fn send_and_confirm_transaction_with_spinner_and_commitment( - &self, - transaction: &Transaction, - commitment: CommitmentConfig, - ) -> ClientResult; - async fn send_and_confirm_transaction_with_spinner_and_config( - &self, - transaction: &Transaction, - commitment: CommitmentConfig, - config: RpcSendTransactionConfig, - ) -> ClientResult; - async fn get_latest_blockhash_with_commitment( - &self, - commitment: CommitmentConfig, - ) -> ClientResult<(Hash, u64)>; - - fn can_simulate_transaction(&self) -> bool; - - async fn simulate_transaction( - &self, - signer: Option, - instructions: &[Instruction], - ) -> RpcResult; - - async fn get_account_with_sol(&self) -> ClientResult; +} - fn as_any(&self) -> &dyn Any; +#[enum_dispatch(Rpc)] +pub enum RpcEnum { + CloneRpcClient, + CallDbClient, } macro_rules! e { @@ -108,10 +54,11 @@ macro_rules! e { ))) }; } + pub(crate) use e; pub(crate) async fn check_account_for_fee( - rpc_client: &RpcClient, + rpc_client: &CloneRpcClient, account_pubkey: &Pubkey, message: &Message, ) -> NeonResult<()> { diff --git a/evm_loader/lib/src/rpc/validator_client.rs b/evm_loader/lib/src/rpc/validator_client.rs index 1a5be4b69..9e75de53c 100644 --- a/evm_loader/lib/src/rpc/validator_client.rs +++ b/evm_loader/lib/src/rpc/validator_client.rs @@ -3,45 +3,43 @@ use async_trait::async_trait; use solana_client::{ client_error::Result as ClientResult, nonblocking::rpc_client::RpcClient, - rpc_config::{ - RpcLargestAccountsConfig, RpcSendTransactionConfig, RpcSimulateTransactionConfig, - RpcTransactionConfig, - }, + rpc_config::{RpcLargestAccountsConfig, RpcSimulateTransactionConfig}, rpc_response::{RpcResult, RpcSimulateTransactionResult}, }; use solana_sdk::{ account::Account, clock::{Slot, UnixTimestamp}, commitment_config::CommitmentConfig, - hash::Hash, instruction::Instruction, pubkey::Pubkey, - signature::Signature, transaction::Transaction, }; -use solana_transaction_status::{ - EncodedConfirmedBlock, EncodedConfirmedTransactionWithStatusMeta, TransactionStatus, -}; -use std::{any::Any, str::FromStr}; +use std::ops::Deref; +use std::str::FromStr; +use std::sync::Arc; -#[async_trait(?Send)] -impl Rpc for RpcClient { - fn commitment(&self) -> CommitmentConfig { - self.commitment() +#[derive(Clone)] +pub struct CloneRpcClient(Arc); + +impl CloneRpcClient { + pub fn new(rpc_client: RpcClient) -> Self { + Self(Arc::new(rpc_client)) } +} - async fn confirm_transaction_with_spinner( - &self, - signature: &Signature, - recent_blockhash: &Hash, - commitment_config: CommitmentConfig, - ) -> ClientResult<()> { - self.confirm_transaction_with_spinner(signature, recent_blockhash, commitment_config) - .await +impl Deref for CloneRpcClient { + type Target = RpcClient; + + fn deref(&self) -> &Self::Target { + &self.0 } +} +#[async_trait(?Send)] +impl Rpc for CloneRpcClient { async fn get_account(&self, key: &Pubkey) -> RpcResult> { - self.get_account_with_commitment(key, self.commitment()) + self.0 + .get_account_with_commitment(key, self.commitment()) .await } @@ -50,7 +48,7 @@ impl Rpc for RpcClient { key: &Pubkey, commitment: CommitmentConfig, ) -> RpcResult> { - self.get_account_with_commitment(key, commitment).await + self.0.get_account_with_commitment(key, commitment).await } async fn get_multiple_accounts( @@ -59,95 +57,36 @@ impl Rpc for RpcClient { ) -> ClientResult>> { let mut result: Vec> = Vec::new(); for chunk in pubkeys.chunks(100) { - let mut accounts = self.get_multiple_accounts(chunk).await?; + let mut accounts = self.0.get_multiple_accounts(chunk).await?; result.append(&mut accounts); } Ok(result) } - async fn get_account_data(&self, key: &Pubkey) -> ClientResult> { - Ok(self.get_account(key).await?.data) - } - - async fn get_block(&self, slot: Slot) -> ClientResult { - self.get_block(slot).await - } - async fn get_block_time(&self, slot: Slot) -> ClientResult { - self.get_block_time(slot).await - } - - async fn get_latest_blockhash(&self) -> ClientResult { - self.get_latest_blockhash().await - } - - async fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> ClientResult { - self.get_minimum_balance_for_rent_exemption(data_len).await + self.0.get_block_time(slot).await } async fn get_slot(&self) -> ClientResult { - self.get_slot().await - } - - async fn get_signature_statuses( - &self, - signatures: &[Signature], - ) -> RpcResult>> { - self.get_signature_statuses(signatures).await - } - - async fn get_transaction_with_config( - &self, - signature: &Signature, - config: RpcTransactionConfig, - ) -> ClientResult { - self.get_transaction_with_config(signature, config).await - } - - async fn send_transaction(&self, transaction: &Transaction) -> ClientResult { - self.send_transaction(transaction).await - } - - async fn send_and_confirm_transaction_with_spinner( - &self, - transaction: &Transaction, - ) -> ClientResult { - self.send_and_confirm_transaction_with_spinner(transaction) - .await - } - - async fn send_and_confirm_transaction_with_spinner_and_commitment( - &self, - transaction: &Transaction, - commitment: CommitmentConfig, - ) -> ClientResult { - self.send_and_confirm_transaction_with_spinner_and_commitment(transaction, commitment) - .await - } - - async fn send_and_confirm_transaction_with_spinner_and_config( - &self, - transaction: &Transaction, - commitment: CommitmentConfig, - config: RpcSendTransactionConfig, - ) -> ClientResult { - self.send_and_confirm_transaction_with_spinner_and_config(transaction, commitment, config) - .await + self.0.get_slot().await } +} - async fn get_latest_blockhash_with_commitment( +#[async_trait(?Send)] +pub trait SolanaRpc { + async fn simulate_transaction_with_instructions( &self, - commitment: CommitmentConfig, - ) -> ClientResult<(Hash, u64)> { - self.get_latest_blockhash_with_commitment(commitment).await - } + signer: Option, + instructions: &[Instruction], + ) -> RpcResult; - fn can_simulate_transaction(&self) -> bool { - true - } + async fn get_account_with_sol(&self) -> ClientResult; +} - async fn simulate_transaction( +#[async_trait(?Send)] +impl SolanaRpc for RpcClient { + async fn simulate_transaction_with_instructions( &self, signer: Option, instructions: &[Instruction], @@ -182,8 +121,4 @@ impl Rpc for RpcClient { let pubkey = Pubkey::from_str(&r.value[0].address).unwrap(); Ok(pubkey) } - - fn as_any(&self) -> &dyn Any { - self - } } diff --git a/evm_loader/lib/src/syscall_stubs.rs b/evm_loader/lib/src/syscall_stubs.rs index 37aa81852..d2608edd7 100644 --- a/evm_loader/lib/src/syscall_stubs.rs +++ b/evm_loader/lib/src/syscall_stubs.rs @@ -1,6 +1,7 @@ use log::info; use solana_sdk::{program_error::ProgramError, program_stubs::SyscallStubs, sysvar::rent::Rent}; +use crate::rpc::RpcEnum; use crate::{errors::NeonError, rpc::Rpc}; pub struct DefaultStubs; @@ -12,9 +13,14 @@ pub struct EmulatorStubs { } impl EmulatorStubs { - pub async fn new(rpc_client: &dyn Rpc) -> Result, NeonError> { + pub async fn new(rpc: &RpcEnum) -> Result, NeonError> { let rent_pubkey = solana_sdk::sysvar::rent::id(); - let data = rpc_client.get_account_data(&rent_pubkey).await?; + let data = rpc + .get_account(&rent_pubkey) + .await? + .value + .map(|a| a.data) + .unwrap_or_default(); let rent = bincode::deserialize(&data).map_err(|_| ProgramError::InvalidArgument)?; Ok(Box::new(Self { rent })) @@ -51,8 +57,8 @@ impl SyscallStubs for EmulatorStubs { } } -pub async fn setup_emulator_syscall_stubs(rpc_client: &dyn Rpc) -> Result<(), NeonError> { - let syscall_stubs = EmulatorStubs::new(rpc_client).await?; +pub async fn setup_emulator_syscall_stubs(rpc: &RpcEnum) -> Result<(), NeonError> { + let syscall_stubs = EmulatorStubs::new(rpc).await?; solana_sdk::program_stubs::set_syscall_stubs(syscall_stubs); Ok(()) diff --git a/evm_loader/lib/src/types/tracer_ch_db.rs b/evm_loader/lib/src/types/tracer_ch_db.rs index f9140fc41..f2ee5f454 100644 --- a/evm_loader/lib/src/types/tracer_ch_db.rs +++ b/evm_loader/lib/src/types/tracer_ch_db.rs @@ -1,12 +1,10 @@ use crate::{ commands::get_neon_elf::get_elf_parameter, types::tracer_ch_common::{AccountRow, ChError, RevisionRow, SlotParent, ROOT_BLOCK_DELAY}, + Config, }; -use super::{ - tracer_ch_common::{ChResult, EthSyncStatus, EthSyncing, RevisionMap, SlotParentRooted}, - ChDbConfig, -}; +use super::tracer_ch_common::{ChResult, EthSyncStatus, EthSyncing, RevisionMap, SlotParentRooted}; use clickhouse::Client; use log::{debug, error, info}; @@ -30,7 +28,9 @@ pub struct ClickHouseDb { } impl ClickHouseDb { - pub fn new(config: &ChDbConfig) -> Self { + pub fn new(config: &Config) -> Self { + let config = config.db_config.as_ref().expect("db-config not found"); + let url_id = rand::thread_rng().gen_range(0..config.clickhouse_url.len()); let url = config.clickhouse_url.get(url_id).unwrap();