diff --git a/evm_loader/lib/src/account_storage.rs b/evm_loader/lib/src/account_storage.rs index 499b0f8df..8485dcbf5 100644 --- a/evm_loader/lib/src/account_storage.rs +++ b/evm_loader/lib/src/account_storage.rs @@ -25,8 +25,7 @@ use serde::{Deserialize, Serialize}; 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::commands::get_config::{BuildConfigSimulator, ChainInfo}; use crate::tracing::{AccountOverride, AccountOverrides, BlockOverrides}; use serde_with::{serde_as, DisplayFromStr}; @@ -44,10 +43,10 @@ pub struct SolanaAccount { } #[allow(clippy::module_name_repetitions)] -pub struct EmulatorAccountStorage<'rpc> { +pub struct EmulatorAccountStorage<'rpc, T: Rpc> { pub accounts: RefCell>, pub gas: u64, - rpc: &'rpc RpcEnum, + rpc: &'rpc T, program_id: Pubkey, chains: Vec, block_number: u64, @@ -55,14 +54,14 @@ pub struct EmulatorAccountStorage<'rpc> { state_overrides: Option, } -impl<'rpc> EmulatorAccountStorage<'rpc> { +impl<'rpc, T: Rpc + BuildConfigSimulator> EmulatorAccountStorage<'rpc, T> { pub async fn new( - rpc: &'rpc RpcEnum, + rpc: &'rpc T, program_id: Pubkey, chains: Option>, block_overrides: Option, state_overrides: Option, - ) -> Result, NeonError> { + ) -> Result, NeonError> { trace!("backend::new"); let block_number = match block_overrides.as_ref().and_then(|o| o.number) { @@ -93,20 +92,22 @@ impl<'rpc> EmulatorAccountStorage<'rpc> { } pub async fn with_accounts( - rpc: &'rpc RpcEnum, + rpc: &'rpc T, program_id: Pubkey, accounts: &[Pubkey], chains: Option>, block_overrides: Option, state_overrides: Option, - ) -> Result, NeonError> { + ) -> Result, NeonError> { let storage = Self::new(rpc, program_id, chains, block_overrides, state_overrides).await?; storage.download_accounts(accounts).await?; Ok(storage) } +} +impl EmulatorAccountStorage<'_, T> { async fn download_accounts(&self, pubkeys: &[Pubkey]) -> Result<(), NeonError> { let accounts = self.rpc.get_multiple_accounts(pubkeys).await?; @@ -503,8 +504,8 @@ impl<'rpc> EmulatorAccountStorage<'rpc> { } } -#[async_trait(? Send)] -impl<'a> AccountStorage for EmulatorAccountStorage<'a> { +#[async_trait(?Send)] +impl AccountStorage for EmulatorAccountStorage<'_, T> { fn program_id(&self) -> &Pubkey { debug!("program_id"); &self.program_id diff --git a/evm_loader/lib/src/commands/collect_treasury.rs b/evm_loader/lib/src/commands/collect_treasury.rs index 2059ed187..709df6a5e 100644 --- a/evm_loader/lib/src/commands/collect_treasury.rs +++ b/evm_loader/lib/src/commands/collect_treasury.rs @@ -26,7 +26,7 @@ pub async fn execute( rpc_client: &CloneRpcClient, signer: &dyn Signer, ) -> NeonResult { - let neon_params = read_elf_parameters_from_account(config, &rpc_client.clone().into()).await?; + let neon_params = read_elf_parameters_from_account(config, rpc_client).await?; let pool_count: u32 = neon_params .get("NEON_TREASURY_POOL_COUNT") diff --git a/evm_loader/lib/src/commands/emulate.rs b/evm_loader/lib/src/commands/emulate.rs index 651c7efb0..0271b6248 100644 --- a/evm_loader/lib/src/commands/emulate.rs +++ b/evm_loader/lib/src/commands/emulate.rs @@ -5,7 +5,8 @@ use serde::{Deserialize, Serialize}; use solana_sdk::entrypoint::MAX_PERMITTED_DATA_INCREASE; use solana_sdk::pubkey::Pubkey; -use crate::rpc::RpcEnum; +use crate::commands::get_config::BuildConfigSimulator; +use crate::rpc::Rpc; use crate::syscall_stubs::setup_emulator_syscall_stubs; use crate::types::{EmulateRequest, TxParams}; use crate::{ @@ -50,16 +51,16 @@ impl EmulateResponse { } pub async fn execute( - rpc: &RpcEnum, + rpc: &(impl Rpc + BuildConfigSimulator), program_id: Pubkey, - config: EmulateRequest, + emulate_request: EmulateRequest, tracer: Option, ) -> NeonResult { - let block_overrides = config + let block_overrides = emulate_request .trace_config .as_ref() .and_then(|t| t.block_overrides.clone()); - let state_overrides = config + let state_overrides = emulate_request .trace_config .as_ref() .and_then(|t| t.state_overrides.clone()); @@ -67,22 +68,22 @@ pub async fn execute( let mut storage = EmulatorAccountStorage::with_accounts( rpc, program_id, - &config.accounts, - config.chains, + &emulate_request.accounts, + emulate_request.chains, block_overrides, state_overrides, ) .await?; - let step_limit = config.step_limit.unwrap_or(100000); + let step_limit = emulate_request.step_limit.unwrap_or(100000); setup_emulator_syscall_stubs(rpc).await?; - emulate_trx(config.tx, &mut storage, step_limit, tracer).await + emulate_trx(emulate_request.tx, &mut storage, step_limit, tracer).await } async fn emulate_trx( tx_params: TxParams, - storage: &mut EmulatorAccountStorage<'_>, + storage: &mut EmulatorAccountStorage<'_, impl Rpc>, step_limit: u64, tracer: Option, ) -> NeonResult { diff --git a/evm_loader/lib/src/commands/get_balance.rs b/evm_loader/lib/src/commands/get_balance.rs index e1d0da6c5..e9d6561a9 100644 --- a/evm_loader/lib/src/commands/get_balance.rs +++ b/evm_loader/lib/src/commands/get_balance.rs @@ -6,10 +6,9 @@ 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; +use super::get_config::{BuildConfigSimulator, ChainInfo}; #[derive(Debug, Serialize, Deserialize)] pub enum BalanceStatus { @@ -92,7 +91,7 @@ fn is_legacy_chain_id(id: u64, chains: &[ChainInfo]) -> bool { } pub async fn execute( - rpc: &RpcEnum, + rpc: &(impl Rpc + BuildConfigSimulator), program_id: &Pubkey, address: &[BalanceAddress], ) -> NeonResult> { diff --git a/evm_loader/lib/src/commands/get_config.rs b/evm_loader/lib/src/commands/get_config.rs index 0a642cc0c..e697de497 100644 --- a/evm_loader/lib/src/commands/get_config.rs +++ b/evm_loader/lib/src/commands/get_config.rs @@ -1,4 +1,6 @@ +use async_trait::async_trait; use base64::Engine; +use enum_dispatch::enum_dispatch; use std::collections::BTreeMap; use tokio::sync::{Mutex, MutexGuard, OnceCell}; @@ -18,7 +20,7 @@ use solana_sdk::{ use crate::{rpc::Rpc, NeonError, NeonResult}; -use crate::rpc::{CallDbClient, RpcEnum, SolanaRpc}; +use crate::rpc::{CallDbClient, CloneRpcClient, SolanaRpc}; use serde_with::{serde_as, DisplayFromStr}; use solana_client::nonblocking::rpc_client::RpcClient; @@ -114,30 +116,39 @@ async fn lock_program_test( context } -enum ConfigSimulator<'r> { +pub enum ConfigSimulator<'r> { Rpc(Pubkey, &'r RpcClient), ProgramTest(MutexGuard<'static, ProgramTestContext>), } -impl<'r> ConfigSimulator<'r> { - 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) +#[async_trait(?Send)] +#[enum_dispatch] +pub trait BuildConfigSimulator { + async fn build_config_simulator(&self, program_id: Pubkey) -> NeonResult; +} + +#[async_trait(?Send)] +impl BuildConfigSimulator for CloneRpcClient { + async fn build_config_simulator(&self, _program_id: Pubkey) -> NeonResult { + Ok(ConfigSimulator::Rpc( + self.get_account_with_sol().await?, + self, + )) } +} + +#[async_trait(?Send)] +impl BuildConfigSimulator for CallDbClient { + async fn build_config_simulator(&self, program_id: Pubkey) -> NeonResult { + let program_data = read_program_data_from_account(self, program_id).await?; + let mut program_test = lock_program_test(program_id, program_data).await; + program_test.get_new_latest_blockhash().await?; + Ok(ConfigSimulator::ProgramTest(program_test)) + } +} + +impl ConfigSimulator<'_> { async fn simulate_config( &mut self, program_id: Pubkey, @@ -195,97 +206,90 @@ impl<'r> ConfigSimulator<'r> { Ok(return_data) } -} -async fn get_version( - context: &mut ConfigSimulator<'_>, - program_id: Pubkey, -) -> NeonResult<(String, String)> { - let return_data = context.simulate_config(program_id, 0xA7, &[]).await?; - let (version, revision) = bincode::deserialize(&return_data)?; + async fn get_version(&mut self, program_id: Pubkey) -> NeonResult<(String, String)> { + let return_data = self.simulate_config(program_id, 0xA7, &[]).await?; + let (version, revision) = bincode::deserialize(&return_data)?; - Ok((version, revision)) -} + Ok((version, revision)) + } -async fn get_status(context: &mut ConfigSimulator<'_>, program_id: Pubkey) -> NeonResult { - let return_data = context.simulate_config(program_id, 0xA6, &[]).await?; - match return_data[0] { - 0 => Ok(Status::Emergency), - 1 => Ok(Status::Ok), - _ => Ok(Status::Unknown), + async fn get_status(&mut self, program_id: Pubkey) -> NeonResult { + let return_data = self.simulate_config(program_id, 0xA6, &[]).await?; + match return_data[0] { + 0 => Ok(Status::Emergency), + 1 => Ok(Status::Ok), + _ => Ok(Status::Unknown), + } } -} -async fn get_environment( - context: &mut ConfigSimulator<'_>, - program_id: Pubkey, -) -> NeonResult { - let return_data = context.simulate_config(program_id, 0xA2, &[]).await?; - let environment = String::from_utf8(return_data)?; + async fn get_environment(&mut self, program_id: Pubkey) -> NeonResult { + let return_data = self.simulate_config(program_id, 0xA2, &[]).await?; + let environment = String::from_utf8(return_data)?; - Ok(environment) -} + Ok(environment) + } -async fn get_chains( - context: &mut ConfigSimulator<'_>, - program_id: Pubkey, -) -> NeonResult> { - let mut result = Vec::new(); + async fn get_chains(&mut self, program_id: Pubkey) -> NeonResult> { + let mut result = Vec::new(); + + let return_data = self.simulate_config(program_id, 0xA0, &[]).await?; + let chain_count = return_data.as_slice().try_into()?; + let chain_count = usize::from_le_bytes(chain_count); - let return_data = context.simulate_config(program_id, 0xA0, &[]).await?; - let chain_count = return_data.as_slice().try_into()?; - let chain_count = usize::from_le_bytes(chain_count); + for i in 0..chain_count { + let index = i.to_le_bytes(); + let return_data = self.simulate_config(program_id, 0xA1, &index).await?; - for i in 0..chain_count { - let index = i.to_le_bytes(); - let return_data = context.simulate_config(program_id, 0xA1, &index).await?; + let (id, name, token) = bincode::deserialize(&return_data)?; + result.push(ChainInfo { id, name, token }); + } - let (id, name, token) = bincode::deserialize(&return_data)?; - result.push(ChainInfo { id, name, token }); + Ok(result) } - Ok(result) -} + async fn get_properties(&mut self, program_id: Pubkey) -> NeonResult> { + let mut result = BTreeMap::new(); -async fn get_properties( - context: &mut ConfigSimulator<'_>, - program_id: Pubkey, -) -> NeonResult> { - let mut result = BTreeMap::new(); + let return_data = self.simulate_config(program_id, 0xA3, &[]).await?; + let count = return_data.as_slice().try_into()?; + let count = usize::from_le_bytes(count); - let return_data = context.simulate_config(program_id, 0xA3, &[]).await?; - let count = return_data.as_slice().try_into()?; - let count = usize::from_le_bytes(count); + for i in 0..count { + let index = i.to_le_bytes(); + let return_data = self.simulate_config(program_id, 0xA4, &index).await?; - for i in 0..count { - let index = i.to_le_bytes(); - let return_data = context.simulate_config(program_id, 0xA4, &index).await?; + let (name, value) = bincode::deserialize(&return_data)?; + result.insert(name, value); + } - let (name, value) = bincode::deserialize(&return_data)?; - result.insert(name, value); + Ok(result) } - - Ok(result) } -pub async fn execute(rpc: &RpcEnum, program_id: Pubkey) -> NeonResult { - let mut simulator = ConfigSimulator::new(rpc, program_id).await?; +pub async fn execute( + rpc: &impl BuildConfigSimulator, + program_id: Pubkey, +) -> NeonResult { + let mut simulator = rpc.build_config_simulator(program_id).await?; - let (version, revision) = get_version(&mut simulator, program_id).await?; + let (version, revision) = simulator.get_version(program_id).await?; Ok(GetConfigResponse { version, revision, - status: get_status(&mut simulator, program_id).await?, - environment: get_environment(&mut simulator, program_id).await?, - chains: get_chains(&mut simulator, program_id).await?, - config: get_properties(&mut simulator, program_id).await?, + status: simulator.get_status(program_id).await?, + environment: simulator.get_environment(program_id).await?, + chains: simulator.get_chains(program_id).await?, + config: simulator.get_properties(program_id).await?, }) } -pub async fn read_chains(rpc: &RpcEnum, program_id: Pubkey) -> NeonResult> { - let mut simulator = ConfigSimulator::new(rpc, program_id).await?; +pub async fn read_chains( + rpc: &impl BuildConfigSimulator, + program_id: Pubkey, +) -> NeonResult> { + let mut simulator = rpc.build_config_simulator(program_id).await?; - let chains = get_chains(&mut simulator, program_id).await?; - Ok(chains) + simulator.get_chains(program_id).await } diff --git a/evm_loader/lib/src/commands/get_contract.rs b/evm_loader/lib/src/commands/get_contract.rs index 842bebb52..6f1a3d324 100644 --- a/evm_loader/lib/src/commands/get_contract.rs +++ b/evm_loader/lib/src/commands/get_contract.rs @@ -7,10 +7,9 @@ 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; +use super::get_config::{BuildConfigSimulator, ChainInfo}; #[serde_as] #[derive(Debug, Serialize, Deserialize)] @@ -75,7 +74,7 @@ fn read_account( } pub async fn execute( - rpc: &RpcEnum, + rpc: &(impl Rpc + BuildConfigSimulator), program_id: &Pubkey, accounts: &[Address], ) -> NeonResult> { diff --git a/evm_loader/lib/src/commands/get_holder.rs b/evm_loader/lib/src/commands/get_holder.rs index 13fa2bcd1..1ad6aff13 100644 --- a/evm_loader/lib/src/commands/get_holder.rs +++ b/evm_loader/lib/src/commands/get_holder.rs @@ -12,7 +12,6 @@ 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)] @@ -141,7 +140,7 @@ pub fn read_holder(program_id: &Pubkey, info: AccountInfo) -> NeonResult NeonResult { diff --git a/evm_loader/lib/src/commands/get_neon_elf.rs b/evm_loader/lib/src/commands/get_neon_elf.rs index a710656ee..5e88bcaaa 100644 --- a/evm_loader/lib/src/commands/get_neon_elf.rs +++ b/evm_loader/lib/src/commands/get_neon_elf.rs @@ -7,7 +7,7 @@ use solana_sdk::{ }; use std::{collections::HashMap, convert::TryFrom, fs::File, io::Read}; -use crate::rpc::{Rpc, RpcEnum}; +use crate::rpc::Rpc; use crate::{errors::NeonError, Config, NeonResult}; pub type GetNeonElfReturn = HashMap; @@ -17,7 +17,7 @@ pub struct CachedElfParams { } impl CachedElfParams { - pub async fn new(config: &Config, rpc: &RpcEnum) -> Self { + pub async fn new(config: &Config, rpc: &impl Rpc) -> Self { Self { elf_params: read_elf_parameters_from_account(config, rpc) .await @@ -144,7 +144,7 @@ pub fn get_elf_parameter(data: &[u8], elf_parameter: &str) -> Result { pub async fn read_elf_parameters_from_account( config: &Config, - rpc: &RpcEnum, + rpc: &impl Rpc, ) -> Result { let (_, program_data) = read_program_data_from_account(config, rpc, &config.evm_loader).await?; Ok(read_elf_parameters(config, &program_data)) @@ -152,7 +152,7 @@ pub async fn read_elf_parameters_from_account( pub async fn read_program_data_from_account( config: &Config, - rpc: &RpcEnum, + rpc: &impl Rpc, evm_loader: &Pubkey, ) -> Result<(Option, Vec), NeonError> { let account = rpc @@ -224,14 +224,14 @@ fn read_program_params_from_file( async fn read_program_params_from_account( config: &Config, - rpc: &RpcEnum, + rpc: &impl Rpc, ) -> NeonResult { read_elf_parameters_from_account(config, rpc).await } pub async fn execute( config: &Config, - rpc: &RpcEnum, + rpc: &impl Rpc, program_location: Option<&str>, ) -> NeonResult { if let Some(program_location) = program_location { diff --git a/evm_loader/lib/src/commands/get_storage_at.rs b/evm_loader/lib/src/commands/get_storage_at.rs index feaf4dc79..24cee229d 100644 --- a/evm_loader/lib/src/commands/get_storage_at.rs +++ b/evm_loader/lib/src/commands/get_storage_at.rs @@ -4,14 +4,15 @@ use solana_sdk::pubkey::Pubkey; use evm_loader::{account_storage::AccountStorage, types::Address}; -use crate::rpc::RpcEnum; +use crate::commands::get_config::BuildConfigSimulator; +use crate::rpc::Rpc; use crate::{account_storage::EmulatorAccountStorage, NeonResult}; #[derive(Debug, Default, Serialize, Deserialize)] pub struct GetStorageAtReturn(pub [u8; 32]); pub async fn execute( - rpc: &RpcEnum, + rpc: &(impl Rpc + BuildConfigSimulator), program_id: &Pubkey, address: Address, index: U256, diff --git a/evm_loader/lib/src/commands/init_environment.rs b/evm_loader/lib/src/commands/init_environment.rs index fdcb02aee..044dfc52e 100644 --- a/evm_loader/lib/src/commands/init_environment.rs +++ b/evm_loader/lib/src/commands/init_environment.rs @@ -129,9 +129,8 @@ 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, &rpc_enum, &config.evm_loader).await?; + read_program_data_from_account(config, client, &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)); @@ -204,7 +203,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(&rpc_enum, config.evm_loader).await?; + let chains = super::get_config::read_chains(client, config.evm_loader).await?; for chain in chains { let pool = get_associated_token_address(&deposit_authority, &chain.token); diff --git a/evm_loader/lib/src/commands/trace.rs b/evm_loader/lib/src/commands/trace.rs index 1496f41d9..b6f8251fb 100644 --- a/evm_loader/lib/src/commands/trace.rs +++ b/evm_loader/lib/src/commands/trace.rs @@ -3,17 +3,18 @@ use std::rc::Rc; use serde_json::Value; use solana_sdk::pubkey::Pubkey; +use crate::commands::get_config::BuildConfigSimulator; use crate::errors::NeonError; -use crate::rpc::RpcEnum; +use crate::rpc::Rpc; use crate::tracing::tracers::new_tracer; use crate::types::EmulateRequest; pub async fn trace_transaction( - rpc: &RpcEnum, + rpc: &(impl Rpc + BuildConfigSimulator), program_id: Pubkey, - config: EmulateRequest, + emulate_request: EmulateRequest, ) -> Result { - let trace_config = config + let trace_config = emulate_request .trace_config .as_ref() .map(|c| c.trace_config.clone()) @@ -22,7 +23,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, program_id, config, emulation_tracer).await?; + let r = super::emulate::execute(rpc, program_id, emulate_request, 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/rpc/mod.rs b/evm_loader/lib/src/rpc/mod.rs index 799305ce4..0a641e027 100644 --- a/evm_loader/lib/src/rpc/mod.rs +++ b/evm_loader/lib/src/rpc/mod.rs @@ -5,6 +5,7 @@ pub use db_call_client::CallDbClient; pub use validator_client::CloneRpcClient; pub use validator_client::SolanaRpc; +use crate::commands::get_config::{BuildConfigSimulator, ConfigSimulator}; use crate::{NeonError, NeonResult}; use async_trait::async_trait; use enum_dispatch::enum_dispatch; @@ -34,7 +35,7 @@ pub trait Rpc { async fn get_slot(&self) -> ClientResult; } -#[enum_dispatch(Rpc)] +#[enum_dispatch(BuildConfigSimulator, Rpc)] pub enum RpcEnum { CloneRpcClient, CallDbClient, diff --git a/evm_loader/lib/src/syscall_stubs.rs b/evm_loader/lib/src/syscall_stubs.rs index d2608edd7..4f996e4c1 100644 --- a/evm_loader/lib/src/syscall_stubs.rs +++ b/evm_loader/lib/src/syscall_stubs.rs @@ -1,7 +1,6 @@ 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; @@ -13,7 +12,7 @@ pub struct EmulatorStubs { } impl EmulatorStubs { - pub async fn new(rpc: &RpcEnum) -> Result, NeonError> { + pub async fn new(rpc: &impl Rpc) -> Result, NeonError> { let rent_pubkey = solana_sdk::sysvar::rent::id(); let data = rpc .get_account(&rent_pubkey) @@ -57,7 +56,7 @@ impl SyscallStubs for EmulatorStubs { } } -pub async fn setup_emulator_syscall_stubs(rpc: &RpcEnum) -> Result<(), NeonError> { +pub async fn setup_emulator_syscall_stubs(rpc: &impl Rpc) -> Result<(), NeonError> { let syscall_stubs = EmulatorStubs::new(rpc).await?; solana_sdk::program_stubs::set_syscall_stubs(syscall_stubs);