Browse Source

Extract define-syscall crate (#1827)

* move define_syscall macro to its own crate

* use solana-define-syscall in solana-poseidon

* add missing dep to solana-program

* update crate version to match workspace

* macro hygiene fix

* fix define_syscall call

* re-export sys_hash in solana-program for backwards compatibility

* convert tabs to spaces

* put re-export behind #[cfg(target_feature = "static-syscalls")]
Kevin Heavey 1 year ago
parent
commit
8eef73da38

+ 6 - 0
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"
@@ -6788,6 +6792,7 @@ version = "2.1.0"
 dependencies = [
  "ark-bn254",
  "light-poseidon",
+ "solana-define-syscall",
  "thiserror",
 ]
 
@@ -6836,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",

+ 2 - 0
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.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" }

+ 13 - 0
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"]

+ 84 - 0
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 = $crate::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
+}

+ 3 - 0
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 }

+ 1 - 9
poseidon/src/lib.rs

@@ -170,15 +170,7 @@ 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.

+ 6 - 0
programs/sbf/Cargo.lock

@@ -4937,6 +4937,10 @@ dependencies = [
  "thiserror",
 ]
 
+[[package]]
+name = "solana-define-syscall"
+version = "2.1.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",
 ]
 
@@ -5314,6 +5319,7 @@ dependencies = [
  "serde_derive",
  "sha2 0.10.8",
  "sha3 0.10.8",
+ "solana-define-syscall",
  "solana-sanitize",
  "solana-sdk-macro",
  "thiserror",

+ 1 - 0
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 }

+ 8 - 86
sdk/program/src/syscalls/definitions.rs

@@ -1,40 +1,12 @@
-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),*) -> ());
-	}
-}
+pub use solana_define_syscall::sys_hash;
+use {
+    crate::{
+        instruction::{AccountMeta, ProcessedSiblingInstruction},
+        pubkey::Pubkey,
+    },
+    solana_define_syscall::define_syscall,
+};
 
 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));
@@ -77,53 +49,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
-}