diff --git a/Cargo.lock b/Cargo.lock
index ace73e6..80f8a22 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -35,6 +35,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "pinocchio"
version = "0.7.1"
+dependencies = [
+ "solana-define-syscall",
+]
[[package]]
name = "pinocchio-associated-token-account"
@@ -131,6 +134,12 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+[[package]]
+name = "solana-define-syscall"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acfe725269aac42d044cca5a99cfe8bd3b3f10e8d429b51f0c274e434fb34556"
+
[[package]]
name = "syn"
version = "1.0.109"
diff --git a/Cargo.toml b/Cargo.toml
index f2929e5..b94fdd5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,3 +19,4 @@ repository = "https://github.com/anza-xyz/pinocchio"
five8_const = "0.1.3"
pinocchio = { path = "sdk/pinocchio", version = ">= 0.6, <= 0.7" }
pinocchio-pubkey = { path = "sdk/pubkey", version = "0.2.1" }
+solana-define-syscall = "2.2.0"
diff --git a/README.md b/README.md
index c604f4a..30317db 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
- Create Solana programs with no dependencies attached.
+ Create Solana programs with minimal dependencies attached.
@@ -13,19 +13,9 @@
-
-I've got no dependencies
-To hold me down
-To make me fret
-Or make me frown
-I had dependencies
-But now I'm free
-There are no dependencies on me
-
-
## Overview
-Pinocchio is a zero-dependency library to create Solana programs in Rust. It takes advantage of the way SBF loaders serialize the program input parameters into a byte array that is then passed to the program's entrypoint to define zero-copy types to read the input. Since the communication between a program and SBF loader — either at the first time the program is called or when one program invokes the instructions of another program — is done via a byte array, a program can define its own types. This completely eliminates the dependency on the `solana-program` crate, which in turn mitigates dependency issues by having a crate specifically designed to create on-chain programs.
+Pinocchio is a library to create Solana programs in Rust. It takes advantage of the way SBF loaders serialize the program input parameters into a byte array that is then passed to the program's entrypoint to define zero-copy types to read the input. Since the communication between a program and SBF loader — either at the first time the program is called or when one program invokes the instructions of another program — is done via a byte array, a program can define its own types. This completely eliminates the dependency on the `solana-program` crate, which in turn mitigates dependency issues by having a crate specifically designed to create on-chain programs.
As a result, Pinocchio can be used as a replacement for [`solana-program`](https://crates.io/crates/solana-program) to write on-chain programs, which are optimized in terms of both compute units consumption and binary size.
@@ -39,7 +29,7 @@ The library defines:
## Features
-* Zero dependencies and `no_std` crate
+* Minimal dependencies and `no_std` crate
* Efficient `entrypoint!` macro – no copies or allocations
* Improved CU consumption of cross-program invocations
diff --git a/sdk/pinocchio/Cargo.toml b/sdk/pinocchio/Cargo.toml
index 30afbad..cad7279 100644
--- a/sdk/pinocchio/Cargo.toml
+++ b/sdk/pinocchio/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "pinocchio"
-description = "Create Solana programs with no dependencies attached"
+description = "Create Solana programs with minimal dependencies attached"
version = "0.7.1"
edition = { workspace = true }
license = { workspace = true }
@@ -10,6 +10,9 @@ repository = { workspace = true }
[lib]
crate-type = ["rlib"]
+[dependencies]
+solana-define-syscall = { workspace = true }
+
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = [
'cfg(target_os, values("solana"))',
diff --git a/sdk/pinocchio/src/syscalls.rs b/sdk/pinocchio/src/syscalls.rs
index ecc74bf..78864d0 100644
--- a/sdk/pinocchio/src/syscalls.rs
+++ b/sdk/pinocchio/src/syscalls.rs
@@ -1,126 +1,13 @@
//! Syscall functions.
+#[cfg(target_feature = "static-syscalls")]
+pub use solana_define_syscall::sys_hash;
+pub use solana_define_syscall::{define_syscall, definitions::*};
+
use crate::{
instruction::{AccountMeta, ProcessedSiblingInstruction},
pubkey::Pubkey,
};
-#[cfg(target_feature = "static-syscalls")]
-macro_rules! define_syscall {
- (fn $name:ident($($arg:ident: $typ:ty),*) -> $ret:ty) => {
- #[inline]
- pub unsafe fn $name($($arg: $typ),*) -> $ret {
- // this enum is used to force the hash to be computed in a const context
- #[repr(usize)]
- enum Syscall {
- Code = sys_hash(stringify!($name)),
- }
-
- let syscall: extern "C" fn($($arg: $typ),*) -> $ret = core::mem::transmute(Syscall::Code);
- syscall($($arg),*)
- }
-
- };
- (fn $name:ident($($arg:ident: $typ:ty),*)) => {
- define_syscall!(fn $name($($arg: $typ),*) -> ());
- }
-}
-
-#[cfg(not(target_feature = "static-syscalls"))]
-macro_rules! define_syscall {
- (fn $name:ident($($arg:ident: $typ:ty),*) -> $ret:ty) => {
- extern "C" {
- pub fn $name($($arg: $typ),*) -> $ret;
- }
- };
- (fn $name:ident($($arg:ident: $typ:ty),*)) => {
- define_syscall!(fn $name($($arg: $typ),*) -> ());
- }
-}
-
-define_syscall!(fn sol_log_(message: *const u8, len: u64));
-define_syscall!(fn sol_log_64_(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64));
-define_syscall!(fn sol_log_compute_units_());
-define_syscall!(fn sol_log_pubkey(pubkey_addr: *const u8));
-define_syscall!(fn sol_create_program_address(seeds_addr: *const u8, seeds_len: u64, program_id_addr: *const u8, address_bytes_addr: *const u8) -> u64);
-define_syscall!(fn sol_try_find_program_address(seeds_addr: *const u8, seeds_len: u64, program_id_addr: *const u8, address_bytes_addr: *const u8, bump_seed_addr: *const u8) -> u64);
-define_syscall!(fn sol_sha256(vals: *const u8, val_len: u64, hash_result: *mut u8) -> u64);
-define_syscall!(fn sol_keccak256(vals: *const u8, val_len: u64, hash_result: *mut u8) -> u64);
-define_syscall!(fn sol_secp256k1_recover(hash: *const u8, recovery_id: u64, signature: *const u8, result: *mut u8) -> u64);
-define_syscall!(fn sol_blake3(vals: *const u8, val_len: u64, hash_result: *mut u8) -> u64);
-define_syscall!(fn sol_get_clock_sysvar(addr: *mut u8) -> u64);
-define_syscall!(fn sol_get_epoch_schedule_sysvar(addr: *mut u8) -> u64);
-define_syscall!(fn sol_get_fees_sysvar(addr: *mut u8) -> u64);
-define_syscall!(fn sol_get_rent_sysvar(addr: *mut u8) -> u64);
-define_syscall!(fn sol_get_last_restart_slot(addr: *mut u8) -> u64);
-define_syscall!(fn sol_memcpy_(dst: *mut u8, src: *const u8, n: u64));
-define_syscall!(fn sol_memmove_(dst: *mut u8, src: *const u8, n: u64));
-define_syscall!(fn sol_memcmp_(s1: *const u8, s2: *const u8, n: u64, result: *mut i32));
-define_syscall!(fn sol_memset_(s: *mut u8, c: u8, n: u64));
-define_syscall!(fn sol_invoke_signed_c(instruction_addr: *const u8, account_infos_addr: *const u8, account_infos_len: u64, signers_seeds_addr: *const u8, signers_seeds_len: u64) -> u64);
-define_syscall!(fn sol_invoke_signed_rust(instruction_addr: *const u8, account_infos_addr: *const u8, account_infos_len: u64, signers_seeds_addr: *const u8, signers_seeds_len: u64) -> u64);
-define_syscall!(fn sol_set_return_data(data: *const u8, length: u64));
define_syscall!(fn sol_get_return_data(data: *mut u8, length: u64, program_id: *mut Pubkey) -> u64);
-define_syscall!(fn sol_log_data(data: *const u8, data_len: u64));
define_syscall!(fn sol_get_processed_sibling_instruction(index: u64, meta: *mut ProcessedSiblingInstruction, program_id: *mut Pubkey, data: *mut u8, accounts: *mut AccountMeta) -> u64);
-define_syscall!(fn sol_get_stack_height() -> u64);
-define_syscall!(fn sol_curve_validate_point(curve_id: u64, point_addr: *const u8, result: *mut u8) -> u64);
-define_syscall!(fn sol_curve_group_op(curve_id: u64, group_op: u64, left_input_addr: *const u8, right_input_addr: *const u8, result_point_addr: *mut u8) -> u64);
-define_syscall!(fn sol_curve_multiscalar_mul(curve_id: u64, scalars_addr: *const u8, points_addr: *const u8, points_len: u64, result_point_addr: *mut u8) -> u64);
-define_syscall!(fn sol_curve_pairing_map(curve_id: u64, point: *const u8, result: *mut u8) -> u64);
-define_syscall!(fn sol_alt_bn128_group_op(group_op: u64, input: *const u8, input_size: u64, result: *mut u8) -> u64);
-define_syscall!(fn sol_big_mod_exp(params: *const u8, result: *mut u8) -> u64);
-define_syscall!(fn sol_get_epoch_rewards_sysvar(addr: *mut u8) -> u64);
-define_syscall!(fn sol_poseidon(parameters: u64, endianness: u64, vals: *const u8, val_len: u64, hash_result: *mut u8) -> u64);
-define_syscall!(fn sol_remaining_compute_units() -> u64);
-define_syscall!(fn sol_alt_bn128_compression(op: u64, input: *const u8, input_size: u64, result: *mut u8) -> u64);
-
-#[cfg(target_feature = "static-syscalls")]
-pub const fn sys_hash(name: &str) -> usize {
- murmur3_32(name.as_bytes(), 0) as usize
-}
-
-#[cfg(target_feature = "static-syscalls")]
-const fn murmur3_32(buf: &[u8], seed: u32) -> u32 {
- const fn pre_mix(buf: [u8; 4]) -> u32 {
- u32::from_le_bytes(buf)
- .wrapping_mul(0xcc9e2d51)
- .rotate_left(15)
- .wrapping_mul(0x1b873593)
- }
-
- let mut hash = seed;
-
- let mut i = 0;
- while i < buf.len() / 4 {
- let buf = [buf[i * 4], buf[i * 4 + 1], buf[i * 4 + 2], buf[i * 4 + 3]];
- hash ^= pre_mix(buf);
- hash = hash.rotate_left(13);
- hash = hash.wrapping_mul(5).wrapping_add(0xe6546b64);
-
- i += 1;
- }
-
- match buf.len() % 4 {
- 0 => {}
- 1 => {
- hash = hash ^ pre_mix([buf[i * 4], 0, 0, 0]);
- }
- 2 => {
- hash = hash ^ pre_mix([buf[i * 4], buf[i * 4 + 1], 0, 0]);
- }
- 3 => {
- hash = hash ^ pre_mix([buf[i * 4], buf[i * 4 + 1], buf[i * 4 + 2], 0]);
- }
- _ => { /* unreachable!() */ }
- }
-
- hash = hash ^ buf.len() as u32;
- hash = hash ^ (hash.wrapping_shr(16));
- hash = hash.wrapping_mul(0x85ebca6b);
- hash = hash ^ (hash.wrapping_shr(13));
- hash = hash.wrapping_mul(0xc2b2ae35);
- hash = hash ^ (hash.wrapping_shr(16));
-
- hash
-}