diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index 9105b0f906..515906d006 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize}; use solana_sdk::{ account::{create_keyed_readonly_accounts, Account, KeyedAccount}, clock::Epoch, + entrypoint_native, instruction::{CompiledInstruction, InstructionError}, - instruction_processor_utils, message::Message, pubkey::Pubkey, system_program, @@ -125,7 +125,7 @@ pub fn verify_account_changes( pub type ProcessInstruction = fn(&Pubkey, &[KeyedAccount], &[u8]) -> Result<(), InstructionError>; -pub type SymbolCache = RwLock, Symbol>>; +pub type SymbolCache = RwLock, Symbol>>; #[derive(Serialize, Deserialize)] pub struct MessageProcessor { diff --git a/runtime/src/native_loader.rs b/runtime/src/native_loader.rs index e0f7450ac5..1065c91f66 100644 --- a/runtime/src/native_loader.rs +++ b/runtime/src/native_loader.rs @@ -6,8 +6,7 @@ use libloading::os::unix::*; use libloading::os::windows::*; use log::*; use solana_sdk::{ - account::KeyedAccount, instruction::InstructionError, instruction_processor_utils, - pubkey::Pubkey, + account::KeyedAccount, entrypoint_native, instruction::InstructionError, pubkey::Pubkey, }; use std::{env, path::PathBuf, str}; @@ -87,7 +86,7 @@ pub fn invoke_entrypoint( let path = create_path(&name); match library_open(&path) { Ok(library) => unsafe { - let entrypoint: Symbol = + let entrypoint: Symbol = match library.get(name.as_bytes()) { Ok(s) => s, Err(e) => { diff --git a/sdk/src/entrypoint.rs b/sdk/src/entrypoint.rs index 6999a0aa77..1035ea4f94 100644 --- a/sdk/src/entrypoint.rs +++ b/sdk/src/entrypoint.rs @@ -1,4 +1,4 @@ -//! @brief Solana Rust-based BPF program entry point and its parameter types +//! @brief Solana Rust-based BPF program entry point extern crate alloc; use crate::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey}; diff --git a/sdk/src/entrypoint_native.rs b/sdk/src/entrypoint_native.rs new file mode 100644 index 0000000000..d559886a3c --- /dev/null +++ b/sdk/src/entrypoint_native.rs @@ -0,0 +1,101 @@ +//! @brief Solana Native program entry point + +use crate::{account::KeyedAccount, instruction::InstructionError, pubkey::Pubkey}; + +// Prototype of a native program entry point +pub type Entrypoint = unsafe extern "C" fn( + program_id: &Pubkey, + keyed_accounts: &[KeyedAccount], + instruction_data: &[u8], +) -> Result<(), InstructionError>; + +/// Convenience macro to declare a native program +/// +/// bs58_string: bs58 string representation the program's id +/// name: Name of the program, must match the library name in Cargo.toml +/// entrypoint: Program's entrypoint, must be of `type Entrypoint` +/// +/// # Examples +/// +/// ``` +/// use std::str::FromStr; +/// # // wrapper is used so that the macro invocation occurs in the item position +/// # // rather than in the statement position which isn't allowed. +/// # mod item_wrapper { +/// use solana_sdk::account::KeyedAccount; +/// use solana_sdk::instruction::InstructionError; +/// use solana_sdk::pubkey::Pubkey; +/// use solana_sdk::declare_program; +/// +/// fn my_process_instruction( +/// program_id: &Pubkey, +/// keyed_accounts: &[KeyedAccount], +/// instruction_data: &[u8], +/// ) -> Result<(), InstructionError> { +/// // Process an instruction +/// Ok(()) +/// } +/// +/// declare_program!( +/// "My11111111111111111111111111111111111111111", +/// solana_my_program, +/// my_process_instruction +/// ); +/// +/// # } +/// # use solana_sdk::pubkey::Pubkey; +/// # use item_wrapper::id; +/// let my_id = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); +/// assert_eq!(id(), my_id); +/// ``` +/// ``` +/// use std::str::FromStr; +/// # // wrapper is used so that the macro invocation occurs in the item position +/// # // rather than in the statement position which isn't allowed. +/// # mod item_wrapper { +/// use solana_sdk::account::KeyedAccount; +/// use solana_sdk::instruction::InstructionError; +/// use solana_sdk::pubkey::Pubkey; +/// use solana_sdk::declare_program; +/// +/// fn my_process_instruction( +/// program_id: &Pubkey, +/// keyed_accounts: &[KeyedAccount], +/// instruction_data: &[u8], +/// ) -> Result<(), InstructionError> { +/// // Process an instruction +/// Ok(()) +/// } +/// +/// declare_program!( +/// solana_sdk::system_program::ID, +/// solana_my_program, +/// my_process_instruction +/// ); +/// # } +/// +/// # use item_wrapper::id; +/// assert_eq!(id(), solana_sdk::system_program::ID); +/// ``` +#[macro_export] +macro_rules! declare_program( + ($bs58_string:expr, $name:ident, $entrypoint:expr) => ( + $crate::declare_id!($bs58_string); + + #[macro_export] + macro_rules! $name { + () => { + (stringify!($name).to_string(), $crate::id()) + }; + } + + #[no_mangle] + pub extern "C" fn $name( + program_id: &$crate::pubkey::Pubkey, + keyed_accounts: &[$crate::account::KeyedAccount], + instruction_data: &[u8], + ) -> Result<(), $crate::instruction::InstructionError> { + $entrypoint(program_id, keyed_accounts, instruction_data) + } + ) +); diff --git a/sdk/src/instruction_processor_utils.rs b/sdk/src/instruction_processor_utils.rs index a76af5ea1b..e97437825f 100644 --- a/sdk/src/instruction_processor_utils.rs +++ b/sdk/src/instruction_processor_utils.rs @@ -1,104 +1,6 @@ -use crate::{account::KeyedAccount, instruction::InstructionError, pubkey::Pubkey}; +use crate::{account::KeyedAccount, instruction::InstructionError}; use num_traits::FromPrimitive; -// Prototype of a native program entry point -pub type Entrypoint = unsafe extern "C" fn( - program_id: &Pubkey, - keyed_accounts: &[KeyedAccount], - instruction_data: &[u8], -) -> Result<(), InstructionError>; - -/// Convenience macro to declare a native program -/// -/// bs58_string: bs58 string representation the program's id -/// name: Name of the program, must match the library name in Cargo.toml -/// entrypoint: Program's entrypoint, must be of `type Entrypoint` -/// -/// # Examples -/// -/// ``` -/// use std::str::FromStr; -/// # // wrapper is used so that the macro invocation occurs in the item position -/// # // rather than in the statement position which isn't allowed. -/// # mod item_wrapper { -/// use solana_sdk::account::KeyedAccount; -/// use solana_sdk::instruction::InstructionError; -/// use solana_sdk::pubkey::Pubkey; -/// use solana_sdk::declare_program; -/// -/// fn my_process_instruction( -/// program_id: &Pubkey, -/// keyed_accounts: &[KeyedAccount], -/// instruction_data: &[u8], -/// ) -> Result<(), InstructionError> { -/// // Process an instruction -/// Ok(()) -/// } -/// -/// declare_program!( -/// "My11111111111111111111111111111111111111111", -/// solana_my_program, -/// my_process_instruction -/// ); -/// -/// # } -/// # use solana_sdk::pubkey::Pubkey; -/// # use item_wrapper::id; -/// let my_id = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); -/// assert_eq!(id(), my_id); -/// ``` -/// ``` -/// use std::str::FromStr; -/// # // wrapper is used so that the macro invocation occurs in the item position -/// # // rather than in the statement position which isn't allowed. -/// # mod item_wrapper { -/// use solana_sdk::account::KeyedAccount; -/// use solana_sdk::instruction::InstructionError; -/// use solana_sdk::pubkey::Pubkey; -/// use solana_sdk::declare_program; -/// -/// fn my_process_instruction( -/// program_id: &Pubkey, -/// keyed_accounts: &[KeyedAccount], -/// instruction_data: &[u8], -/// ) -> Result<(), InstructionError> { -/// // Process an instruction -/// Ok(()) -/// } -/// -/// declare_program!( -/// solana_sdk::system_program::ID, -/// solana_my_program, -/// my_process_instruction -/// ); -/// # } -/// -/// # use item_wrapper::id; -/// assert_eq!(id(), solana_sdk::system_program::ID); -/// ``` -#[macro_export] -macro_rules! declare_program( - ($bs58_string:expr, $name:ident, $entrypoint:expr) => ( - $crate::declare_id!($bs58_string); - - #[macro_export] - macro_rules! $name { - () => { - (stringify!($name).to_string(), $crate::id()) - }; - } - - #[no_mangle] - pub extern "C" fn $name( - program_id: &$crate::pubkey::Pubkey, - keyed_accounts: &[$crate::account::KeyedAccount], - instruction_data: &[u8], - ) -> Result<(), $crate::instruction::InstructionError> { - $entrypoint(program_id, keyed_accounts, instruction_data) - } - ) -); - /// Return the next KeyedAccount or a NotEnoughAccountKeys instruction error pub fn next_keyed_account(iter: &mut I) -> Result { iter.next().ok_or(InstructionError::NotEnoughAccountKeys) diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 88804f4764..47b33cc7ac 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -6,6 +6,7 @@ pub mod account_utils; pub mod bpf_loader; pub mod clock; pub mod commitment_config; +pub mod entrypoint_native; pub mod epoch_schedule; pub mod fee_calculator; pub mod hash;