Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions genesis-programs/.gitignore

This file was deleted.

6 changes: 3 additions & 3 deletions programs/bpf/benches/bpf_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ use solana_runtime::{
bank_client::BankClient,
genesis_utils::{create_genesis_config, GenesisConfigInfo},
loader_utils::load_program,
process_instruction::{
ComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, ProcessInstruction,
},
};
use solana_sdk::{
account::Account,
bpf_loader,
client::SyncClient,
entrypoint::SUCCESS,
entrypoint_native::{
ComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, ProcessInstruction,
},
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
message::Message,
pubkey::Pubkey,
Expand Down
13 changes: 7 additions & 6 deletions programs/bpf/tests/programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@ use solana_runtime::{
bank_client::BankClient,
genesis_utils::{create_genesis_config, GenesisConfigInfo},
loader_utils::load_program,
process_instruction::{
ComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, ProcessInstruction,
},
};
use solana_sdk::{
account::{Account, KeyedAccount},
bpf_loader, bpf_loader_deprecated,
client::SyncClient,
clock::{DEFAULT_SLOTS_PER_EPOCH, MAX_PROCESSING_AGE},
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
entrypoint_native::{
ComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, ProcessInstruction,
},

instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
message::Message,
pubkey::Pubkey,
Expand Down Expand Up @@ -629,12 +630,12 @@ fn assert_instruction_count() {
("solana_bpf_rust_128bit", 543),
("solana_bpf_rust_alloc", 19082),
("solana_bpf_rust_dep_crate", 2),
("solana_bpf_rust_external_spend", 473),
("solana_bpf_rust_external_spend", 477),
("solana_bpf_rust_iter", 723),
("solana_bpf_rust_many_args", 231),
("solana_bpf_rust_noop", 447),
("solana_bpf_rust_noop", 451),
("solana_bpf_rust_param_passing", 54),
("solana_bpf_rust_sanity", 2211),
("solana_bpf_rust_sanity", 2215),
]);
}

Expand Down
15 changes: 7 additions & 8 deletions programs/bpf_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ use solana_rbpf::{
memory_region::MemoryRegion,
vm::{EbpfVm, Executable, InstructionMeter},
};
use solana_runtime::process_instruction::{ComputeMeter, Executor, InvokeContext};
use solana_sdk::{
account::{is_executable, next_keyed_account, KeyedAccount},
bpf_loader, bpf_loader_deprecated,
decode_error::DecodeError,
entrypoint::SUCCESS,
entrypoint_native::{ComputeMeter, Executor, InvokeContext},
instruction::InstructionError,
loader_instruction::LoaderInstruction,
program_utils::limited_deserialize,
Expand Down Expand Up @@ -270,14 +270,13 @@ impl Executor for BPFExecutor {
mod tests {
use super::*;
use rand::Rng;
use solana_runtime::message_processor::{Executors, ThisInvokeContext};
use solana_runtime::{
message_processor::{Executors, ThisInvokeContext},
process_instruction::{ComputeBudget, Logger, ProcessInstruction},
};
use solana_sdk::{
account::Account,
entrypoint_native::{ComputeBudget, Logger, ProcessInstruction},
instruction::CompiledInstruction,
instruction::Instruction,
message::Message,
rent::Rent,
account::Account, instruction::CompiledInstruction, instruction::Instruction,
message::Message, rent::Rent,
};
use std::{cell::RefCell, fs::File, io::Read, ops::Range, rc::Rc};

Expand Down
6 changes: 4 additions & 2 deletions programs/bpf_loader/src/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ use solana_rbpf::{
memory_region::{translate_addr, MemoryRegion},
vm::{EbpfVm, SyscallObject},
};
use solana_runtime::message_processor::MessageProcessor;
use solana_runtime::{
message_processor::MessageProcessor,
process_instruction::{ComputeMeter, InvokeContext, Logger},
};
use solana_sdk::{
account::Account,
account::KeyedAccount,
account_info::AccountInfo,
bpf_loader, bpf_loader_deprecated,
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
entrypoint_native::{ComputeMeter, InvokeContext, Logger},
instruction::{AccountMeta, Instruction, InstructionError},
message::Message,
program_error::ProgramError,
Expand Down
22 changes: 16 additions & 6 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ use crate::{
log_collector::LogCollector,
message_processor::{Executors, MessageProcessor},
nonce_utils,
process_instruction::{
ComputeBudget, Executor, ProcessInstruction, ProcessInstructionWithContext,
},
rent_collector::RentCollector,
stakes::Stakes,
status_cache::{SlotDelta, StatusCache},
Expand All @@ -38,9 +41,6 @@ use solana_sdk::{
Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_TICKS_PER_SECOND,
MAX_PROCESSING_AGE, MAX_RECENT_BLOCKHASHES, SECONDS_PER_DAY,
},
entrypoint_native::{
ComputeBudget, Executor, ProcessInstruction, ProcessInstructionWithContext,
},
epoch_info::EpochInfo,
epoch_schedule::EpochSchedule,
fee_calculator::{FeeCalculator, FeeConfig, FeeRateGovernor},
Expand Down Expand Up @@ -211,7 +211,6 @@ pub struct Builtins {
const MAX_CACHED_EXECUTORS: usize = 100; // 10 MB assuming programs are around 100k

/// LFU Cache of executors
#[derive(AbiExample)]
struct CachedExecutors {
max: usize,
executors: HashMap<Pubkey, (AtomicU64, Arc<dyn Executor>)>,
Expand All @@ -224,6 +223,17 @@ impl Default for CachedExecutors {
}
}
}

#[cfg(RUSTC_WITH_SPECIALIZATION)]
impl AbiExample for CachedExecutors {
fn example() -> Self {
// Delegate AbiExample impl to Default before going deep and stuck with
// not easily impl-able Arc<dyn Executor> due to rust's coherence issue
// This is safe because CachedExecutors isn't serializable by definition.
Self::default()
}
}

impl Clone for CachedExecutors {
fn clone(&self) -> Self {
let mut executors = HashMap::new();
Expand Down Expand Up @@ -3805,13 +3815,13 @@ mod tests {
genesis_utils::{
create_genesis_config_with_leader, GenesisConfigInfo, BOOTSTRAP_VALIDATOR_LAMPORTS,
},
process_instruction::InvokeContext,
status_cache::MAX_CACHE_ENTRIES,
};
use solana_sdk::{
account::KeyedAccount,
account_utils::StateMut,
clock::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT},
entrypoint_native::InvokeContext,
epoch_schedule::MINIMUM_SLOTS_PER_EPOCH,
genesis_config::create_genesis_config,
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
Expand Down Expand Up @@ -8740,7 +8750,7 @@ mod tests {
_pubkey: &Pubkey,
_ka: &[KeyedAccount],
_data: &[u8],
_context: &mut dyn solana_sdk::entrypoint_native::InvokeContext,
_context: &mut dyn InvokeContext,
) -> std::result::Result<(), InstructionError> {
Ok(())
}
Expand Down
1 change: 1 addition & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod log_collector;
pub mod message_processor;
mod native_loader;
pub mod nonce_utils;
pub mod process_instruction;
pub mod rent_collector;
pub mod serde_snapshot;
pub mod snapshot_package;
Expand Down
10 changes: 5 additions & 5 deletions runtime/src/message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ use crate::{
instruction_recorder::InstructionRecorder,
log_collector::LogCollector,
native_loader::NativeLoader,
process_instruction::{
ComputeBudget, ComputeMeter, ErasedProcessInstruction, ErasedProcessInstructionWithContext,
Executor, InvokeContext, Logger, ProcessInstruction, ProcessInstructionWithContext,
},
rent_collector::RentCollector,
};
use log::*;
use serde::{Deserialize, Serialize};
use solana_sdk::{
account::{create_keyed_readonly_accounts, Account, KeyedAccount},
clock::Epoch,
entrypoint_native::{
ComputeBudget, ComputeMeter, ErasedProcessInstruction, ErasedProcessInstructionWithContext,
Executor, InvokeContext, Logger, ProcessInstruction, ProcessInstructionWithContext,
},
instruction::{CompiledInstruction, Instruction, InstructionError},
message::Message,
native_loader,
Expand Down Expand Up @@ -1694,7 +1694,7 @@ mod tests {
_pubkey: &Pubkey,
_ka: &[KeyedAccount],
_data: &[u8],
_context: &mut dyn solana_sdk::entrypoint_native::InvokeContext,
_context: &mut dyn InvokeContext,
) -> std::result::Result<(), InstructionError> {
Ok(())
}
Expand Down
3 changes: 2 additions & 1 deletion runtime/src/native_loader.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Native loader
use crate::process_instruction::{InvokeContext, LoaderEntrypoint};
#[cfg(unix)]
use libloading::os::unix::*;
#[cfg(windows)]
Expand All @@ -8,7 +9,7 @@ use num_derive::{FromPrimitive, ToPrimitive};
use solana_sdk::{
account::{next_keyed_account, KeyedAccount},
decode_error::DecodeError,
entrypoint_native::{InvokeContext, LoaderEntrypoint, ProgramEntrypoint},
entrypoint_native::ProgramEntrypoint,
instruction::InstructionError,
pubkey::Pubkey,
};
Expand Down
130 changes: 130 additions & 0 deletions runtime/src/process_instruction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
use solana_sdk::{
account::{Account, KeyedAccount},
instruction::{CompiledInstruction, Instruction, InstructionError},
message::Message,
pubkey::Pubkey,
};
use std::{cell::RefCell, rc::Rc, sync::Arc};

// Prototype of a native loader entry point
///
/// program_id: Program ID of the currently executing program
/// keyed_accounts: Accounts passed as part of the instruction
/// instruction_data: Instruction data
/// invoke_context: Invocation context
pub type LoaderEntrypoint = unsafe extern "C" fn(
program_id: &Pubkey,
keyed_accounts: &[KeyedAccount],
instruction_data: &[u8],
invoke_context: &dyn InvokeContext,
) -> Result<(), InstructionError>;

pub type ProcessInstruction = fn(&Pubkey, &[KeyedAccount], &[u8]) -> Result<(), InstructionError>;
pub type ProcessInstructionWithContext =
fn(&Pubkey, &[KeyedAccount], &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>;

// These are just type aliases for work around of Debug-ing above function pointers
pub type ErasedProcessInstructionWithContext = fn(
&'static Pubkey,
&'static [KeyedAccount<'static>],
&'static [u8],
&'static mut dyn InvokeContext,
) -> Result<(), InstructionError>;

pub type ErasedProcessInstruction = fn(
&'static Pubkey,
&'static [KeyedAccount<'static>],
&'static [u8],
) -> Result<(), InstructionError>;

/// Invocation context passed to loaders
pub trait InvokeContext {
/// Push a program ID on to the invocation stack
fn push(&mut self, key: &Pubkey) -> Result<(), InstructionError>;
/// Pop a program ID off of the invocation stack
fn pop(&mut self);
/// Verify and update PreAccount state based on program execution
fn verify_and_update(
&mut self,
message: &Message,
instruction: &CompiledInstruction,
accounts: &[Rc<RefCell<Account>>],
) -> Result<(), InstructionError>;
/// Get the program ID of the currently executing program
fn get_caller(&self) -> Result<&Pubkey, InstructionError>;
/// Get a list of built-in programs
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;
/// 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
/// the work that can be re-used across executions
fn add_executor(&mut self, pubkey: &Pubkey, executor: Arc<dyn Executor>);
/// Get the completed loader work that can be re-used across executions
fn get_executor(&mut self, pubkey: &Pubkey) -> Option<Arc<dyn Executor>>;
/// Record invoked instruction
fn record_instruction(&self, instruction: &Instruction);
}

#[derive(Clone, Copy, Debug)]
pub struct ComputeBudget {
/// Number of compute units that an instruction is allowed. Compute units
/// are consumed by program execution, resources they use, etc...
pub max_units: u64,
/// Number of compute units consumed by a log call
pub log_units: u64,
/// Number of compute units consumed by a log_u64 call
pub log_64_units: u64,
/// Number of compute units consumed by a create_program_address call
pub create_program_address_units: u64,
/// Number of compute units consumed by an invoke call (not including the cost incured by
/// the called program)
pub invoke_units: u64,
/// Maximum cross-program invocation depth allowed including the orignal caller
pub max_invoke_depth: usize,
}
impl Default for ComputeBudget {
fn default() -> Self {
// Tuned for ~1ms
ComputeBudget {
max_units: 200_000,
log_units: 100,
log_64_units: 100,
create_program_address_units: 1500,
invoke_units: 1000,
max_invoke_depth: 2,
}
}
}

/// Compute meter
pub trait ComputeMeter {
/// Consume compute units
fn consume(&mut self, amount: u64) -> Result<(), InstructionError>;
/// Get the number of remaining compute units
fn get_remaining(&self) -> u64;
}

/// Log messages
pub trait Logger {
fn log_enabled(&self) -> bool;
/// Log a message
fn log(&mut self, message: &str);
}

/// Program executor
pub trait Executor: Send + Sync {
/// Execute the program
fn execute(
&self,
program_id: &Pubkey,
keyed_accounts: &[KeyedAccount],
instruction_data: &[u8],
invoke_context: &mut dyn InvokeContext,
) -> Result<(), InstructionError>;
}
Loading