2019-05-21 13:39:27 -07:00
|
|
|
//! @brief Solana Rust-based BPF program entrypoint and its parameter types
|
2019-06-20 16:07:12 -07:00
|
|
|
extern crate alloc;
|
2019-05-21 13:39:27 -07:00
|
|
|
|
2019-06-20 16:07:12 -07:00
|
|
|
use alloc::vec::Vec;
|
2019-05-21 13:39:27 -07:00
|
|
|
use core::mem::size_of;
|
|
|
|
use core::slice::{from_raw_parts, from_raw_parts_mut};
|
|
|
|
|
|
|
|
/// Public key
|
2019-06-20 16:07:12 -07:00
|
|
|
pub type SolPubkey = [u8; 32];
|
2019-05-21 13:39:27 -07:00
|
|
|
|
|
|
|
/// Keyed Account
|
|
|
|
pub struct SolKeyedAccount<'a> {
|
|
|
|
/// Public key of the account
|
2019-06-20 16:07:12 -07:00
|
|
|
pub key: &'a SolPubkey,
|
2019-05-21 13:39:27 -07:00
|
|
|
/// Public key of the account
|
|
|
|
pub is_signer: bool,
|
|
|
|
/// Number of lamports owned by this account
|
2019-07-08 15:52:25 -08:00
|
|
|
pub lamports: &'a mut u64,
|
2019-05-21 13:39:27 -07:00
|
|
|
/// On-chain data within this account
|
|
|
|
pub data: &'a mut [u8],
|
|
|
|
/// Program that owns this account
|
2019-06-20 16:07:12 -07:00
|
|
|
pub owner: &'a SolPubkey,
|
2019-05-21 13:39:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Information about the state of the cluster immediately before the program
|
|
|
|
/// started executing the current instruction
|
|
|
|
pub struct SolClusterInfo<'a> {
|
2019-06-20 16:07:12 -07:00
|
|
|
/// program_id of the currently executing program
|
|
|
|
pub program_id: &'a SolPubkey,
|
2019-05-21 13:39:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Declare entrypoint of the program.
|
|
|
|
///
|
|
|
|
/// Deserialize the program input parameters and call
|
|
|
|
/// a user defined entrypoint. Users must call
|
|
|
|
/// this function otherwise an entrypoint for
|
|
|
|
/// their program will not be created.
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! entrypoint {
|
|
|
|
($process_instruction:ident) => {
|
|
|
|
#[no_mangle]
|
2019-06-20 07:43:31 -07:00
|
|
|
pub unsafe extern "C" fn entrypoint(input: *mut u8) -> bool {
|
2019-05-21 13:39:27 -07:00
|
|
|
unsafe {
|
2019-06-20 16:07:12 -07:00
|
|
|
if let Ok((mut kas, info, data)) = $crate::entrypoint::deserialize(input) {
|
|
|
|
$process_instruction(&mut kas, &info, &data)
|
2019-05-21 13:39:27 -07:00
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Deserialize the input parameters
|
|
|
|
#[allow(clippy::type_complexity)]
|
|
|
|
pub unsafe fn deserialize<'a>(
|
|
|
|
input: *mut u8,
|
2019-06-20 16:07:12 -07:00
|
|
|
) -> Result<(Vec<SolKeyedAccount<'a>>, SolClusterInfo<'a>, &'a [u8]), ()> {
|
2019-05-21 13:39:27 -07:00
|
|
|
let mut offset: usize = 0;
|
|
|
|
|
|
|
|
// Number of KeyedAccounts present
|
|
|
|
|
|
|
|
#[allow(clippy::cast_ptr_alignment)]
|
|
|
|
let num_ka = *(input.add(offset) as *const u64) as usize;
|
2019-06-20 16:07:12 -07:00
|
|
|
offset += size_of::<u64>();
|
2019-05-21 13:39:27 -07:00
|
|
|
|
|
|
|
// KeyedAccounts
|
|
|
|
|
2019-06-20 16:07:12 -07:00
|
|
|
let mut kas = Vec::new();
|
|
|
|
for _ in 0..num_ka {
|
2019-05-21 13:39:27 -07:00
|
|
|
let is_signer = {
|
|
|
|
#[allow(clippy::cast_ptr_alignment)]
|
|
|
|
let is_signer_val = *(input.add(offset) as *const u64);
|
|
|
|
(is_signer_val != 0)
|
|
|
|
};
|
|
|
|
offset += size_of::<u64>();
|
|
|
|
|
2019-06-20 16:07:12 -07:00
|
|
|
let key: &SolPubkey = &*(input.add(offset) as *const [u8; size_of::<SolPubkey>()]);
|
|
|
|
offset += size_of::<SolPubkey>();
|
2019-05-21 13:39:27 -07:00
|
|
|
|
|
|
|
#[allow(clippy::cast_ptr_alignment)]
|
2019-07-08 15:52:25 -08:00
|
|
|
let lamports = &mut *(input.add(offset) as *mut u64);
|
2019-05-21 13:39:27 -07:00
|
|
|
offset += size_of::<u64>();
|
|
|
|
|
|
|
|
#[allow(clippy::cast_ptr_alignment)]
|
|
|
|
let data_length = *(input.add(offset) as *const u64) as usize;
|
|
|
|
offset += size_of::<u64>();
|
|
|
|
|
|
|
|
let data = { from_raw_parts_mut(input.add(offset), data_length) };
|
|
|
|
offset += data_length;
|
|
|
|
|
2019-06-20 16:07:12 -07:00
|
|
|
let owner: &SolPubkey = &*(input.add(offset) as *const [u8; size_of::<SolPubkey>()]);
|
|
|
|
offset += size_of::<SolPubkey>();
|
2019-05-21 13:39:27 -07:00
|
|
|
|
2019-06-20 16:07:12 -07:00
|
|
|
kas.push(SolKeyedAccount {
|
2019-05-21 13:39:27 -07:00
|
|
|
key,
|
|
|
|
is_signer,
|
|
|
|
lamports,
|
|
|
|
data,
|
|
|
|
owner,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instruction data
|
|
|
|
|
|
|
|
#[allow(clippy::cast_ptr_alignment)]
|
|
|
|
let data_length = *(input.add(offset) as *const u64) as usize;
|
|
|
|
offset += size_of::<u64>();
|
|
|
|
|
|
|
|
let data = { from_raw_parts(input.add(offset), data_length) };
|
|
|
|
offset += data_length;
|
|
|
|
|
2019-06-20 16:07:12 -07:00
|
|
|
// Program Id
|
2019-05-21 13:39:27 -07:00
|
|
|
|
2019-06-20 16:07:12 -07:00
|
|
|
let program_id: &SolPubkey = &*(input.add(offset) as *const [u8; size_of::<SolPubkey>()]);
|
2019-06-10 10:19:58 -07:00
|
|
|
let info = SolClusterInfo { program_id };
|
2019-05-21 13:39:27 -07:00
|
|
|
|
2019-06-20 07:43:31 -07:00
|
|
|
Ok((kas, info, data))
|
2019-05-21 13:39:27 -07:00
|
|
|
}
|