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 @@ Limestone

- 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 -}