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

Tmp depl slot 0 #609

Open
wants to merge 16 commits into
base: develop
Choose a base branch
from
4 changes: 4 additions & 0 deletions evm_loader/lib/src/commands/emulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ async fn emulate_trx_multiple_steps<'rpc, T: Tracer>(
}

if execution_step.is_reset {
tracer_result = evm.take_tracer();
if tracer_result.is_none() {
error!("EVM execution tracer is none ");
}
drop(evm);
drop(backend);
drop(storage);
Expand Down
19 changes: 5 additions & 14 deletions evm_loader/lib/src/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ pub use validator_client::CloneRpcClient;
use crate::commands::get_config::{BuildConfigSimulator, ConfigSimulator};
use crate::{NeonError, NeonResult};
use async_trait::async_trait;

use enum_dispatch::enum_dispatch;
use evm_loader::solana_program::bpf_loader_upgradeable::UpgradeableLoaderState;

pub use solana_account_decoder::UiDataSliceConfig as SliceConfig;
use solana_cli::cli::CliError;
use solana_client::client_error::{ClientErrorKind, Result as ClientResult};
use solana_client::client_error::Result as ClientResult;
use solana_sdk::{
account::Account, message::Message, native_token::lamports_to_sol, pubkey::Pubkey,
};
Expand All @@ -28,17 +29,8 @@ pub trait Rpc {
slice: Option<SliceConfig>,
) -> ClientResult<Option<Account>>;

async fn get_last_deployed_slot(&self, program_id: &Pubkey) -> ClientResult<Option<u64>> {
let slice = SliceConfig {
offset: 0,
length: UpgradeableLoaderState::size_of_programdata_metadata(),
};
let result = self.get_account_slice(program_id, Some(slice)).await;
if let Ok(Some(acc)) = result {
let slot = get_programdata_slot_from_account(&acc)?;
return Ok(slot);
}
Err(ClientErrorKind::Custom("Not account on slot ".to_string()).into())
async fn get_last_deployed_slot(&self, _program_id: &Pubkey) -> ClientResult<Option<u64>> {
return Ok(Some(1));
}

async fn get_account(&self, key: &Pubkey) -> ClientResult<Option<Account>> {
Expand Down Expand Up @@ -85,7 +77,6 @@ macro_rules! e {
};
}

use crate::types::programs_cache::get_programdata_slot_from_account;
pub(crate) use e;

pub(crate) async fn check_account_for_fee(
Expand Down
5 changes: 3 additions & 2 deletions evm_loader/lib/src/tracing/tracers/call_tracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,10 @@ impl CallTracer {

impl Tracer for CallTracer {
fn into_traces(mut self, emulator_gas_used: u64) -> Value {
let call_stack_len = self.call_stack.len();
assert!(
self.call_stack.len() == 1,
"incorrect number of top-level calls"
call_stack_len == 1,
"incorrect number of top-level calls, call_stack_len== {call_stack_len}, and it must be 1 . (emulator_gas_used: {emulator_gas_used})"
);

let call_frame = &mut self.call_stack[0];
Expand Down
5 changes: 5 additions & 0 deletions evm_loader/lib/src/tracing/tracers/struct_logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ impl EventListener for StructLogger {

impl Tracer for StructLogger {
fn into_traces(self, emulator_gas_used: u64) -> Value {
let call_stack_len = self.depth;
assert!(
call_stack_len == 0,
"incorrect number of top-level calls {call_stack_len} - StructLogger depth should be 0 "
);
let exit_status = self.exit_status.expect("Exit status should be set");
let result = StructLoggerResult {
gas: self.actual_gas_used.map_or(emulator_gas_used, U256::as_u64),
Expand Down
82 changes: 48 additions & 34 deletions evm_loader/lib/src/types/programs_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ pub struct KeyAccountCache {
pub addr: Pubkey,
pub slot: u64,
}
impl KeyAccountCache {
#[must_use]

pub const fn new(addr: &Pubkey, slot: u64) -> Self {
Self { addr: *addr, slot }
}
}

type ProgramDataCache<Value> = HashMap<KeyAccountCache, Value>;

Expand Down Expand Up @@ -78,25 +85,48 @@ async fn programdata_account_cache_get_instance() -> &'static ThreadSaveProgramD
.await
}

async fn programdata_account_cache_get(addr: Pubkey, slot: u64) -> Option<Account> {
let key = KeyAccountCache { addr, slot };
programdata_account_cache_get_instance().await.get(&key)
async fn programdata_account_cache_get(key: &KeyAccountCache) -> Option<Account> {
programdata_account_cache_get_instance().await.get(key)
}

async fn programdata_account_cache_add(addr: Pubkey, slot: u64, acc: Account) {
let key = KeyAccountCache { addr, slot };
async fn programdata_account_cache_add(key: KeyAccountCache, acc: Account) {
programdata_account_cache_get_instance().await.add(key, acc);
}

/// in case of Not upgradeable account - return option None
pub fn get_programdata_slot_from_account(acc: &Account) -> ClientResult<Option<u64>> {
if !bpf_loader_upgradeable::check_id(&acc.owner) {
return Ok(None);
/// in case of Not upgradeable account - return option None
pub fn get_program_programdata_address(acc: &Account) -> ClientResult<Option<Pubkey>> {
assert!(!bpf_loader_upgradeable::check_id(&acc.owner), "NOT AN ACC");

match deserialize::<UpgradeableLoaderState>(&acc.data) {
Ok(UpgradeableLoaderState::Program {
programdata_address,
..
}) => Ok(Some(programdata_address)),
Ok(_) => {
panic!("Unexpected account type! Only Program type is acceptable ");
}
Err(e) => {
eprintln!("Error occurred: {e:?}");
panic!("Failed to deserialize account data.");
}
}
}

pub fn get_programdata_slot_from_account(acc: &Account) -> ClientResult<Option<u64>> {
assert!(bpf_loader_upgradeable::check_id(&acc.owner), "NOT AN ACC");
match deserialize::<UpgradeableLoaderState>(&acc.data) {
Ok(UpgradeableLoaderState::ProgramData { slot, .. }) => Ok(Some(slot)),
Ok(_) => Ok(None),
Ok(UpgradeableLoaderState::Program {
programdata_address,
..
}) => {
info!(" programdata_address:{programdata_address}");
Ok(Some(0))
}

Ok(_) => {
panic!("Unexpected account type! Only ProgramData type is acceptable ");
}
Err(e) => {
eprintln!("Error occurred: {e:?}");
panic!("Failed to deserialize account data.");
Expand Down Expand Up @@ -127,16 +157,18 @@ pub async fn programdata_cache_get_values_by_keys(
"programdata_keys.size()!=future_requests.size()"
);
let results = join_all(future_requests).await;
for (result, key) in results.iter().zip(programdata_keys) {
for (result, addr) in results.iter().zip(programdata_keys) {
match result {
Ok(Some(account)) => {
if let Some(slot_val) = get_programdata_slot_from_account(account)? {
if let Some(acc) = programdata_account_cache_get(*key, slot_val).await {
let key = KeyAccountCache::new(addr, slot_val);
if let Some(acc) = programdata_account_cache_get(&key).await {
answer.push(Some(acc));
} else if let Ok(Some(tmp_acc)) = rpc.get_account(key).await {
} else if let Ok(Some(tmp_acc)) = rpc.get_account(&key.addr).await {
let current_slot =
get_programdata_slot_from_account(&tmp_acc)?.expect("No current slot ");
programdata_account_cache_add(*key, current_slot, tmp_acc.clone()).await;
let key = KeyAccountCache::new(addr, current_slot);
programdata_account_cache_add(key, tmp_acc.clone()).await;

answer.push(Some(tmp_acc));
} else {
Expand All @@ -147,11 +179,11 @@ pub async fn programdata_cache_get_values_by_keys(
}
}
Ok(None) => {
info!("Account for key {key:?} is None.");
info!("Account for key {addr:?} is None.");
answer.push(None);
}
Err(e) => {
info!("Error fetching account for key {key:?}: {e:?}");
info!("Error fetching account for key {addr:?}: {e:?}");
}
}
}
Expand Down Expand Up @@ -320,24 +352,6 @@ mod tests {
.is_none());
}

#[test]
fn test_add_and_get_value() {
let cache: ThreadSaveCache<String> = ThreadSaveCache::new();
let key = KeyAccountCache {
slot: 0,
addr: Pubkey::new_unique(),
};
let value = "test_value".to_string();

// Add the value to the cache
cache.add(key.clone(), value.clone());

// Retrieve the value from the cache
let result = cache.get(&key);
assert!(result.is_some());
assert_eq!(result.unwrap(), value);
}

#[test]
fn test_get_nonexistent_key() {
let cache: ThreadSaveCache<String> = ThreadSaveCache::new();
Expand Down
52 changes: 29 additions & 23 deletions evm_loader/program/src/evm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ impl<B: Database, T: EventListener> Machine<B, T> {
}
}

#[allow(unused_mut)]
#[maybe_async]
async fn new_call(
chain_id: u64,
Expand All @@ -266,8 +267,7 @@ impl<B: Database, T: EventListener> Machine<B, T> {
.await?;

let execution_code = backend.code(target).await?;

Ok(Self {
let mut answer = Self {
origin,
chain_id,
context: Context {
Expand All @@ -291,9 +291,23 @@ impl<B: Database, T: EventListener> Machine<B, T> {
parent: None,
phantom: PhantomData,
tracer,
})
};
begin_vm!(
answer,
backend,
answer.context,
answer.chain_id,
answer.call_data.to_vec(),
opcode_table::CALL
);

Ok(answer)
}
pub fn take_tracer(&mut self) -> Option<T> {
self.tracer.take()
}

#[allow(unused_mut)]
#[maybe_async]
async fn new_create(
chain_id: u64,
Expand All @@ -318,8 +332,7 @@ impl<B: Database, T: EventListener> Machine<B, T> {
backend
.transfer(origin, target, chain_id, trx.value())
.await?;

Ok(Self {
let mut answer = Self {
origin,
chain_id,
context: Context {
Expand All @@ -343,7 +356,17 @@ impl<B: Database, T: EventListener> Machine<B, T> {
parent: None,
phantom: PhantomData,
tracer,
})
};
begin_vm!(
answer,
backend,
answer.context,
answer.chain_id,
answer.execution_code.to_vec(),
opcode_table::CREATE
);

Ok(answer)
}

#[maybe_async]
Expand All @@ -354,23 +377,6 @@ impl<B: Database, T: EventListener> Machine<B, T> {
) -> Result<(ExitStatus, u64, Option<T>)> {
let mut step = 0_u64;

begin_vm!(
self,
backend,
self.context,
self.chain_id,
if self.reason == Reason::Call {
self.call_data.to_vec()
} else {
self.execution_code.to_vec()
},
if self.reason == Reason::Call {
opcode_table::CALL
} else {
opcode_table::CREATE
}
);

let status = if is_precompile_address(&self.context.contract) {
let value = Self::precompile(&self.context.contract, &self.call_data).unwrap();

Expand Down
Loading