From 556eb7fc11d5843f1b27c760349579f7d2e3f7ea Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Sun, 23 Jun 2024 03:03:58 +0400 Subject: [PATCH 1/9] move define_syscall macro to its own crate --- Cargo.lock | 4 ++ Cargo.toml | 2 + define-syscall/Cargo.toml | 13 ++++ define-syscall/src/lib.rs | 84 ++++++++++++++++++++++ sdk/program/src/syscalls/definitions.rs | 92 ++----------------------- 5 files changed, 109 insertions(+), 86 deletions(-) create mode 100644 define-syscall/Cargo.toml create mode 100644 define-syscall/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index c71bd32fbab642..1148bacfd93f1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6188,6 +6188,10 @@ dependencies = [ "thiserror", ] +[[package]] +name = "solana-define-syscall" +version = "2.1.0" + [[package]] name = "solana-dos" version = "2.1.0" diff --git a/Cargo.toml b/Cargo.toml index 195ea0c3680fa4..c19e0c555036af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ members = [ "core", "cost-model", "curves/*", + "define-syscall", "dos", "download-utils", "entry", @@ -346,6 +347,7 @@ solana-connection-cache = { path = "connection-cache", version = "=2.1.0", defau solana-core = { path = "core", version = "=2.1.0" } solana-cost-model = { path = "cost-model", version = "=2.1.0" } solana-curve25519 = { path = "curves/curve25519", version = "=2.1.0" } +solana-define-syscall = { path = "define-syscall", version = "=2.0.0" } solana-download-utils = { path = "download-utils", version = "=2.1.0" } solana-entry = { path = "entry", version = "=2.1.0" } solana-faucet = { path = "faucet", version = "=2.1.0" } diff --git a/define-syscall/Cargo.toml b/define-syscall/Cargo.toml new file mode 100644 index 00000000000000..af8ef66d74450e --- /dev/null +++ b/define-syscall/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "solana-define-syscall" +description = "Solana define_syscall macro. For internal use only." +documentation = "https://docs.rs/solana-define-syscall" +version = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +edition = { workspace = true } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/define-syscall/src/lib.rs b/define-syscall/src/lib.rs new file mode 100644 index 00000000000000..16479ff2f12508 --- /dev/null +++ b/define-syscall/src/lib.rs @@ -0,0 +1,84 @@ +#[cfg(target_feature = "static-syscalls")] +#[macro_export] +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_export] +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),*) -> ()); + } +} + +#[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 +} diff --git a/sdk/program/src/syscalls/definitions.rs b/sdk/program/src/syscalls/definitions.rs index bdae7960b33da3..eb26d640832bf5 100644 --- a/sdk/program/src/syscalls/definitions.rs +++ b/sdk/program/src/syscalls/definitions.rs @@ -1,41 +1,11 @@ -use crate::{ - instruction::{AccountMeta, ProcessedSiblingInstruction}, - pubkey::Pubkey, +use { + crate::{ + instruction::{AccountMeta, ProcessedSiblingInstruction}, + pubkey::Pubkey, + }, + solana_define_syscall::define_syscall, }; -#[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_()); @@ -77,53 +47,3 @@ define_syscall!(fn sol_get_epoch_rewards_sysvar(addr: *mut u8) -> u64); // this cannot go through sol_get_sysvar but can be removed once no longer in use define_syscall!(fn sol_get_fees_sysvar(addr: *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 -} From 3e179b1b9a59c1e7e2b75c362d1f36aa698c9539 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Sun, 23 Jun 2024 03:12:57 +0400 Subject: [PATCH 2/9] use solana-define-syscall in solana-poseidon --- Cargo.lock | 1 + poseidon/Cargo.toml | 3 +++ poseidon/src/lib.rs | 16 +++++++--------- programs/sbf/Cargo.lock | 5 +++++ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1148bacfd93f1f..69b72092e2ee8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6792,6 +6792,7 @@ version = "2.1.0" dependencies = [ "ark-bn254", "light-poseidon", + "solana-define-syscall", "thiserror", ] diff --git a/poseidon/Cargo.toml b/poseidon/Cargo.toml index 2787f501e57ff8..09f40b2ac65ecb 100644 --- a/poseidon/Cargo.toml +++ b/poseidon/Cargo.toml @@ -12,6 +12,9 @@ edition = { workspace = true } [dependencies] thiserror = { workspace = true } +[target.'cfg(target_os = "solana")'.dependencies] +solana-define-syscall = { workspace = true } + [target.'cfg(not(target_os = "solana"))'.dependencies] ark-bn254 = { workspace = true } light-poseidon = { workspace = true } diff --git a/poseidon/src/lib.rs b/poseidon/src/lib.rs index f4b6530a1d5aa4..9e65cc60d31503 100644 --- a/poseidon/src/lib.rs +++ b/poseidon/src/lib.rs @@ -170,15 +170,13 @@ impl PoseidonHash { } #[cfg(target_os = "solana")] -extern "C" { - pub fn sol_poseidon( - parameters: u64, - endianness: u64, - vals: *const u8, - val_len: u64, - hash_result: *mut u8, - ) -> u64; -} +solana_define_syscall::define_syscall!(fn sol_poseidon( + parameters: u64, + endianness: u64, + vals: *const u8, + val_len: u64, + hash_result: *mut u8, +) -> u64); /// Return a Poseidon hash for the given data with the given elliptic curve and /// endianness. diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 8a192d1b538512..36427ed000f525 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -4937,6 +4937,10 @@ dependencies = [ "thiserror", ] +[[package]] +name = "solana-define-syscall" +version = "2.0.0" + [[package]] name = "solana-download-utils" version = "2.1.0" @@ -5273,6 +5277,7 @@ version = "2.1.0" dependencies = [ "ark-bn254", "light-poseidon", + "solana-define-syscall", "thiserror", ] From 1c5314eecf247b6411eba92effee05e17f2a92a8 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Sun, 23 Jun 2024 03:41:03 +0400 Subject: [PATCH 3/9] add missing dep to solana-program --- Cargo.lock | 1 + programs/sbf/Cargo.lock | 1 + sdk/program/Cargo.toml | 1 + 3 files changed, 3 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 69b72092e2ee8c..8e13c3ccd8a785 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6841,6 +6841,7 @@ dependencies = [ "serial_test", "sha2 0.10.8", "sha3 0.10.8", + "solana-define-syscall", "solana-frozen-abi", "solana-frozen-abi-macro", "solana-logger", diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 36427ed000f525..2f19f1b01b2f1e 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -5319,6 +5319,7 @@ dependencies = [ "serde_derive", "sha2 0.10.8", "sha3 0.10.8", + "solana-define-syscall", "solana-sanitize", "solana-sdk-macro", "thiserror", diff --git a/sdk/program/Cargo.toml b/sdk/program/Cargo.toml index 45a6927d8cc447..a798bcada04608 100644 --- a/sdk/program/Cargo.toml +++ b/sdk/program/Cargo.toml @@ -44,6 +44,7 @@ thiserror = { workspace = true } # hashbrown dependency as optional. [target.'cfg(target_os = "solana")'.dependencies] getrandom = { workspace = true, features = ["custom"] } +solana-define-syscall = { workspace = true } [target.'cfg(not(target_os = "solana"))'.dependencies] ark-bn254 = { workspace = true } From bc684db0290b0c9f78b99c717062622b410cd66a Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Wed, 26 Jun 2024 07:19:10 +0400 Subject: [PATCH 4/9] update crate version to match workspace --- Cargo.toml | 2 +- programs/sbf/Cargo.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c19e0c555036af..02ab28a0acea10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -347,7 +347,7 @@ solana-connection-cache = { path = "connection-cache", version = "=2.1.0", defau solana-core = { path = "core", version = "=2.1.0" } solana-cost-model = { path = "cost-model", version = "=2.1.0" } solana-curve25519 = { path = "curves/curve25519", version = "=2.1.0" } -solana-define-syscall = { path = "define-syscall", version = "=2.0.0" } +solana-define-syscall = { path = "define-syscall", version = "=2.1.0" } solana-download-utils = { path = "download-utils", version = "=2.1.0" } solana-entry = { path = "entry", version = "=2.1.0" } solana-faucet = { path = "faucet", version = "=2.1.0" } diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 2f19f1b01b2f1e..2851a373c75521 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -4939,7 +4939,7 @@ dependencies = [ [[package]] name = "solana-define-syscall" -version = "2.0.0" +version = "2.1.0" [[package]] name = "solana-download-utils" From 1694ba6b45446fe09a3aedf8f1c70f8e07ac906d Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Wed, 26 Jun 2024 09:47:29 +0400 Subject: [PATCH 5/9] macro hygiene fix --- define-syscall/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/define-syscall/src/lib.rs b/define-syscall/src/lib.rs index 16479ff2f12508..0c5ff5d8a0eed9 100644 --- a/define-syscall/src/lib.rs +++ b/define-syscall/src/lib.rs @@ -7,7 +7,7 @@ macro_rules! define_syscall { // this enum is used to force the hash to be computed in a const context #[repr(usize)] enum Syscall { - Code = sys_hash(stringify!($name)), + Code = $crate::sys_hash(stringify!($name)), } let syscall: extern "C" fn($($arg: $typ),*) -> $ret = core::mem::transmute(Syscall::Code); From 917c2bf3f71b03ab0cf39b416cab6b2318dca17b Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Thu, 27 Jun 2024 08:35:47 +0400 Subject: [PATCH 6/9] fix define_syscall call --- poseidon/src/lib.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/poseidon/src/lib.rs b/poseidon/src/lib.rs index 9e65cc60d31503..81bd84f80d2a04 100644 --- a/poseidon/src/lib.rs +++ b/poseidon/src/lib.rs @@ -170,13 +170,7 @@ impl PoseidonHash { } #[cfg(target_os = "solana")] -solana_define_syscall::define_syscall!(fn sol_poseidon( - parameters: u64, - endianness: u64, - vals: *const u8, - val_len: u64, - hash_result: *mut u8, -) -> u64); +solana_define_syscall::define_syscall!(fn sol_poseidon(parameters: u64, endianness: u64, vals: *const u8, val_len: u64, hash_result: *mut u8) -> u64); /// Return a Poseidon hash for the given data with the given elliptic curve and /// endianness. From 48927ff555e44d3bd80619c38f8c93fa76a98905 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Thu, 27 Jun 2024 15:05:39 +0400 Subject: [PATCH 7/9] re-export sys_hash in solana-program for backwards compatibility --- sdk/program/src/syscalls/definitions.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/program/src/syscalls/definitions.rs b/sdk/program/src/syscalls/definitions.rs index eb26d640832bf5..1d35cd9bb5aec9 100644 --- a/sdk/program/src/syscalls/definitions.rs +++ b/sdk/program/src/syscalls/definitions.rs @@ -1,3 +1,4 @@ +pub use solana_define_syscall::sys_hash; use { crate::{ instruction::{AccountMeta, ProcessedSiblingInstruction}, From 652df986cc4471e1b80fbe3f324351a12fc9c061 Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Thu, 27 Jun 2024 15:06:24 +0400 Subject: [PATCH 8/9] convert tabs to spaces --- define-syscall/src/lib.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/define-syscall/src/lib.rs b/define-syscall/src/lib.rs index 0c5ff5d8a0eed9..7e94b953bfef4d 100644 --- a/define-syscall/src/lib.rs +++ b/define-syscall/src/lib.rs @@ -2,13 +2,13 @@ #[macro_export] macro_rules! define_syscall { (fn $name:ident($($arg:ident: $typ:ty),*) -> $ret:ty) => { - #[inline] + #[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 = $crate::sys_hash(stringify!($name)), - } + // this enum is used to force the hash to be computed in a const context + #[repr(usize)] + enum Syscall { + Code = $crate::sys_hash(stringify!($name)), + } let syscall: extern "C" fn($($arg: $typ),*) -> $ret = core::mem::transmute(Syscall::Code); syscall($($arg),*) @@ -23,14 +23,14 @@ macro_rules! define_syscall { #[cfg(not(target_feature = "static-syscalls"))] #[macro_export] 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),*) -> ()); - } + (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),*) -> ()); + } } #[cfg(target_feature = "static-syscalls")] From bdc8d2c3d9f8cffef874944c8efc3dd54cd9157f Mon Sep 17 00:00:00 2001 From: kevinheavey Date: Thu, 27 Jun 2024 15:43:36 +0400 Subject: [PATCH 9/9] put re-export behind #[cfg(target_feature = "static-syscalls")] --- sdk/program/src/syscalls/definitions.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/program/src/syscalls/definitions.rs b/sdk/program/src/syscalls/definitions.rs index 1d35cd9bb5aec9..5988cbb76d4073 100644 --- a/sdk/program/src/syscalls/definitions.rs +++ b/sdk/program/src/syscalls/definitions.rs @@ -1,3 +1,4 @@ +#[cfg(target_feature = "static-syscalls")] pub use solana_define_syscall::sys_hash; use { crate::{