Pipe FeatureSet though InvokeContext (#12536)
* Pipe FeatureSet though InvokeContext * gate program size cap * nit
This commit is contained in:
parent
ce98088457
commit
74fcb184b2
|
@ -218,7 +218,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
|||
"Tuner must consume the whole budget"
|
||||
);
|
||||
println!(
|
||||
"{:?} Consumed compute budget took {:?} us ({:?} instructions)",
|
||||
"{:?} compute units took {:?} us ({:?} instructions)",
|
||||
BUDGET - instruction_meter.get_remaining(),
|
||||
measure.as_us(),
|
||||
vm.get_total_instruction_count(),
|
||||
|
@ -229,6 +229,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
|||
pub struct MockInvokeContext {
|
||||
key: Pubkey,
|
||||
logger: MockLogger,
|
||||
compute_budget: ComputeBudget,
|
||||
compute_meter: Rc<RefCell<MockComputeMeter>>,
|
||||
}
|
||||
impl InvokeContext for MockInvokeContext {
|
||||
|
@ -253,11 +254,8 @@ impl InvokeContext for MockInvokeContext {
|
|||
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>> {
|
||||
self.compute_meter.clone()
|
||||
|
@ -267,6 +265,9 @@ impl InvokeContext for MockInvokeContext {
|
|||
None
|
||||
}
|
||||
fn record_instruction(&self, _instruction: &Instruction) {}
|
||||
fn is_feature_active(&self, _feature_id: &Pubkey) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct MockLogger {
|
||||
|
|
|
@ -23,7 +23,6 @@ use solana_sdk::{
|
|||
client::SyncClient,
|
||||
clock::{DEFAULT_SLOTS_PER_EPOCH, MAX_PROCESSING_AGE},
|
||||
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
|
||||
|
||||
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
|
||||
message::Message,
|
||||
pubkey::Pubkey,
|
||||
|
@ -657,6 +656,7 @@ fn assert_instruction_count() {
|
|||
struct MockInvokeContext {
|
||||
pub key: Pubkey,
|
||||
pub logger: MockLogger,
|
||||
pub compute_budget: ComputeBudget,
|
||||
pub compute_meter: MockComputeMeter,
|
||||
}
|
||||
impl InvokeContext for MockInvokeContext {
|
||||
|
@ -681,11 +681,8 @@ impl InvokeContext for MockInvokeContext {
|
|||
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()))
|
||||
|
@ -695,6 +692,9 @@ impl InvokeContext for MockInvokeContext {
|
|||
None
|
||||
}
|
||||
fn record_instruction(&self, _instruction: &Instruction) {}
|
||||
fn is_feature_active(&self, _feature_id: &Pubkey) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
|
|
|
@ -54,11 +54,11 @@ pub enum VerifierError {
|
|||
InvalidRegister(usize),
|
||||
}
|
||||
|
||||
fn check_prog_len(prog: &[u8]) -> Result<(), BPFError> {
|
||||
fn check_prog_len(prog: &[u8], is_program_size_cap: bool) -> Result<(), BPFError> {
|
||||
if prog.len() % ebpf::INSN_SIZE != 0 {
|
||||
return Err(VerifierError::ProgramLengthNotMultiple.into());
|
||||
}
|
||||
if prog.len() > ebpf::PROG_MAX_SIZE {
|
||||
if is_program_size_cap && prog.len() > ebpf::PROG_MAX_SIZE {
|
||||
return Err(VerifierError::ProgramTooLarge(prog.len() / ebpf::INSN_SIZE).into());
|
||||
}
|
||||
|
||||
|
@ -139,8 +139,8 @@ fn check_imm_register(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), Verifier
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn check(prog: &[u8]) -> Result<(), BPFError> {
|
||||
check_prog_len(prog)?;
|
||||
pub fn check(prog: &[u8], is_program_size_cap: bool) -> Result<(), BPFError> {
|
||||
check_prog_len(prog, is_program_size_cap)?;
|
||||
|
||||
let mut insn_ptr: usize = 0;
|
||||
while insn_ptr * ebpf::INSN_SIZE < prog.len() {
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -94,6 +94,7 @@ pub fn register_syscalls<'a>(
|
|||
invoke_context: &'a mut dyn InvokeContext,
|
||||
) -> Result<MemoryRegion, EbpfError<BPFError>> {
|
||||
let compute_budget = invoke_context.get_compute_budget();
|
||||
|
||||
// Syscall functions common across languages
|
||||
|
||||
vm.register_syscall_ex("abort", syscall_abort)?;
|
||||
|
@ -115,36 +116,35 @@ pub fn register_syscalls<'a>(
|
|||
logger: invoke_context.get_logger(),
|
||||
}),
|
||||
)?;
|
||||
if invoke_context.is_cross_program_supported() {
|
||||
vm.register_syscall_with_context_ex(
|
||||
"sol_create_program_address",
|
||||
Box::new(SyscallCreateProgramAddress {
|
||||
cost: compute_budget.create_program_address_units,
|
||||
compute_meter: invoke_context.get_compute_meter(),
|
||||
loader_id,
|
||||
}),
|
||||
)?;
|
||||
|
||||
// Cross-program invocation syscalls
|
||||
vm.register_syscall_with_context_ex(
|
||||
"sol_create_program_address",
|
||||
Box::new(SyscallCreateProgramAddress {
|
||||
cost: compute_budget.create_program_address_units,
|
||||
compute_meter: invoke_context.get_compute_meter(),
|
||||
loader_id,
|
||||
}),
|
||||
)?;
|
||||
|
||||
let invoke_context = Rc::new(RefCell::new(invoke_context));
|
||||
vm.register_syscall_with_context_ex(
|
||||
"sol_invoke_signed_c",
|
||||
Box::new(SyscallInvokeSignedC {
|
||||
callers_keyed_accounts,
|
||||
invoke_context: invoke_context.clone(),
|
||||
loader_id,
|
||||
}),
|
||||
)?;
|
||||
vm.register_syscall_with_context_ex(
|
||||
"sol_invoke_signed_rust",
|
||||
Box::new(SyscallInvokeSignedRust {
|
||||
callers_keyed_accounts,
|
||||
invoke_context: invoke_context.clone(),
|
||||
loader_id,
|
||||
}),
|
||||
)?;
|
||||
}
|
||||
// Cross-program invocation syscalls
|
||||
|
||||
let invoke_context = Rc::new(RefCell::new(invoke_context));
|
||||
vm.register_syscall_with_context_ex(
|
||||
"sol_invoke_signed_c",
|
||||
Box::new(SyscallInvokeSignedC {
|
||||
callers_keyed_accounts,
|
||||
invoke_context: invoke_context.clone(),
|
||||
loader_id,
|
||||
}),
|
||||
)?;
|
||||
vm.register_syscall_with_context_ex(
|
||||
"sol_invoke_signed_rust",
|
||||
Box::new(SyscallInvokeSignedRust {
|
||||
callers_keyed_accounts,
|
||||
invoke_context: invoke_context.clone(),
|
||||
loader_id,
|
||||
}),
|
||||
)?;
|
||||
|
||||
// Memory allocator
|
||||
let heap = vec![0_u8; DEFAULT_HEAP_SIZE];
|
||||
|
@ -1044,7 +1044,6 @@ fn call<'a>(
|
|||
}
|
||||
message_processor.add_loader(bpf_loader::id(), crate::process_instruction);
|
||||
message_processor.add_loader(bpf_loader_deprecated::id(), crate::process_instruction);
|
||||
message_processor.set_cross_program_support(invoke_context.is_cross_program_supported());
|
||||
|
||||
#[allow(clippy::deref_addrof)]
|
||||
match message_processor.process_cross_program_instruction(
|
||||
|
|
|
@ -18,9 +18,7 @@ use crate::{
|
|||
log_collector::LogCollector,
|
||||
message_processor::{Executors, MessageProcessor},
|
||||
nonce_utils,
|
||||
process_instruction::{
|
||||
ComputeBudget, Executor, ProcessInstruction, ProcessInstructionWithContext,
|
||||
},
|
||||
process_instruction::{Executor, ProcessInstruction, ProcessInstructionWithContext},
|
||||
rent_collector::RentCollector,
|
||||
stakes::Stakes,
|
||||
status_cache::{SlotDelta, StatusCache},
|
||||
|
@ -1476,15 +1474,6 @@ impl Bank {
|
|||
debug!("Added native program {} under {:?}", name, program_id);
|
||||
}
|
||||
|
||||
pub fn set_cross_program_support(&mut self, is_supported: bool) {
|
||||
self.message_processor
|
||||
.set_cross_program_support(is_supported);
|
||||
}
|
||||
|
||||
pub fn set_compute_budget(&mut self, budget: ComputeBudget) {
|
||||
self.message_processor.set_compute_budget(budget);
|
||||
}
|
||||
|
||||
pub fn set_rent_burn_percentage(&mut self, burn_percent: u8) {
|
||||
self.rent_collector.rent.burn_percent = burn_percent;
|
||||
}
|
||||
|
@ -2155,7 +2144,7 @@ impl Bank {
|
|||
log_collector.clone(),
|
||||
executors.clone(),
|
||||
instruction_recorders.as_deref(),
|
||||
&self.feature_set,
|
||||
self.feature_set.clone(),
|
||||
);
|
||||
|
||||
Self::compile_recorded_instructions(
|
||||
|
@ -3610,8 +3599,6 @@ impl Bank {
|
|||
}
|
||||
|
||||
self.ensure_feature_builtins(init_finish_or_warp, &new_feature_activations);
|
||||
self.recheck_cross_program_support();
|
||||
self.recheck_compute_budget();
|
||||
self.reconfigure_token2_native_mint();
|
||||
self.ensure_no_storage_rewards_pool();
|
||||
}
|
||||
|
@ -3675,35 +3662,6 @@ impl Bank {
|
|||
}
|
||||
}
|
||||
|
||||
fn recheck_cross_program_support(&mut self) {
|
||||
if ClusterType::MainnetBeta == self.cluster_type() {
|
||||
self.set_cross_program_support(self.epoch() >= 63);
|
||||
} else {
|
||||
self.set_cross_program_support(true);
|
||||
}
|
||||
}
|
||||
|
||||
fn recheck_compute_budget(&mut self) {
|
||||
let compute_budget = if ClusterType::MainnetBeta == self.cluster_type() {
|
||||
if self.epoch() >= u64::MAX - 1 {
|
||||
ComputeBudget::default()
|
||||
} else {
|
||||
// Original
|
||||
ComputeBudget {
|
||||
max_units: 100_000,
|
||||
log_units: 0,
|
||||
log_64_units: 0,
|
||||
create_program_address_units: 0,
|
||||
invoke_units: 0,
|
||||
max_invoke_depth: 2,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ComputeBudget::default()
|
||||
};
|
||||
self.set_compute_budget(compute_budget);
|
||||
}
|
||||
|
||||
fn apply_spl_token_v2_multisig_fix(&mut self) {
|
||||
if let Some(mut account) = self.get_account(&inline_spl_token_v2_0::id()) {
|
||||
self.capitalization.fetch_sub(account.lamports, Relaxed);
|
||||
|
@ -8701,19 +8659,6 @@ mod tests {
|
|||
assert_eq!(bank.get_balance(&mint_keypair.pubkey()), 496); // no transaction fee charged
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_finish_init() {
|
||||
let (genesis_config, _mint_keypair) = create_genesis_config(100_000);
|
||||
let mut bank = Bank::new(&genesis_config);
|
||||
bank.message_processor = MessageProcessor::default();
|
||||
bank.message_processor.set_cross_program_support(false);
|
||||
|
||||
// simulate bank is just after deserialized from snapshot
|
||||
bank.finish_init(&genesis_config, None);
|
||||
|
||||
assert_eq!(bank.message_processor.get_cross_program_support(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_builtin_program_no_overwrite() {
|
||||
let (genesis_config, _mint_keypair) = create_genesis_config(100_000);
|
||||
|
|
|
@ -29,6 +29,10 @@ pub mod bpf_loader2_program {
|
|||
solana_sdk::declare_id!("DFBnrgThdzH4W6wZ12uGPoWcMnvfZj11EHnxHcVxLPhD");
|
||||
}
|
||||
|
||||
pub mod compute_budget_config2 {
|
||||
solana_sdk::declare_id!("HxvjqDSiF5sYdSYuCXsUnS8UeAoWsMT9iGoFP8pgV1mB");
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Map of feature identifiers to user-visible description
|
||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||
|
@ -38,6 +42,7 @@ lazy_static! {
|
|||
(pico_inflation::id(), "pico-inflation"),
|
||||
(spl_token_v2_multisig_fix::id(), "spl-token multisig fix"),
|
||||
(bpf_loader2_program::id(), "bpf_loader2 program"),
|
||||
(compute_budget_config2::id(), "1ms compute budget"),
|
||||
/*************** ADD NEW FEATURES HERE ***************/
|
||||
]
|
||||
.iter()
|
||||
|
@ -78,12 +83,3 @@ impl Default for FeatureSet {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FeatureSet {
|
||||
pub fn enabled() -> Self {
|
||||
Self {
|
||||
active: FEATURE_NAMES.keys().cloned().collect(),
|
||||
inactive: HashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
feature_set::{self, FeatureSet},
|
||||
feature_set::{compute_budget_config2, instructions_sysvar_enabled, FeatureSet},
|
||||
instruction_recorder::InstructionRecorder,
|
||||
log_collector::LogCollector,
|
||||
native_loader::NativeLoader,
|
||||
|
@ -206,11 +206,11 @@ pub struct ThisInvokeContext {
|
|||
pre_accounts: Vec<PreAccount>,
|
||||
programs: Vec<(Pubkey, ProcessInstruction)>,
|
||||
logger: Rc<RefCell<dyn Logger>>,
|
||||
is_cross_program_supported: bool,
|
||||
compute_budget: ComputeBudget,
|
||||
compute_meter: Rc<RefCell<dyn ComputeMeter>>,
|
||||
executors: Rc<RefCell<Executors>>,
|
||||
instruction_recorder: Option<InstructionRecorder>,
|
||||
feature_set: Arc<FeatureSet>,
|
||||
}
|
||||
impl ThisInvokeContext {
|
||||
pub fn new(
|
||||
|
@ -219,10 +219,10 @@ impl ThisInvokeContext {
|
|||
pre_accounts: Vec<PreAccount>,
|
||||
programs: Vec<(Pubkey, ProcessInstruction)>,
|
||||
log_collector: Option<Rc<LogCollector>>,
|
||||
is_cross_program_supported: bool,
|
||||
compute_budget: ComputeBudget,
|
||||
executors: Rc<RefCell<Executors>>,
|
||||
instruction_recorder: Option<InstructionRecorder>,
|
||||
feature_set: Arc<FeatureSet>,
|
||||
) -> Self {
|
||||
let mut program_ids = Vec::with_capacity(compute_budget.max_invoke_depth);
|
||||
program_ids.push(*program_id);
|
||||
|
@ -232,13 +232,13 @@ impl ThisInvokeContext {
|
|||
pre_accounts,
|
||||
programs,
|
||||
logger: Rc::new(RefCell::new(ThisLogger { log_collector })),
|
||||
is_cross_program_supported,
|
||||
compute_budget,
|
||||
compute_meter: Rc::new(RefCell::new(ThisComputeMeter {
|
||||
remaining: compute_budget.max_units,
|
||||
})),
|
||||
executors,
|
||||
instruction_recorder,
|
||||
feature_set,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,11 +286,8 @@ impl InvokeContext for ThisInvokeContext {
|
|||
fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
|
||||
self.logger.clone()
|
||||
}
|
||||
fn is_cross_program_supported(&self) -> bool {
|
||||
self.is_cross_program_supported
|
||||
}
|
||||
fn get_compute_budget(&self) -> ComputeBudget {
|
||||
self.compute_budget
|
||||
fn get_compute_budget(&self) -> &ComputeBudget {
|
||||
&self.compute_budget
|
||||
}
|
||||
fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>> {
|
||||
self.compute_meter.clone()
|
||||
|
@ -306,6 +303,9 @@ impl InvokeContext for ThisInvokeContext {
|
|||
recorder.record_instruction(instruction.clone());
|
||||
}
|
||||
}
|
||||
fn is_feature_active(&self, feature_id: &Pubkey) -> bool {
|
||||
self.feature_set.is_active(feature_id)
|
||||
}
|
||||
}
|
||||
pub struct ThisLogger {
|
||||
log_collector: Option<Rc<LogCollector>>,
|
||||
|
@ -330,10 +330,6 @@ pub struct MessageProcessor {
|
|||
loaders: Vec<(Pubkey, ProcessInstructionWithContext)>,
|
||||
#[serde(skip)]
|
||||
native_loader: NativeLoader,
|
||||
#[serde(skip)]
|
||||
is_cross_program_supported: bool,
|
||||
#[serde(skip)]
|
||||
compute_budget: ComputeBudget,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for MessageProcessor {
|
||||
|
@ -343,8 +339,6 @@ impl std::fmt::Debug for MessageProcessor {
|
|||
programs: Vec<String>,
|
||||
loaders: Vec<String>,
|
||||
native_loader: &'a NativeLoader,
|
||||
is_cross_program_supported: bool,
|
||||
compute_budget: ComputeBudget,
|
||||
}
|
||||
// rustc doesn't compile due to bug without this work around
|
||||
// https://github.com/rust-lang/rust/issues/50280
|
||||
|
@ -367,8 +361,6 @@ impl std::fmt::Debug for MessageProcessor {
|
|||
})
|
||||
.collect::<Vec<_>>(),
|
||||
native_loader: &self.native_loader,
|
||||
is_cross_program_supported: self.is_cross_program_supported,
|
||||
compute_budget: self.compute_budget,
|
||||
};
|
||||
|
||||
write!(f, "{:?}", processor)
|
||||
|
@ -381,8 +373,6 @@ impl Default for MessageProcessor {
|
|||
programs: vec![],
|
||||
loaders: vec![],
|
||||
native_loader: NativeLoader::default(),
|
||||
is_cross_program_supported: true,
|
||||
compute_budget: ComputeBudget::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -392,7 +382,6 @@ impl Clone for MessageProcessor {
|
|||
programs: self.programs.clone(),
|
||||
loaders: self.loaders.clone(),
|
||||
native_loader: NativeLoader::default(),
|
||||
..*self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -426,17 +415,20 @@ impl MessageProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_cross_program_support(&mut self, is_supported: bool) {
|
||||
self.is_cross_program_supported = is_supported;
|
||||
}
|
||||
|
||||
pub fn set_compute_budget(&mut self, compute_budget: ComputeBudget) {
|
||||
self.compute_budget = compute_budget;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn get_cross_program_support(&mut self) -> bool {
|
||||
self.is_cross_program_supported
|
||||
fn get_compute_budget(feature_set: &FeatureSet) -> ComputeBudget {
|
||||
if feature_set.is_active(&compute_budget_config2::id()) {
|
||||
ComputeBudget::default()
|
||||
} else {
|
||||
// Original
|
||||
ComputeBudget {
|
||||
max_units: 100_000,
|
||||
log_units: 0,
|
||||
log_64_units: 0,
|
||||
create_program_address_units: 0,
|
||||
invoke_units: 0,
|
||||
max_invoke_depth: 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the KeyedAccounts that will be passed to the program
|
||||
|
@ -527,10 +519,6 @@ impl MessageProcessor {
|
|||
accounts: &[Rc<RefCell<Account>>],
|
||||
invoke_context: &mut dyn InvokeContext,
|
||||
) -> Result<(), InstructionError> {
|
||||
if !self.is_cross_program_supported {
|
||||
return Err(InstructionError::ReentrancyNotAllowed);
|
||||
}
|
||||
|
||||
let instruction = &message.instructions[0];
|
||||
|
||||
// Verify the calling program hasn't misbehaved
|
||||
|
@ -681,11 +669,11 @@ impl MessageProcessor {
|
|||
executors: Rc<RefCell<Executors>>,
|
||||
instruction_recorder: Option<InstructionRecorder>,
|
||||
instruction_index: usize,
|
||||
feature_set: &FeatureSet,
|
||||
feature_set: Arc<FeatureSet>,
|
||||
) -> Result<(), InstructionError> {
|
||||
// Fixup the special instructions key if present
|
||||
// before the account pre-values are taken care of
|
||||
if feature_set.is_active(&feature_set::instructions_sysvar_enabled::id()) {
|
||||
if feature_set.is_active(&instructions_sysvar_enabled::id()) {
|
||||
for (i, key) in message.account_keys.iter().enumerate() {
|
||||
if solana_sdk::sysvar::instructions::check_id(key) {
|
||||
let mut mut_account_ref = accounts[i].borrow_mut();
|
||||
|
@ -705,10 +693,10 @@ impl MessageProcessor {
|
|||
pre_accounts,
|
||||
self.programs.clone(), // get rid of clone
|
||||
log_collector,
|
||||
self.is_cross_program_supported,
|
||||
self.compute_budget,
|
||||
Self::get_compute_budget(&feature_set),
|
||||
executors,
|
||||
instruction_recorder,
|
||||
feature_set,
|
||||
);
|
||||
let keyed_accounts =
|
||||
Self::create_keyed_accounts(message, instruction, executable_accounts, accounts)?;
|
||||
|
@ -737,7 +725,7 @@ impl MessageProcessor {
|
|||
log_collector: Option<Rc<LogCollector>>,
|
||||
executors: Rc<RefCell<Executors>>,
|
||||
instruction_recorders: Option<&[InstructionRecorder]>,
|
||||
feature_set: &FeatureSet,
|
||||
feature_set: Arc<FeatureSet>,
|
||||
) -> Result<(), TransactionError> {
|
||||
for (instruction_index, instruction) in message.instructions.iter().enumerate() {
|
||||
let instruction_recorder = instruction_recorders
|
||||
|
@ -753,7 +741,7 @@ impl MessageProcessor {
|
|||
executors.clone(),
|
||||
instruction_recorder,
|
||||
instruction_index,
|
||||
feature_set,
|
||||
feature_set.clone(),
|
||||
)
|
||||
.map_err(|err| TransactionError::InstructionError(instruction_index as u8, err))?;
|
||||
}
|
||||
|
@ -798,10 +786,10 @@ mod tests {
|
|||
pre_accounts,
|
||||
vec![],
|
||||
None,
|
||||
true,
|
||||
ComputeBudget::default(),
|
||||
Rc::new(RefCell::new(Executors::default())),
|
||||
None,
|
||||
Arc::new(FeatureSet::default()),
|
||||
);
|
||||
|
||||
// Check call depth increases and has a limit
|
||||
|
@ -1338,7 +1326,7 @@ mod tests {
|
|||
None,
|
||||
executors.clone(),
|
||||
None,
|
||||
&FeatureSet::default(),
|
||||
Arc::new(FeatureSet::default()),
|
||||
);
|
||||
assert_eq!(result, Ok(()));
|
||||
assert_eq!(accounts[0].borrow().lamports, 100);
|
||||
|
@ -1361,7 +1349,7 @@ mod tests {
|
|||
None,
|
||||
executors.clone(),
|
||||
None,
|
||||
&FeatureSet::default(),
|
||||
Arc::new(FeatureSet::default()),
|
||||
);
|
||||
assert_eq!(
|
||||
result,
|
||||
|
@ -1388,7 +1376,7 @@ mod tests {
|
|||
None,
|
||||
executors,
|
||||
None,
|
||||
&FeatureSet::default(),
|
||||
Arc::new(FeatureSet::default()),
|
||||
);
|
||||
assert_eq!(
|
||||
result,
|
||||
|
@ -1498,7 +1486,7 @@ mod tests {
|
|||
None,
|
||||
executors.clone(),
|
||||
None,
|
||||
&FeatureSet::default(),
|
||||
Arc::new(FeatureSet::default()),
|
||||
);
|
||||
assert_eq!(
|
||||
result,
|
||||
|
@ -1525,7 +1513,7 @@ mod tests {
|
|||
None,
|
||||
executors.clone(),
|
||||
None,
|
||||
&FeatureSet::default(),
|
||||
Arc::new(FeatureSet::default()),
|
||||
);
|
||||
assert_eq!(result, Ok(()));
|
||||
|
||||
|
@ -1549,7 +1537,7 @@ mod tests {
|
|||
None,
|
||||
executors,
|
||||
None,
|
||||
&FeatureSet::default(),
|
||||
Arc::new(FeatureSet::default()),
|
||||
);
|
||||
assert_eq!(result, Ok(()));
|
||||
assert_eq!(accounts[0].borrow().lamports, 80);
|
||||
|
@ -1623,10 +1611,10 @@ mod tests {
|
|||
vec![owned_preaccount, not_owned_preaccount],
|
||||
vec![],
|
||||
None,
|
||||
true,
|
||||
ComputeBudget::default(),
|
||||
Rc::new(RefCell::new(Executors::default())),
|
||||
None,
|
||||
Arc::new(FeatureSet::default()),
|
||||
);
|
||||
let metas = vec![
|
||||
AccountMeta::new(owned_key, false),
|
||||
|
|
|
@ -56,10 +56,8 @@ pub trait InvokeContext {
|
|||
fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)];
|
||||
/// Get this invocation's logger
|
||||
fn get_logger(&self) -> Rc<RefCell<dyn Logger>>;
|
||||
/// Are cross program invocations supported
|
||||
fn is_cross_program_supported(&self) -> bool;
|
||||
/// Get this invocation's compute budget
|
||||
fn get_compute_budget(&self) -> ComputeBudget;
|
||||
fn get_compute_budget(&self) -> &ComputeBudget;
|
||||
/// Get this invocation's compute meter
|
||||
fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>>;
|
||||
/// Loaders may need to do work in order to execute a program. Cache
|
||||
|
@ -69,6 +67,8 @@ pub trait InvokeContext {
|
|||
fn get_executor(&mut self, pubkey: &Pubkey) -> Option<Arc<dyn Executor>>;
|
||||
/// Record invoked instruction
|
||||
fn record_instruction(&self, instruction: &Instruction);
|
||||
/// Get the bank's active feature set
|
||||
fn is_feature_active(&self, feature_id: &Pubkey) -> bool;
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
|
Loading…
Reference in New Issue