gemachain_program/
program_stubs.rs1#![cfg(not(target_arch = "bpf"))]
4
5use crate::{
6 account_info::AccountInfo, entrypoint::ProgramResult, instruction::Instruction,
7 program_error::UNSUPPORTED_SYSVAR, pubkey::Pubkey,
8};
9use itertools::Itertools;
10use std::sync::{Arc, RwLock};
11
12lazy_static::lazy_static! {
13 static ref SYSCALL_STUBS: Arc<RwLock<Box<dyn SyscallStubs>>> = Arc::new(RwLock::new(Box::new(DefaultSyscallStubs {})));
14}
15
16pub fn set_syscall_stubs(syscall_stubs: Box<dyn SyscallStubs>) -> Box<dyn SyscallStubs> {
19 std::mem::replace(&mut SYSCALL_STUBS.write().unwrap(), syscall_stubs)
20}
21
22#[allow(clippy::integer_arithmetic)]
23pub trait SyscallStubs: Sync + Send {
24 fn gema_log(&self, message: &str) {
25 println!("{}", message);
26 }
27 fn gema_log_compute_units(&self) {
28 gema_log("SyscallStubs: gema_log_compute_units() not available");
29 }
30 fn gema_invoke_signed(
31 &self,
32 _instruction: &Instruction,
33 _account_infos: &[AccountInfo],
34 _signers_seeds: &[&[&[u8]]],
35 ) -> ProgramResult {
36 gema_log("SyscallStubs: gema_invoke_signed() not available");
37 Ok(())
38 }
39 fn gema_get_clock_sysvar(&self, _var_addr: *mut u8) -> u64 {
40 UNSUPPORTED_SYSVAR
41 }
42 fn gema_get_epoch_schedule_sysvar(&self, _var_addr: *mut u8) -> u64 {
43 UNSUPPORTED_SYSVAR
44 }
45 fn gema_get_fees_sysvar(&self, _var_addr: *mut u8) -> u64 {
46 UNSUPPORTED_SYSVAR
47 }
48 fn gema_get_rent_sysvar(&self, _var_addr: *mut u8) -> u64 {
49 UNSUPPORTED_SYSVAR
50 }
51 unsafe fn gema_memcpy(&self, dst: *mut u8, src: *const u8, n: usize) {
53 if dst as usize + n > src as usize && src as usize > dst as usize {
55 panic!("memcpy does not support overlapping regions");
56 }
57 std::ptr::copy_nonoverlapping(src, dst, n as usize);
58 }
59 unsafe fn gema_memmove(&self, dst: *mut u8, src: *const u8, n: usize) {
61 std::ptr::copy(src, dst, n as usize);
62 }
63 unsafe fn gema_memcmp(&self, s1: *const u8, s2: *const u8, n: usize, result: *mut i32) {
65 let mut i = 0;
66 while i < n {
67 let a = *s1.add(i);
68 let b = *s2.add(i);
69 if a != b {
70 *result = a as i32 - b as i32;
71 return;
72 }
73 i += 1;
74 }
75 *result = 0
76 }
77 unsafe fn gema_memset(&self, s: *mut u8, c: u8, n: usize) {
79 let s = std::slice::from_raw_parts_mut(s, n);
80 for val in s.iter_mut().take(n) {
81 *val = c;
82 }
83 }
84 fn gema_get_return_data(&self) -> Option<(Pubkey, Vec<u8>)> {
85 None
86 }
87 fn gema_set_return_data(&mut self, _data: &[u8]) {}
88 fn gema_log_data(&self, fields: &[&[u8]]) {
89 println!("data: {}", fields.iter().map(base64::encode).join(" "));
90 }
91}
92
93struct DefaultSyscallStubs {}
94impl SyscallStubs for DefaultSyscallStubs {}
95
96pub(crate) fn gema_log(message: &str) {
97 SYSCALL_STUBS.read().unwrap().gema_log(message);
98}
99
100pub(crate) fn gema_log_64(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) {
101 gema_log(&format!(
102 "{:#x}, {:#x}, {:#x}, {:#x}, {:#x}",
103 arg1, arg2, arg3, arg4, arg5
104 ));
105}
106
107pub(crate) fn gema_log_compute_units() {
108 SYSCALL_STUBS.read().unwrap().gema_log_compute_units();
109}
110
111pub(crate) fn gema_invoke_signed(
112 instruction: &Instruction,
113 account_infos: &[AccountInfo],
114 signers_seeds: &[&[&[u8]]],
115) -> ProgramResult {
116 SYSCALL_STUBS
117 .read()
118 .unwrap()
119 .gema_invoke_signed(instruction, account_infos, signers_seeds)
120}
121
122pub(crate) fn gema_get_clock_sysvar(var_addr: *mut u8) -> u64 {
123 SYSCALL_STUBS.read().unwrap().gema_get_clock_sysvar(var_addr)
124}
125
126pub(crate) fn gema_get_epoch_schedule_sysvar(var_addr: *mut u8) -> u64 {
127 SYSCALL_STUBS
128 .read()
129 .unwrap()
130 .gema_get_epoch_schedule_sysvar(var_addr)
131}
132
133pub(crate) fn gema_get_fees_sysvar(_var_addr: *mut u8) -> u64 {
134 UNSUPPORTED_SYSVAR
135}
136
137pub(crate) fn gema_get_rent_sysvar(var_addr: *mut u8) -> u64 {
138 SYSCALL_STUBS.read().unwrap().gema_get_rent_sysvar(var_addr)
139}
140
141pub(crate) fn gema_memcpy(dst: *mut u8, src: *const u8, n: usize) {
142 unsafe {
143 SYSCALL_STUBS.read().unwrap().gema_memcpy(dst, src, n);
144 }
145}
146
147pub(crate) fn gema_memmove(dst: *mut u8, src: *const u8, n: usize) {
148 unsafe {
149 SYSCALL_STUBS.read().unwrap().gema_memmove(dst, src, n);
150 }
151}
152
153pub(crate) fn gema_memcmp(s1: *const u8, s2: *const u8, n: usize, result: *mut i32) {
154 unsafe {
155 SYSCALL_STUBS.read().unwrap().gema_memcmp(s1, s2, n, result);
156 }
157}
158
159pub(crate) fn gema_memset(s: *mut u8, c: u8, n: usize) {
160 unsafe {
161 SYSCALL_STUBS.read().unwrap().gema_memset(s, c, n);
162 }
163}
164
165pub(crate) fn gema_get_return_data() -> Option<(Pubkey, Vec<u8>)> {
166 SYSCALL_STUBS.read().unwrap().gema_get_return_data()
167}
168
169pub(crate) fn gema_set_return_data(data: &[u8]) {
170 SYSCALL_STUBS.write().unwrap().gema_set_return_data(data)
171}
172
173pub(crate) fn gema_log_data(data: &[&[u8]]) {
174 SYSCALL_STUBS.read().unwrap().gema_log_data(data)
175}