diff --git a/evm_loader/lib/src/account_storage.rs b/evm_loader/lib/src/account_storage.rs index 46fa908a8..862eda6d7 100644 --- a/evm_loader/lib/src/account_storage.rs +++ b/evm_loader/lib/src/account_storage.rs @@ -1053,6 +1053,10 @@ impl AccountStorage for EmulatorAccountStorage<'_, T> { .unwrap() } + fn is_on_emulator(&self) -> bool { + true + } + fn is_valid_chain_id(&self, chain_id: u64) -> bool { for chain in &self.chains { if chain.id == chain_id { diff --git a/evm_loader/lib/src/commands/emulate.rs b/evm_loader/lib/src/commands/emulate.rs index 24858a0d1..3da0a4a73 100644 --- a/evm_loader/lib/src/commands/emulate.rs +++ b/evm_loader/lib/src/commands/emulate.rs @@ -226,6 +226,7 @@ async fn transfer_gas_limit<'rpc, T: Rpc + BuildConfigSimulator>( async fn calculate_response( steps_executed: u64, + step_on_solana: Option, exit_status: ExitStatus, storage: &EmulatorAccountStorage<'_, T>, tracer: Option, @@ -233,6 +234,9 @@ async fn calculate_response( ) -> NeonResult<(EmulateResponse, Option)> { debug!("Execute done, result={exit_status:?}"); debug!("{steps_executed} steps executed"); + if let Some(step) = step_on_solana { + debug!("Got Solana call on {step}"); + } let logs = storage.logs(); let execute_status = storage.execute_status; @@ -322,7 +326,7 @@ async fn emulate_trx_single_step<'rpc, T: Tracer>( ) -> NeonResult<(EmulateResponse, Option)> { let origin = emulate_request.tx.from; - let (exit_status, steps_executed, tracer) = { + let (exit_status, steps_executed, step_on_solana, tracer) = { let mut backend = SyncedExecutorState::new(storage); let mut evm = match Machine::new(tx, origin, &mut backend, tracer).await { Ok(evm) => evm, @@ -332,7 +336,8 @@ async fn emulate_trx_single_step<'rpc, T: Tracer>( } }; - let (exit_status, steps_executed, tracer) = evm.execute(step_limit, &mut backend).await?; + let (exit_status, steps_executed, step_on_solana, tracer) = + evm.execute(step_limit, &mut backend).await?; if exit_status == ExitStatus::StepLimit { error!("Step_limit={step_limit} exceeded"); @@ -341,11 +346,12 @@ async fn emulate_trx_single_step<'rpc, T: Tracer>( None, )); } - (exit_status, steps_executed, tracer) + (exit_status, steps_executed, step_on_solana, tracer) }; calculate_response( steps_executed, + step_on_solana, exit_status, storage, tracer, @@ -390,7 +396,7 @@ async fn emulate_trx_multiple_steps<'rpc, T: Tracer>( transfer_gas_limit(&mut storage, &tx, &origin, chain_id, increase_gas_limit).await?; - let (exit_status, steps_executed, tracer) = { + let (exit_status, steps_executed, step_on_solana, tracer) = { let mut backend = SyncedExecutorState::new(&mut storage); let mut evm = match Machine::new(&tx, origin, &mut backend, tracer).await { Ok(evm) => evm, @@ -402,6 +408,7 @@ async fn emulate_trx_multiple_steps<'rpc, T: Tracer>( let mut exit_status: ExitStatus = ExitStatus::Stop; let mut steps_executed = 0u64; + let mut step_on_solana = None; let mut tracer_result: Option = None; for (pos, execution_step) in execution_map.iter().enumerate() { if execution_step.steps == 0 && !execution_step.is_cancel { @@ -455,12 +462,13 @@ async fn emulate_trx_multiple_steps<'rpc, T: Tracer>( evm.set_tracer(tracer_result); } - let (local_exit_status, local_steps_executed, local_tracer) = evm + let (local_exit_status, local_steps_executed, local_step_on_solana, local_tracer) = evm .execute(u64::from(execution_step.steps), &mut backend) .await?; exit_status = local_exit_status; steps_executed += local_steps_executed; + step_on_solana = local_step_on_solana; tracer_result = local_tracer; } @@ -472,11 +480,12 @@ async fn emulate_trx_multiple_steps<'rpc, T: Tracer>( )); } - (exit_status, steps_executed, tracer_result) + (exit_status, steps_executed, step_on_solana, tracer_result) }; calculate_response( steps_executed, + step_on_solana, exit_status, &storage, tracer, diff --git a/evm_loader/program/src/account_storage/backend.rs b/evm_loader/program/src/account_storage/backend.rs index 9b33c2c36..1bfae1164 100644 --- a/evm_loader/program/src/account_storage/backend.rs +++ b/evm_loader/program/src/account_storage/backend.rs @@ -94,6 +94,10 @@ impl<'a> AccountStorage for ProgramAccountStorage<'a> { .map_or(U256::ZERO, |a| a.balance()) } + fn is_on_emulator(&self) -> bool { + false + } + fn is_valid_chain_id(&self, chain_id: u64) -> bool { crate::config::CHAIN_ID_LIST .binary_search_by_key(&chain_id, |c| c.0) diff --git a/evm_loader/program/src/account_storage/mod.rs b/evm_loader/program/src/account_storage/mod.rs index 5efd41264..f094d6b1e 100644 --- a/evm_loader/program/src/account_storage/mod.rs +++ b/evm_loader/program/src/account_storage/mod.rs @@ -65,6 +65,7 @@ pub trait AccountStorage: LogCollector { /// Get account balance async fn balance(&self, address: Address, chain_id: u64) -> U256; + fn is_on_emulator(&self) -> bool; fn is_valid_chain_id(&self, chain_id: u64) -> bool; fn chain_id_to_token(&self, chain_id: u64) -> Pubkey; fn default_chain_id(&self) -> u64; diff --git a/evm_loader/program/src/evm/database.rs b/evm_loader/program/src/evm/database.rs index 892469a93..a33958818 100644 --- a/evm_loader/program/src/evm/database.rs +++ b/evm_loader/program/src/evm/database.rs @@ -11,6 +11,7 @@ use solana_program::{ #[maybe_async(?Send)] pub trait Database: LogCollector { fn is_synced_state(&self) -> bool; + fn is_on_emulator(&self) -> bool; fn program_id(&self) -> &Pubkey; fn operator(&self) -> Pubkey; fn chain_id_to_token(&self, chain_id: u64) -> Pubkey; diff --git a/evm_loader/program/src/evm/mod.rs b/evm_loader/program/src/evm/mod.rs index 70b5a86c4..6d280c47b 100644 --- a/evm_loader/program/src/evm/mod.rs +++ b/evm_loader/program/src/evm/mod.rs @@ -170,7 +170,7 @@ pub struct Context { pub contract_chain_id: u64, pub value: U256, pub code_address: Option
, - pub interrupt_solana_call: bool, + pub got_solana_call: bool, } #[repr(C)] @@ -279,7 +279,7 @@ impl Machine { contract_chain_id: backend.contract_chain_id(target).await.unwrap_or(chain_id), value: trx.value(), code_address: Some(target), - interrupt_solana_call: true, + got_solana_call: false, }, gas_price: trx.gas_price(), gas_limit: trx.gas_limit(), @@ -332,7 +332,7 @@ impl Machine { contract_chain_id: chain_id, value: trx.value(), code_address: None, - interrupt_solana_call: true, + got_solana_call: false, }, gas_price: trx.gas_price(), gas_limit: trx.gas_limit(), @@ -356,8 +356,9 @@ impl Machine { &mut self, step_limit: u64, backend: &mut B, - ) -> Result<(ExitStatus, u64, Option)> { + ) -> Result<(ExitStatus, u64, Option, Option)> { let mut step = 0_u64; + let mut step_call_solana: Option = None; begin_vm!( self, @@ -401,6 +402,9 @@ impl Machine { } }; + if step_call_solana.is_none() && self.context.got_solana_call { + step_call_solana = Some(step); + } match opcode_result { Action::Continue => self.pc += 1, Action::Jump(target) => self.pc = target, @@ -414,7 +418,7 @@ impl Machine { } }; - Ok((status, step, self.tracer.take())) + Ok((status, step, step_call_solana, self.tracer.take())) } fn fork( diff --git a/evm_loader/program/src/evm/opcode.rs b/evm_loader/program/src/evm/opcode.rs index 124f524f6..3b9773443 100644 --- a/evm_loader/program/src/evm/opcode.rs +++ b/evm_loader/program/src/evm/opcode.rs @@ -1111,7 +1111,7 @@ impl Machine { contract_chain_id: chain_id, value, code_address: None, - interrupt_solana_call: true, + got_solana_call: false, }; begin_vm!(self, backend, context, chain_id, init_code); @@ -1166,7 +1166,7 @@ impl Machine { contract_chain_id: backend.contract_chain_id(address).await.unwrap_or(chain_id), value, code_address: Some(address), - interrupt_solana_call: true, + got_solana_call: false, }; begin_vm!(self, backend, context, chain_id, call_data); @@ -1307,7 +1307,7 @@ impl Machine { contract_chain_id: backend.contract_chain_id(address).await.unwrap_or(chain_id), value: U256::ZERO, code_address: Some(address), - interrupt_solana_call: true, + got_solana_call: false, }; begin_vm!(self, backend, context, chain_id, call_data); diff --git a/evm_loader/program/src/executor/precompile_extension/call_solana.rs b/evm_loader/program/src/executor/precompile_extension/call_solana.rs index f4c94efc5..1a6a47240 100644 --- a/evm_loader/program/src/executor/precompile_extension/call_solana.rs +++ b/evm_loader/program/src/executor/precompile_extension/call_solana.rs @@ -317,10 +317,19 @@ async fn execute_external_instruction( #[cfg(not(target_os = "solana"))] log::info!("instruction: {:?}", instruction); - if !state.is_synced_state() && context.interrupt_solana_call { - context.interrupt_solana_call = false; + if !state.is_synced_state() && !context.got_solana_call { + context.got_solana_call = true; return Err(Error::InterruptedCall); } + + /* + if !context.got_solana_call { + context.got_solana_call = true; + if !state.is_synced_state() /*|| !state.is_on_emulator()*/ { + return Err(Error::InterruptedCall); + } + } + */ let called_program = instruction.program_id; state.set_return_data(&[]); diff --git a/evm_loader/program/src/executor/state.rs b/evm_loader/program/src/executor/state.rs index 0e1ffd2a9..efb18f040 100644 --- a/evm_loader/program/src/executor/state.rs +++ b/evm_loader/program/src/executor/state.rs @@ -204,6 +204,9 @@ impl<'a, B: AccountStorage> Database for ExecutorState<'a, B> { fn is_synced_state(&self) -> bool { false } + fn is_on_emulator(&self) -> bool { + self.backend.is_on_emulator() + } fn program_id(&self) -> &Pubkey { self.backend.program_id() } diff --git a/evm_loader/program/src/executor/synced_state.rs b/evm_loader/program/src/executor/synced_state.rs index de047da3f..c55400934 100644 --- a/evm_loader/program/src/executor/synced_state.rs +++ b/evm_loader/program/src/executor/synced_state.rs @@ -60,6 +60,9 @@ impl<'a, B: SyncedAccountStorage> Database for SyncedExecutorState<'a, B> { fn is_synced_state(&self) -> bool { true } + fn is_on_emulator(&self) -> bool { + self.backend.is_on_emulator() + } fn program_id(&self) -> &Pubkey { self.backend.program_id() } diff --git a/evm_loader/program/src/instruction/transaction_execute.rs b/evm_loader/program/src/instruction/transaction_execute.rs index ef5330ce4..0fea9e6a9 100644 --- a/evm_loader/program/src/instruction/transaction_execute.rs +++ b/evm_loader/program/src/instruction/transaction_execute.rs @@ -31,7 +31,7 @@ pub fn execute( let mut backend = ExecutorState::new(&mut account_storage, &mut backend_data); let mut evm = Machine::new(&trx, origin, &mut backend, None::)?; - let (result, steps_executed, _) = evm.execute(u64::MAX, &mut backend)?; + let (result, steps_executed, _, _) = evm.execute(u64::MAX, &mut backend)?; (result, steps_executed) }; @@ -89,7 +89,7 @@ pub fn execute_with_solana_call( let mut backend = SyncedExecutorState::new(&mut account_storage); let mut evm = Machine::new(&trx, origin, &mut backend, None::)?; - let (result, steps_executed, _) = evm.execute(u64::MAX, &mut backend)?; + let (result, steps_executed, _, _) = evm.execute(u64::MAX, &mut backend)?; (result, steps_executed) }; diff --git a/evm_loader/program/src/instruction/transaction_step.rs b/evm_loader/program/src/instruction/transaction_step.rs index 68a395249..2133bf162 100644 --- a/evm_loader/program/src/instruction/transaction_step.rs +++ b/evm_loader/program/src/instruction/transaction_step.rs @@ -89,7 +89,7 @@ pub fn do_continue<'a>( let mut steps_executed = 0; if backend.exit_status().is_none() { - let (exit_status, steps_returned, _) = evm.execute(step_count, &mut backend)?; + let (exit_status, steps_returned, _, _) = evm.execute(step_count, &mut backend)?; if exit_status != ExitStatus::StepLimit { backend.set_exit_status(exit_status) } @@ -261,7 +261,7 @@ fn finalize_interrupted( &mut backend, None::, )?; - let (result, steps_executed, _) = evm.execute(u64::MAX, &mut backend)?; + let (result, steps_executed, _, _) = evm.execute(u64::MAX, &mut backend)?; (result, steps_executed) }; log_data(&[