Skip to content

Commit

Permalink
change rpc API
Browse files Browse the repository at this point in the history
  • Loading branch information
rnovikov committed Nov 18, 2024
1 parent eecd6b1 commit f1c2999
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 107 deletions.
52 changes: 29 additions & 23 deletions evm_loader/lib/src/account_storage_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::rpc;
use crate::tracing::AccountOverride;
use evm_loader::types::vector::VectorVecExt;
use hex_literal::hex;
use solana_account_decoder::UiDataSliceConfig;
use std::collections::HashMap;
use std::str::FromStr;

Expand All @@ -19,6 +20,8 @@ mod mock_rpc_client {
use solana_sdk::pubkey::Pubkey;
use std::collections::HashMap;

use solana_account_decoder::UiDataSliceConfig;

pub struct MockRpcClient {
accounts: HashMap<Pubkey, Account>,
}
Expand All @@ -33,34 +36,33 @@ mod mock_rpc_client {

#[async_trait(?Send)]
impl Rpc for MockRpcClient {
async fn get_account(&self, key: &Pubkey) -> ClientResult<Option<Account>> {
let result = self.accounts.get(key).cloned();
Ok(result)
}
async fn get_account_slice(
&self,
key: &Pubkey,
offset: usize,
data_size: usize,
slice: Option<UiDataSliceConfig>,
) -> ClientResult<Option<Account>> {
if let Some(orig_acc) = self.accounts.get(key) {
let cut_to = usize::min(offset + data_size, orig_acc.data.len());
let sliced_data = if offset < orig_acc.data.len() {
orig_acc.data[offset..cut_to].to_vec()
} else {
vec![]
};

return Ok(Some(Account {
lamports: orig_acc.lamports,
data: sliced_data,
owner: orig_acc.owner,
executable: orig_acc.executable,
rent_epoch: orig_acc.rent_epoch,
}));
if let Some(data_slice) = slice {
if let Some(orig_acc) = self.accounts.get(key) {
let cut_to =
usize::min(data_slice.offset + data_slice.length, orig_acc.data.len());
let sliced_data = if data_slice.offset < orig_acc.data.len() {
orig_acc.data[data_slice.offset..cut_to].to_vec()
} else {
vec![]
};

return Ok(Some(Account {
lamports: orig_acc.lamports,
data: sliced_data,
owner: orig_acc.owner,
executable: orig_acc.executable,
rent_epoch: orig_acc.rent_epoch,
}));
}
}

Ok(None)
let result = self.accounts.get(key).cloned();
Ok(result)
}

async fn get_multiple_accounts(
Expand Down Expand Up @@ -1834,8 +1836,12 @@ async fn test_storage_get_account_slice() {
.await
.expect("Failed to get account slice");

let slice_cfg = UiDataSliceConfig {
offset: slice_from,
length: slice_size,
};
let sliced_acc = rpc_client
.get_account_slice(&test_key, slice_from, slice_size)
.get_account_slice(&test_key, Some(slice_cfg))
.await
.expect("Failed to get account slice");
assert!(acc_no_slice.is_some());
Expand Down
1 change: 0 additions & 1 deletion evm_loader/lib/src/commands/get_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ pub enum ConfigSimulator<'r> {
pub trait BuildConfigSimulator {
fn use_cache(&self) -> bool;
async fn build_config_simulator(&self, program_id: Pubkey) -> NeonResult<ConfigSimulator>;
// get_last_deployed_slot():u64
}

#[async_trait(?Send)]
Expand Down
22 changes: 12 additions & 10 deletions evm_loader/lib/src/rpc/db_call_client.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use super::{e, Rpc};
use super::{e, Rpc, SliceConfig};
use crate::types::{TracerDb, TracerDbTrait};
use crate::NeonError;
use crate::NeonError::RocksDb;
use async_trait::async_trait;
use log::debug;
use solana_account_decoder::UiDataSliceConfig;
use solana_client::{
client_error::Result as ClientResult,
client_error::{ClientError, ClientErrorKind},
Expand Down Expand Up @@ -42,34 +43,35 @@ impl CallDbClient {
})
}

async fn get_account_at(&self, key: &Pubkey) -> ClientResult<Option<Account>> {
async fn get_account_at(
&self,
key: &Pubkey,
slice: Option<UiDataSliceConfig>,
) -> ClientResult<Option<Account>> {
self.tracer_db
.get_account_at(key, self.slot, self.tx_index_in_block, None)
.get_account_at(key, self.slot, self.tx_index_in_block, slice)
.await
.map_err(|e| e!("load account error", key, e))
}
}

#[async_trait(?Send)]
impl Rpc for CallDbClient {
async fn get_account(&self, key: &Pubkey) -> ClientResult<Option<Account>> {
self.get_account_at(key).await
}
async fn get_account_slice(
&self,
key: &Pubkey,
_offset: usize,
_data_size: usize,
slice: Option<SliceConfig>,
) -> ClientResult<Option<Account>> {
self.get_account(key).await
self.get_account_at(key, slice).await
}

async fn get_multiple_accounts(
&self,
pubkeys: &[Pubkey],
) -> ClientResult<Vec<Option<Account>>> {
let mut result = Vec::new();
for key in pubkeys {
result.push(self.get_account_at(key).await?);
result.push(self.get_account_at(key, None).await?);
}
debug!("get_multiple_accounts: pubkeys={pubkeys:?} result={result:?}");
Ok(result)
Expand Down
38 changes: 22 additions & 16 deletions evm_loader/lib/src/rpc/emulator_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,35 @@ use solana_sdk::{

use crate::account_storage::{fake_operator, EmulatorAccountStorage};

use super::Rpc;
use super::{Rpc, SliceConfig};

#[async_trait(?Send)]
impl<'rpc, T: Rpc> Rpc for EmulatorAccountStorage<'rpc, T> {
async fn get_account(&self, key: &Pubkey) -> ClientResult<Option<Account>> {
if *key == self.operator() {
return Ok(Some(fake_operator()));
}

if let Some(account_data) = self.accounts_get(key) {
return Ok(Some(Account::from(&*account_data)));
}

let account = self._get_account_from_rpc(*key).await?.cloned();
Ok(account)
}
async fn get_account_slice(
&self,
key: &Pubkey,
_offset: usize,
_data_size: usize,
slice: Option<SliceConfig>,
) -> ClientResult<Option<Account>> {
self.get_account(key).await
let answer_account = if *key == self.operator() {
Some(fake_operator())
} else if let Some(account_data) = self.accounts_get(key) {
Some(Account::from(&*account_data))
} else {
self._get_account_from_rpc(*key).await?.cloned()
};

if let Some(data_slice) = slice {
// if only slice is necessary - cut data
if let Some(mut account) = answer_account {
if data_slice.offset != 0 {
account.data.drain(0..data_slice.offset);
}
account.data.truncate(data_slice.length);
return Ok(Some(account));
}
}

Ok(answer_account)
}

async fn get_multiple_accounts(
Expand Down
13 changes: 7 additions & 6 deletions evm_loader/lib/src/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,28 @@ use crate::commands::get_config::{BuildConfigSimulator, ConfigSimulator};
use crate::{NeonError, NeonResult};
use async_trait::async_trait;
use enum_dispatch::enum_dispatch;
pub use solana_account_decoder::UiDataSliceConfig as SliceConfig;
use solana_cli::cli::CliError;
use solana_client::client_error::Result as ClientResult;
use solana_sdk::message::Message;
use solana_sdk::native_token::lamports_to_sol;
use solana_sdk::{
account::Account,
clock::{Slot, UnixTimestamp},
message::Message,
native_token::lamports_to_sol,
pubkey::Pubkey,
};

#[async_trait(?Send)]
#[enum_dispatch]
pub trait Rpc {
async fn get_account(&self, key: &Pubkey) -> ClientResult<Option<Account>>;

async fn get_account_slice(
&self,
key: &Pubkey,
offset: usize,
data_size: usize,
slice: Option<SliceConfig>,
) -> ClientResult<Option<Account>>;
async fn get_account(&self, key: &Pubkey) -> ClientResult<Option<Account>> {
self.get_account_slice(key, None).await
}

async fn get_multiple_accounts(&self, pubkeys: &[Pubkey])
-> ClientResult<Vec<Option<Account>>>;
Expand Down
33 changes: 4 additions & 29 deletions evm_loader/lib/src/rpc/validator_client.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::{config::APIOptions, Config};

use super::Rpc;
use super::{Rpc, SliceConfig};
use async_trait::async_trait;
use solana_account_decoder::{UiAccount, UiAccountEncoding, UiDataSliceConfig};
use solana_account_decoder::{UiAccount, UiAccountEncoding};
use solana_client::{
client_error::{ClientError, ClientErrorKind, Result as ClientResult},
nonblocking::rpc_client::RpcClient,
Expand Down Expand Up @@ -114,41 +114,16 @@ impl Deref for CloneRpcClient {

#[async_trait(?Send)]
impl Rpc for CloneRpcClient {
async fn get_account(&self, key: &Pubkey) -> ClientResult<Option<Account>> {
let request = || {
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64Zstd),
commitment: Some(self.commitment()),
data_slice: None,
min_context_slot: None,
};
let params = serde_json::json!([key.to_string(), config]);

self.send(RpcRequest::GetAccountInfo, params)
};

let response: serde_json::Value = with_retries(self.max_retries, request).await?;
let response: Response<Option<UiAccount>> = serde_json::from_value(response)?;

let account = response.value.and_then(|v| v.decode());
Ok(account)
}
async fn get_account_slice(
&self,
key: &Pubkey,
offset: usize,
data_size: usize,
slice: Option<SliceConfig>,
) -> ClientResult<Option<Account>> {
let slice_shape = UiDataSliceConfig {
offset,
length: data_size,
};

let request = || {
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64Zstd),
commitment: Some(self.commitment()),
data_slice: Some(slice_shape),
data_slice: slice,
min_context_slot: None,
};
let params = serde_json::json!([key.to_string(), config]);
Expand Down
2 changes: 1 addition & 1 deletion evm_loader/lib/src/solana_simulator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ use solana_sdk::{
pub use utils::SyncState;

use crate::rpc::Rpc;
use crate::types::account_cache::acc_hash_get_values_by_keys;
use crate::types::programs_cache::acc_hash_get_values_by_keys;

mod error;
mod utils;
Expand Down
2 changes: 1 addition & 1 deletion evm_loader/lib/src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub mod tracer_ch_common;

pub mod account_cache;
pub mod programs_cache;
pub(crate) mod tracer_ch_db;
pub mod tracer_rocks_db;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ pub struct KeyAccountCache {
slot: u64,
}

type AccCache = HashMap<KeyAccountCache, Account>;
type ProtectedAppCache = RwLock<AccCache>;
pub use solana_account_decoder::UiDataSliceConfig as SliceConfig;
type ProgramDataCache = HashMap<KeyAccountCache, Account>;
type ThreadSaveProgramDataCache = RwLock<ProgramDataCache>;

static LOCAL_CONFIG: OnceCell<ProtectedAppCache> = OnceCell::const_new();
static LOCAL_CONFIG: OnceCell<ThreadSaveProgramDataCache> = OnceCell::const_new();

async fn acc_hash_get_instance() -> &'static ProtectedAppCache {
async fn acc_hash_get_instance() -> &'static ThreadSaveProgramDataCache {
LOCAL_CONFIG
.get_or_init(|| async {
let map = HashMap::new();
Expand Down Expand Up @@ -84,8 +85,10 @@ pub async fn acc_hash_get_values_by_keys(
for key in programdata_keys {
future_requests.push(rpc.get_account_slice(
key,
0,
UpgradeableLoaderState::size_of_programdata_metadata(),
Some(SliceConfig {
offset: 0,
length: UpgradeableLoaderState::size_of_programdata_metadata(),
}),
));
//future_requests.push(rpc.get_account_slice(key, 0, 512));
}
Expand Down Expand Up @@ -164,26 +167,22 @@ impl FakeRpc {
#[async_trait(?Send)]

impl Rpc for FakeRpc {
async fn get_account(&self, pubkey: &Pubkey) -> ClientResult<Option<Account>> {
assert!(self.accounts.contains_key(pubkey), " ");
Ok(Some(self.accounts.get(pubkey).unwrap().clone()))
}

async fn get_account_slice(
&self,
pubkey: &Pubkey,
offset: usize,
data_size: usize,
slice: Option<SliceConfig>,
) -> ClientResult<Option<Account>> {
assert!(self.accounts.contains_key(pubkey), " ");
let mut answer = self.accounts.get(pubkey).unwrap().clone();

if offset != 0 {
answer
.data
.drain(..std::cmp::min(answer.data.len(), offset));
let mut answer = self.accounts.get(pubkey).unwrap().clone();
if let Some(data_slice) = slice {
if data_slice.offset != 0 {
answer
.data
.drain(..std::cmp::min(answer.data.len(), data_slice.offset));
}
answer.data.truncate(data_slice.length);
}
answer.data.truncate(data_size);
Ok(Some(answer))
}

Expand Down Expand Up @@ -235,7 +234,15 @@ mod tests {
panic!("fake rpc returned error");
}

let test3_acc = rpc.get_account_slice(&test_key, 0, 1024).await;
let test3_acc = rpc
.get_account_slice(
&test_key,
Some(SliceConfig {
offset: 0,
length: 1024,
}),
)
.await;
assert_eq!(1024, test3_acc.unwrap().expect("test fail").data.len());
}
#[tokio::test]
Expand Down

0 comments on commit f1c2999

Please sign in to comment.