diff --git a/programs/bpf/benches/bpf_loader.rs b/programs/bpf/benches/bpf_loader.rs index 1c308b249b..fe4ceb07b9 100644 --- a/programs/bpf/benches/bpf_loader.rs +++ b/programs/bpf/benches/bpf_loader.rs @@ -6,24 +6,22 @@ extern crate test; extern crate solana_bpf_loader_program; use byteorder::{ByteOrder, LittleEndian, WriteBytesExt}; -use solana_bpf_loader_program::syscalls::SyscallError; use solana_measure::measure::Measure; use solana_rbpf::vm::{EbpfVm, InstructionMeter}; use solana_runtime::{ bank::Bank, bank_client::BankClient, + bpf_test_utils::MockInvokeContext, genesis_utils::{create_genesis_config, GenesisConfigInfo}, loader_utils::load_program, - process_instruction::{ - ComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, ProcessInstruction, - }, + process_instruction::{ComputeMeter, InvokeContext}, }; use solana_sdk::{ account::Account, bpf_loader, client::SyncClient, entrypoint::SUCCESS, - instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError}, + instruction::{AccountMeta, Instruction}, message::Message, pubkey::Pubkey, signature::{Keypair, Signer}, @@ -193,7 +191,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) { const BUDGET: u64 = 200_000; let loader_id = bpf_loader::id(); let mut invoke_context = MockInvokeContext::default(); - invoke_context.compute_meter.borrow_mut().remaining = BUDGET; + invoke_context.compute_meter.remaining = BUDGET; let compute_meter = invoke_context.get_compute_meter(); let elf = load_elf("tuner").unwrap(); @@ -248,80 +246,6 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) { ); } -#[derive(Debug, Default)] -pub struct MockInvokeContext { - key: Pubkey, - logger: MockLogger, - compute_budget: ComputeBudget, - compute_meter: Rc>, -} -impl InvokeContext for MockInvokeContext { - fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> { - Ok(()) - } - fn pop(&mut self) {} - fn verify_and_update( - &mut self, - _message: &Message, - _instruction: &CompiledInstruction, - _accounts: &[Rc>], - ) -> Result<(), InstructionError> { - Ok(()) - } - fn get_caller(&self) -> Result<&Pubkey, InstructionError> { - Ok(&self.key) - } - fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] { - &[] - } - fn get_logger(&self) -> Rc> { - Rc::new(RefCell::new(self.logger.clone())) - } - fn get_compute_budget(&self) -> &ComputeBudget { - &self.compute_budget - } - fn get_compute_meter(&self) -> Rc> { - self.compute_meter.clone() - } - fn add_executor(&mut self, _pubkey: &Pubkey, _executor: Arc) {} - fn get_executor(&mut self, _pubkey: &Pubkey) -> Option> { - None - } - fn record_instruction(&self, _instruction: &Instruction) {} - fn is_feature_active(&self, _feature_id: &Pubkey) -> bool { - true - } -} -#[derive(Debug, Default, Clone)] -pub struct MockLogger { - pub log: Rc>>, -} -impl Logger for MockLogger { - fn log_enabled(&self) -> bool { - true - } - fn log(&mut self, message: &str) { - self.log.borrow_mut().push(message.to_string()); - } -} -#[derive(Debug, Default, Clone)] -pub struct MockComputeMeter { - pub remaining: u64, -} -impl ComputeMeter for MockComputeMeter { - fn consume(&mut self, amount: u64) -> Result<(), InstructionError> { - let exceeded = self.remaining < amount; - self.remaining = self.remaining.saturating_sub(amount); - if exceeded { - return Err(InstructionError::ComputationalBudgetExceeded); - } - Ok(()) - } - fn get_remaining(&self) -> u64 { - self.remaining - } -} - /// Passed to the VM to enforce the compute budget #[derive(Clone)] struct MockInstructionMeter { diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index e11b1864d8..7d3ca5b0f8 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -7,15 +7,14 @@ use solana_bpf_loader_program::{ create_vm, serialization::{deserialize_parameters, serialize_parameters}, }; -use solana_rbpf::vm::{EbpfVm, InstructionMeter}; +use solana_rbpf::vm::EbpfVm; use solana_runtime::{ bank::Bank, bank_client::BankClient, + bpf_test_utils::MockInvokeContext, genesis_utils::{create_genesis_config, GenesisConfigInfo}, loader_utils::load_program, - process_instruction::{ - ComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, ProcessInstruction, - }, + process_instruction::ComputeBudget, }; use solana_sdk::{ account::Account, @@ -31,7 +30,7 @@ use solana_sdk::{ sysvar::{clock, fees, rent, slot_hashes, stake_history}, transaction::{Transaction, TransactionError}, }; -use std::{cell::RefCell, env, fs::File, io::Read, path::PathBuf, rc::Rc, sync::Arc}; +use std::{cell::RefCell, env, fs::File, io::Read, path::PathBuf, sync::Arc}; /// BPF program file extension const PLATFORM_FILE_EXTENSION_BPF: &str = "so"; @@ -776,82 +775,6 @@ fn assert_instruction_count() { } } -// Mock InvokeContext - -#[derive(Debug, Default)] -struct MockInvokeContext { - pub key: Pubkey, - pub logger: MockLogger, - pub compute_budget: ComputeBudget, - pub compute_meter: MockComputeMeter, -} -impl InvokeContext for MockInvokeContext { - fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> { - Ok(()) - } - fn pop(&mut self) {} - fn verify_and_update( - &mut self, - _message: &Message, - _instruction: &CompiledInstruction, - _accounts: &[Rc>], - ) -> Result<(), InstructionError> { - Ok(()) - } - fn get_caller(&self) -> Result<&Pubkey, InstructionError> { - Ok(&self.key) - } - fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] { - &[] - } - fn get_logger(&self) -> Rc> { - Rc::new(RefCell::new(self.logger.clone())) - } - fn get_compute_budget(&self) -> &ComputeBudget { - &self.compute_budget - } - fn get_compute_meter(&self) -> Rc> { - Rc::new(RefCell::new(self.compute_meter.clone())) - } - fn add_executor(&mut self, _pubkey: &Pubkey, _executor: Arc) {} - fn get_executor(&mut self, _pubkey: &Pubkey) -> Option> { - None - } - fn record_instruction(&self, _instruction: &Instruction) {} - fn is_feature_active(&self, _feature_id: &Pubkey) -> bool { - true - } -} - -#[derive(Debug, Default, Clone)] -struct MockComputeMeter {} -impl ComputeMeter for MockComputeMeter { - fn consume(&mut self, _amount: u64) -> Result<(), InstructionError> { - Ok(()) - } - fn get_remaining(&self) -> u64 { - u64::MAX - } -} -#[derive(Debug, Default, Clone)] -struct MockLogger {} -impl Logger for MockLogger { - fn log_enabled(&self) -> bool { - true - } - fn log(&mut self, _message: &str) { - // println!("{}", message); - } -} - -struct TestInstructionMeter {} -impl InstructionMeter for TestInstructionMeter { - fn consume(&mut self, _amount: u64) {} - fn get_remaining(&self) -> u64 { - u64::MAX - } -} - #[cfg(any(feature = "bpf_rust"))] #[test] fn test_program_bpf_instruction_introspection() { diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 6a85961088..d908c61633 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -313,102 +313,14 @@ mod tests { use super::*; use rand::Rng; use solana_runtime::{ + bpf_test_utils::MockInvokeContext, feature_set::FeatureSet, message_processor::{Executors, ThisInvokeContext}, - process_instruction::{ComputeBudget, Logger, ProcessInstruction}, - }; - use solana_sdk::{ - account::Account, instruction::CompiledInstruction, instruction::Instruction, - message::Message, rent::Rent, + process_instruction::ComputeBudget, }; + use solana_sdk::{account::Account, rent::Rent}; use std::{cell::RefCell, fs::File, io::Read, ops::Range, rc::Rc}; - #[derive(Debug, Default, Clone)] - pub struct MockComputeMeter { - pub remaining: u64, - } - impl ComputeMeter for MockComputeMeter { - fn consume(&mut self, amount: u64) -> Result<(), InstructionError> { - let exceeded = self.remaining < amount; - self.remaining = self.remaining.saturating_sub(amount); - if exceeded { - return Err(InstructionError::ComputationalBudgetExceeded); - } - Ok(()) - } - fn get_remaining(&self) -> u64 { - self.remaining - } - } - #[derive(Debug, Default, Clone)] - pub struct MockLogger { - pub log: Rc>>, - } - impl Logger for MockLogger { - fn log_enabled(&self) -> bool { - true - } - fn log(&mut self, message: &str) { - self.log.borrow_mut().push(message.to_string()); - } - } - #[derive(Debug)] - pub struct MockInvokeContext { - pub key: Pubkey, - pub logger: MockLogger, - pub compute_budget: ComputeBudget, - pub compute_meter: MockComputeMeter, - } - impl Default for MockInvokeContext { - fn default() -> Self { - MockInvokeContext { - key: Pubkey::default(), - logger: MockLogger::default(), - compute_budget: ComputeBudget::default(), - compute_meter: MockComputeMeter { - remaining: std::u64::MAX, - }, - } - } - } - impl InvokeContext for MockInvokeContext { - fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> { - Ok(()) - } - fn pop(&mut self) {} - fn verify_and_update( - &mut self, - _message: &Message, - _instruction: &CompiledInstruction, - _accounts: &[Rc>], - ) -> Result<(), InstructionError> { - Ok(()) - } - fn get_caller(&self) -> Result<&Pubkey, InstructionError> { - Ok(&self.key) - } - fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] { - &[] - } - fn get_logger(&self) -> Rc> { - Rc::new(RefCell::new(self.logger.clone())) - } - fn get_compute_budget(&self) -> &ComputeBudget { - &self.compute_budget - } - fn get_compute_meter(&self) -> Rc> { - Rc::new(RefCell::new(self.compute_meter.clone())) - } - fn add_executor(&mut self, _pubkey: &Pubkey, _executor: Arc) {} - fn get_executor(&mut self, _pubkey: &Pubkey) -> Option> { - None - } - fn record_instruction(&self, _instruction: &Instruction) {} - fn is_feature_active(&self, _feature_id: &Pubkey) -> bool { - true - } - } - struct TestInstructionMeter { remaining: u64, } diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index cee61d7343..b581409838 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -1237,7 +1237,7 @@ fn call<'a>( #[cfg(test)] mod tests { use super::*; - use crate::tests::{MockComputeMeter, MockLogger}; + use solana_runtime::bpf_test_utils::{MockComputeMeter, MockLogger}; use solana_sdk::hash::hashv; use std::str::FromStr; diff --git a/runtime/src/bpf_test_utils.rs b/runtime/src/bpf_test_utils.rs new file mode 100644 index 0000000000..8a7b43a77a --- /dev/null +++ b/runtime/src/bpf_test_utils.rs @@ -0,0 +1,96 @@ +use crate::process_instruction::{ + ComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, ProcessInstruction, +}; +use solana_sdk::{ + account::Account, instruction::CompiledInstruction, instruction::Instruction, + instruction::InstructionError, message::Message, pubkey::Pubkey, +}; +use std::{cell::RefCell, rc::Rc, sync::Arc}; + +#[derive(Debug, Default, Clone)] +pub struct MockComputeMeter { + pub remaining: u64, +} +impl ComputeMeter for MockComputeMeter { + fn consume(&mut self, amount: u64) -> Result<(), InstructionError> { + let exceeded = self.remaining < amount; + self.remaining = self.remaining.saturating_sub(amount); + if exceeded { + return Err(InstructionError::ComputationalBudgetExceeded); + } + Ok(()) + } + fn get_remaining(&self) -> u64 { + self.remaining + } +} + +#[derive(Debug, Default, Clone)] +pub struct MockLogger { + pub log: Rc>>, +} +impl Logger for MockLogger { + fn log_enabled(&self) -> bool { + true + } + fn log(&mut self, message: &str) { + self.log.borrow_mut().push(message.to_string()); + } +} + +#[derive(Debug)] +pub struct MockInvokeContext { + pub key: Pubkey, + pub logger: MockLogger, + pub compute_budget: ComputeBudget, + pub compute_meter: MockComputeMeter, +} +impl Default for MockInvokeContext { + fn default() -> Self { + MockInvokeContext { + key: Pubkey::default(), + logger: MockLogger::default(), + compute_budget: ComputeBudget::default(), + compute_meter: MockComputeMeter { + remaining: std::i64::MAX as u64, + }, + } + } +} +impl InvokeContext for MockInvokeContext { + fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> { + Ok(()) + } + fn pop(&mut self) {} + fn verify_and_update( + &mut self, + _message: &Message, + _instruction: &CompiledInstruction, + _accounts: &[Rc>], + ) -> Result<(), InstructionError> { + Ok(()) + } + fn get_caller(&self) -> Result<&Pubkey, InstructionError> { + Ok(&self.key) + } + fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] { + &[] + } + fn get_logger(&self) -> Rc> { + Rc::new(RefCell::new(self.logger.clone())) + } + fn get_compute_budget(&self) -> &ComputeBudget { + &self.compute_budget + } + fn get_compute_meter(&self) -> Rc> { + Rc::new(RefCell::new(self.compute_meter.clone())) + } + fn add_executor(&mut self, _pubkey: &Pubkey, _executor: Arc) {} + fn get_executor(&mut self, _pubkey: &Pubkey) -> Option> { + None + } + fn record_instruction(&self, _instruction: &Instruction) {} + fn is_feature_active(&self, _feature_id: &Pubkey) -> bool { + true + } +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index c2345e0ddd..078f5605c7 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -10,6 +10,7 @@ pub mod bank_forks; pub mod bank_utils; mod blockhash_queue; pub mod bloom; +pub mod bpf_test_utils; pub mod builtins; pub mod commitment; pub mod epoch_stakes;