solana_instruction/
syscalls.rs

1#[cfg(feature = "syscalls")]
2use crate::Instruction;
3#[cfg(target_os = "solana")]
4pub use {
5    crate::{AccountMeta, ProcessedSiblingInstruction},
6    solana_define_syscall::definitions::sol_get_stack_height,
7    solana_pubkey::Pubkey,
8};
9
10#[cfg(target_os = "solana")]
11#[deprecated(
12    since = "3.1.0",
13    note = "Use `solana_define_syscall::definitions::get_processed_sibling_instruction` instead"
14)]
15pub unsafe fn sol_get_processed_sibling_instruction(
16    index: u64,
17    meta: *mut ProcessedSiblingInstruction,
18    program_id: *mut Pubkey,
19    data: *mut u8,
20    accounts: *mut AccountMeta,
21) -> u64 {
22    unsafe {
23        solana_define_syscall::definitions::sol_get_processed_sibling_instruction(
24            index,
25            meta as *mut u8,
26            program_id as *mut u8,
27            data,
28            accounts as *mut u8,
29        )
30    }
31}
32
33/// Returns a sibling instruction from the processed sibling instruction list.
34///
35/// The processed sibling instruction list is a reverse-ordered list of
36/// successfully processed sibling instructions. For example, given the call flow:
37///
38/// A
39/// B -> C -> D
40/// B -> E
41/// B -> F
42///
43/// Then B's processed sibling instruction list is: `[A]`
44/// Then F's processed sibling instruction list is: `[E, C]`
45#[cfg(feature = "syscalls")]
46pub fn get_processed_sibling_instruction(index: usize) -> Option<Instruction> {
47    #[cfg(target_os = "solana")]
48    {
49        let mut meta = ProcessedSiblingInstruction::default();
50        let mut program_id = solana_pubkey::Pubkey::default();
51        let mut account_meta = AccountMeta::default();
52
53        if 1 == unsafe {
54            solana_define_syscall::definitions::sol_get_processed_sibling_instruction(
55                index as u64,
56                &mut meta as *mut _ as *mut u8,
57                &mut program_id as *mut _ as *mut u8,
58                &mut u8::default(),
59                &mut account_meta as *mut _ as *mut u8,
60            )
61        } {
62            let mut data = std::vec::Vec::new();
63            let mut accounts = std::vec::Vec::new();
64            data.resize_with(meta.data_len as usize, u8::default);
65            accounts.resize_with(meta.accounts_len as usize, AccountMeta::default);
66
67            let _ = unsafe {
68                solana_define_syscall::definitions::sol_get_processed_sibling_instruction(
69                    index as u64,
70                    &mut meta as *mut _ as *mut u8,
71                    &mut program_id as *mut _ as *mut u8,
72                    data.as_mut_ptr(),
73                    accounts.as_mut_ptr() as *mut u8,
74                )
75            };
76
77            Some(Instruction::new_with_bytes(program_id, &data, accounts))
78        } else {
79            None
80        }
81    }
82
83    #[cfg(not(target_os = "solana"))]
84    {
85        core::hint::black_box(index);
86        // Same value used in `solana_sysvar::program_stubs`.
87        None
88    }
89}
90
91/// Get the current stack height.
92///
93/// Transaction-level instructions are height
94/// [`crate::TRANSACTION_LEVEL_STACK_HEIGHT`]`, fist invoked inner instruction
95/// is height `TRANSACTION_LEVEL_STACK_HEIGHT + 1`, and so forth.
96#[cfg(feature = "syscalls")]
97pub fn get_stack_height() -> usize {
98    #[cfg(target_os = "solana")]
99    unsafe {
100        sol_get_stack_height() as usize
101    }
102
103    #[cfg(not(target_os = "solana"))]
104    // Same value used in `solana_sysvar::program_stubs`.
105    0
106}