gemachain_program/
entrypoint_deprecated.rs

1#![allow(clippy::integer_arithmetic)]
2//! @brief Gemachain Rust-based BPF program entry point supported by the original
3//!  and now deprecated BPFLoader.  For more information see
4//!  './bpf_loader_deprecated.rs'
5
6extern crate alloc;
7use crate::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey};
8use alloc::vec::Vec;
9use std::{
10    cell::RefCell,
11    mem::size_of,
12    rc::Rc,
13    // Hide Result from bindgen gets confused about generics in non-generic type declarations
14    result::Result as ResultGeneric,
15    slice::{from_raw_parts, from_raw_parts_mut},
16};
17
18pub type ProgramResult = ResultGeneric<(), ProgramError>;
19
20/// User implemented function to process an instruction
21///
22/// program_id: Program ID of the currently executing program
23/// accounts: Accounts passed as part of the instruction
24/// instruction_data: Instruction data
25pub type ProcessInstruction =
26    fn(program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult;
27
28/// Programs indicate success with a return value of 0
29pub const SUCCESS: u64 = 0;
30
31/// Declare the entry point of the program.
32///
33/// Deserialize the program input arguments and call
34/// the user defined `process_instruction` function.
35/// Users must call this macro otherwise an entry point for
36/// their program will not be created.
37#[macro_export]
38macro_rules! entrypoint_deprecated {
39    ($process_instruction:ident) => {
40        /// # Safety
41        #[no_mangle]
42        pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 {
43            let (program_id, accounts, instruction_data) =
44                unsafe { $crate::entrypoint_deprecated::deserialize(input) };
45            match $process_instruction(&program_id, &accounts, &instruction_data) {
46                Ok(()) => $crate::entrypoint_deprecated::SUCCESS,
47                Err(error) => error.into(),
48            }
49        }
50    };
51}
52
53/// Deserialize the input arguments
54///
55/// # Safety
56#[allow(clippy::type_complexity)]
57pub unsafe fn deserialize<'a>(input: *mut u8) -> (&'a Pubkey, Vec<AccountInfo<'a>>, &'a [u8]) {
58    let mut offset: usize = 0;
59
60    // Number of accounts present
61
62    #[allow(clippy::cast_ptr_alignment)]
63    let num_accounts = *(input.add(offset) as *const u64) as usize;
64    offset += size_of::<u64>();
65
66    // Account Infos
67
68    let mut accounts = Vec::with_capacity(num_accounts);
69    for _ in 0..num_accounts {
70        let dup_info = *(input.add(offset) as *const u8);
71        offset += size_of::<u8>();
72        if dup_info == std::u8::MAX {
73            #[allow(clippy::cast_ptr_alignment)]
74            let is_signer = *(input.add(offset) as *const u8) != 0;
75            offset += size_of::<u8>();
76
77            #[allow(clippy::cast_ptr_alignment)]
78            let is_writable = *(input.add(offset) as *const u8) != 0;
79            offset += size_of::<u8>();
80
81            let key: &Pubkey = &*(input.add(offset) as *const Pubkey);
82            offset += size_of::<Pubkey>();
83
84            #[allow(clippy::cast_ptr_alignment)]
85            let carats = Rc::new(RefCell::new(&mut *(input.add(offset) as *mut u64)));
86            offset += size_of::<u64>();
87
88            #[allow(clippy::cast_ptr_alignment)]
89            let data_len = *(input.add(offset) as *const u64) as usize;
90            offset += size_of::<u64>();
91
92            let data = Rc::new(RefCell::new({
93                from_raw_parts_mut(input.add(offset), data_len)
94            }));
95            offset += data_len;
96
97            let owner: &Pubkey = &*(input.add(offset) as *const Pubkey);
98            offset += size_of::<Pubkey>();
99
100            #[allow(clippy::cast_ptr_alignment)]
101            let executable = *(input.add(offset) as *const u8) != 0;
102            offset += size_of::<u8>();
103
104            #[allow(clippy::cast_ptr_alignment)]
105            let rent_epoch = *(input.add(offset) as *const u64);
106            offset += size_of::<u64>();
107
108            accounts.push(AccountInfo {
109                key,
110                is_signer,
111                is_writable,
112                carats,
113                data,
114                owner,
115                executable,
116                rent_epoch,
117            });
118        } else {
119            // Duplicate account, clone the original
120            accounts.push(accounts[dup_info as usize].clone());
121        }
122    }
123
124    // Instruction data
125
126    #[allow(clippy::cast_ptr_alignment)]
127    let instruction_data_len = *(input.add(offset) as *const u64) as usize;
128    offset += size_of::<u64>();
129
130    let instruction_data = { from_raw_parts(input.add(offset), instruction_data_len) };
131    offset += instruction_data_len;
132
133    // Program Id
134
135    let program_id: &Pubkey = &*(input.add(offset) as *const Pubkey);
136
137    (program_id, accounts, instruction_data)
138}