Pipe FeatureSet though InvokeContext (#12536)

* Pipe FeatureSet though InvokeContext

* gate program size cap

* nit
This commit is contained in:
Jack May
2020-09-29 14:36:30 -07:00
committed by GitHub
parent ce98088457
commit 74fcb184b2
9 changed files with 124 additions and 180 deletions

View File

@@ -16,7 +16,10 @@ use solana_rbpf::{
memory_region::MemoryRegion,
vm::{EbpfVm, Executable, InstructionMeter},
};
use solana_runtime::process_instruction::{ComputeMeter, Executor, InvokeContext};
use solana_runtime::{
feature_set::compute_budget_config2,
process_instruction::{ComputeMeter, Executor, InvokeContext},
};
use solana_sdk::{
account::{is_executable, next_keyed_account, KeyedAccount},
bpf_loader, bpf_loader_deprecated,
@@ -78,19 +81,29 @@ macro_rules! log{
};
}
fn map_ebpf_error(
invoke_context: &mut dyn InvokeContext,
e: EbpfError<BPFError>,
) -> InstructionError {
let logger = invoke_context.get_logger();
log!(logger, "{}", e);
InstructionError::InvalidAccountData
}
pub fn create_and_cache_executor(
program: &KeyedAccount,
invoke_context: &mut dyn InvokeContext,
) -> Result<Arc<BPFExecutor>, InstructionError> {
let executable = EbpfVm::create_executable_from_elf(
&program.try_account_ref()?.data,
Some(bpf_verifier::check),
let executable = EbpfVm::create_executable_from_elf(&program.try_account_ref()?.data, None)
.map_err(|e| map_ebpf_error(invoke_context, e))?;
let (_, elf_bytes) = executable
.get_text_bytes()
.map_err(|e| map_ebpf_error(invoke_context, e))?;
bpf_verifier::check(
elf_bytes,
!invoke_context.is_feature_active(&compute_budget_config2::id()),
)
.map_err(|e| {
let logger = invoke_context.get_logger();
log!(logger, "{}", e);
InstructionError::InvalidAccountData
})?;
.map_err(|e| map_ebpf_error(invoke_context, EbpfError::UserError(e)))?;
let executor = Arc::new(BPFExecutor { executable });
invoke_context.add_executor(program.unsigned_key(), executor.clone());
Ok(executor)
@@ -271,6 +284,7 @@ mod tests {
use super::*;
use rand::Rng;
use solana_runtime::{
feature_set::FeatureSet,
message_processor::{Executors, ThisInvokeContext},
process_instruction::{ComputeBudget, Logger, ProcessInstruction},
};
@@ -313,6 +327,7 @@ mod tests {
pub struct MockInvokeContext {
pub key: Pubkey,
pub logger: MockLogger,
pub compute_budget: ComputeBudget,
pub compute_meter: MockComputeMeter,
}
impl Default for MockInvokeContext {
@@ -320,6 +335,7 @@ mod tests {
MockInvokeContext {
key: Pubkey::default(),
logger: MockLogger::default(),
compute_budget: ComputeBudget::default(),
compute_meter: MockComputeMeter {
remaining: std::u64::MAX,
},
@@ -348,11 +364,8 @@ mod tests {
fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
Rc::new(RefCell::new(self.logger.clone()))
}
fn is_cross_program_supported(&self) -> bool {
true
}
fn get_compute_budget(&self) -> ComputeBudget {
ComputeBudget::default()
fn get_compute_budget(&self) -> &ComputeBudget {
&self.compute_budget
}
fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>> {
Rc::new(RefCell::new(self.compute_meter.clone()))
@@ -362,6 +375,9 @@ mod tests {
None
}
fn record_instruction(&self, _instruction: &Instruction) {}
fn is_feature_active(&self, _feature_id: &Pubkey) -> bool {
true
}
}
struct TestInstructionMeter {
@@ -387,8 +403,7 @@ mod tests {
];
let input = &mut [0x00];
let executable =
EbpfVm::create_executable_from_text_bytes(program, Some(bpf_verifier::check)).unwrap();
let executable = EbpfVm::create_executable_from_text_bytes(program, None).unwrap();
let mut vm = EbpfVm::<BPFError>::new(executable.as_ref()).unwrap();
let instruction_meter = TestInstructionMeter { remaining: 10 };
vm.execute_program_metered(input, &[], &[], instruction_meter)
@@ -579,7 +594,6 @@ mod tests {
vec![],
vec![],
None,
true,
ComputeBudget {
max_units: 1,
log_units: 100,
@@ -590,6 +604,7 @@ mod tests {
},
Rc::new(RefCell::new(Executors::default())),
None,
Arc::new(FeatureSet::default()),
);
assert_eq!(
Err(InstructionError::Custom(194969602)),