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 1a21408
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 96 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
20 changes: 11 additions & 9 deletions evm_loader/lib/src/rpc/db_call_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ 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<UiDataSliceConfig>,
) -> 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
37 changes: 22 additions & 15 deletions evm_loader/lib/src/rpc/emulator_client.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use async_trait::async_trait;
use evm_loader::account_storage::AccountStorage;
use log::debug;
use solana_account_decoder::UiDataSliceConfig;
use solana_client::client_error::Result as ClientResult;
use solana_sdk::{
account::Account,
Expand All @@ -14,25 +15,31 @@ use super::Rpc;

#[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<UiDataSliceConfig>,
) -> 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 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;
use solana_account_decoder::UiDataSliceConfig;
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<UiDataSliceConfig>,
) -> 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
29 changes: 2 additions & 27 deletions evm_loader/lib/src/rpc/validator_client.rs
Original file line number Diff line number Diff line change
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<UiDataSliceConfig>,
) -> 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
39 changes: 23 additions & 16 deletions evm_loader/lib/src/types/account_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::hash::Hash;
use std::sync::RwLock;

use bincode::serialize;
use solana_account_decoder::UiDataSliceConfig;
use tokio::sync::OnceCell;
use tracing::info;
#[derive(Debug, Eq, PartialEq, Hash)]
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(UiDataSliceConfig {
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<UiDataSliceConfig>,
) -> 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(UiDataSliceConfig {
offset: 0,
length: 1024,
}),
)
.await;
assert_eq!(1024, test3_acc.unwrap().expect("test fail").data.len());
}
#[tokio::test]
Expand Down

0 comments on commit 1a21408

Please sign in to comment.