diff --git a/Cargo.lock b/Cargo.lock index 2fe1c1119..059a8b0c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2863,16 +2863,9 @@ name = "solana-blake3-hasher" version = "2.2.1" dependencies = [ "blake3", - "borsh", - "bs58", - "serde", - "serde_derive", "solana-blake3-hasher", "solana-define-syscall", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-hash", - "solana-sanitize", ] [[package]] @@ -3312,15 +3305,9 @@ dependencies = [ name = "solana-keccak-hasher" version = "2.2.1" dependencies = [ - "borsh", - "serde", - "serde_derive", "sha3", "solana-define-syscall", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-hash", - "solana-sanitize", ] [[package]] @@ -3923,6 +3910,7 @@ dependencies = [ "sha2 0.10.8", "solana-define-syscall", "solana-hash", + "solana-sha256-hasher", ] [[package]] diff --git a/blake3-hasher/Cargo.toml b/blake3-hasher/Cargo.toml index 59e969ce7..8d451945a 100644 --- a/blake3-hasher/Cargo.toml +++ b/blake3-hasher/Cargo.toml @@ -15,39 +15,19 @@ all-features = true rustdoc-args = ["--cfg=docsrs"] [features] -borsh = ["dep:borsh", "std"] -dev-context-only-utils = ["std"] -frozen-abi = ["dep:solana-frozen-abi", "dep:solana-frozen-abi-macro", "std"] -serde = ["dep:serde", "dep:serde_derive"] blake3 = ["dep:blake3"] -std = ["solana-hash/std"] [dependencies] -borsh = { workspace = true, optional = true } -serde = { workspace = true, optional = true } -serde_derive = { workspace = true, optional = true } -solana-frozen-abi = { workspace = true, optional = true, features = [ - "frozen-abi", -] } -solana-frozen-abi-macro = { workspace = true, optional = true, features = [ - "frozen-abi", -] } solana-hash = { workspace = true } -solana-sanitize = { workspace = true } [target.'cfg(not(target_os = "solana"))'.dependencies] -blake3 = { workspace = true } +blake3 = { workspace = true, optional = true } [target.'cfg(target_os = "solana")'.dependencies] -# blake3 should be removed in the next breaking release, -# as there's no reason to use the crate instead of the syscall -# onchain -blake3 = { workspace = true, optional = true } solana-define-syscall = { workspace = true } [dev-dependencies] -bs58 = { workspace = true, features = ["std"] } -solana-blake3-hasher = { path = ".", features = ["dev-context-only-utils"] } +solana-blake3-hasher = { path = ".", features = ["blake3"] } [lints] workspace = true diff --git a/blake3-hasher/src/lib.rs b/blake3-hasher/src/lib.rs index c13f817d1..da56a1710 100644 --- a/blake3-hasher/src/lib.rs +++ b/blake3-hasher/src/lib.rs @@ -2,48 +2,17 @@ //! //! [blake3]: https://github.com/BLAKE3-team/BLAKE3 #![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![cfg_attr(feature = "frozen-abi", feature(min_specialization))] #![no_std] -#[cfg(feature = "std")] -extern crate std; -pub use solana_hash::{ParseHashError, HASH_BYTES, MAX_BASE58_LEN}; -#[cfg(feature = "borsh")] -use { - borsh::{BorshDeserialize, BorshSchema, BorshSerialize}, - std::string::ToString, -}; -use { - core::{fmt, str::FromStr}, - solana_sanitize::Sanitize, -}; +pub use solana_hash::{Hash, ParseHashError, HASH_BYTES, MAX_BASE58_LEN}; -// TODO: replace this with `solana_hash::Hash` in the -// next breaking change. -// It's a breaking change because the field is public -// here and private in `solana_hash`, and making -// it public in `solana_hash` would break wasm-bindgen -#[cfg_attr(feature = "frozen-abi", derive(solana_frozen_abi_macro::AbiExample))] -#[cfg_attr( - feature = "borsh", - derive(BorshSerialize, BorshDeserialize, BorshSchema), - borsh(crate = "borsh") -)] -#[cfg_attr( - feature = "serde", - derive(serde_derive::Deserialize, serde_derive::Serialize) -)] -#[derive(Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] -#[repr(transparent)] -pub struct Hash(pub [u8; HASH_BYTES]); - -#[cfg(any(feature = "blake3", not(target_os = "solana")))] #[derive(Clone, Default)] +#[cfg(all(feature = "blake3", not(target_os = "solana")))] pub struct Hasher { hasher: blake3::Hasher, } -#[cfg(any(feature = "blake3", not(target_os = "solana")))] +#[cfg(all(feature = "blake3", not(target_os = "solana")))] impl Hasher { pub fn hash(&mut self, val: &[u8]) { self.hasher.update(val); @@ -54,65 +23,7 @@ impl Hasher { } } pub fn result(self) -> Hash { - Hash(*self.hasher.finalize().as_bytes()) - } -} - -impl From for Hash { - fn from(val: solana_hash::Hash) -> Self { - Self(val.to_bytes()) - } -} - -impl From for solana_hash::Hash { - fn from(val: Hash) -> Self { - Self::new_from_array(val.0) - } -} - -impl Sanitize for Hash {} - -impl AsRef<[u8]> for Hash { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl fmt::Debug for Hash { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let converted: solana_hash::Hash = (*self).into(); - fmt::Debug::fmt(&converted, f) - } -} - -impl fmt::Display for Hash { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let converted: solana_hash::Hash = (*self).into(); - fmt::Display::fmt(&converted, f) - } -} - -impl FromStr for Hash { - type Err = ParseHashError; - - fn from_str(s: &str) -> Result { - let unconverted = solana_hash::Hash::from_str(s)?; - Ok(unconverted.into()) - } -} - -impl Hash { - pub const fn new_from_array(hash_array: [u8; HASH_BYTES]) -> Self { - Self(hash_array) - } - - /// unique Hash for tests and benchmarks. - pub fn new_unique() -> Self { - Self::from(solana_hash::Hash::new_unique()) - } - - pub fn to_bytes(self) -> [u8; HASH_BYTES] { - self.0 + Hash::new_from_array(*self.hasher.finalize().as_bytes()) } } @@ -122,9 +33,17 @@ pub fn hashv(vals: &[&[u8]]) -> Hash { // not supported #[cfg(not(target_os = "solana"))] { - let mut hasher = Hasher::default(); - hasher.hashv(vals); - hasher.result() + #[cfg(feature = "blake3")] + { + let mut hasher = Hasher::default(); + hasher.hashv(vals); + hasher.result() + } + #[cfg(not(feature = "blake3"))] + { + core::hint::black_box(vals); + panic!("hashv is only available on target `solana` or with the `blake3` feature enabled on this crate") + } } // Call via a system call to perform the calculation #[cfg(target_os = "solana")] @@ -146,71 +65,20 @@ pub fn hash(val: &[u8]) -> Hash { hashv(&[val]) } -#[cfg(feature = "std")] -/// Return the hash of the given hash extended with the given value. -pub fn extend_and_hash(id: &Hash, val: &[u8]) -> Hash { - let mut hash_data = id.as_ref().to_vec(); - hash_data.extend_from_slice(val); - hash(&hash_data) -} - #[cfg(test)] +#[cfg(feature = "blake3")] mod tests { use super::*; #[test] - fn test_new_unique() { - assert!(Hash::new_unique() != Hash::new_unique()); - } - - #[test] - fn test_hash_fromstr() { - let hash = hash(&[1u8]); - - let mut hash_base58_str = bs58::encode(hash).into_string(); - - assert_eq!(hash_base58_str.parse::(), Ok(hash)); - - hash_base58_str.push_str(&bs58::encode(hash.0).into_string()); - assert_eq!( - hash_base58_str.parse::(), - Err(ParseHashError::WrongSize) - ); - - hash_base58_str.truncate(hash_base58_str.len() / 2); - assert_eq!(hash_base58_str.parse::(), Ok(hash)); - - hash_base58_str.truncate(hash_base58_str.len() / 2); - assert_eq!( - hash_base58_str.parse::(), - Err(ParseHashError::WrongSize) - ); - - let input_too_big = bs58::encode(&[0xffu8; HASH_BYTES + 1]).into_string(); - assert!(input_too_big.len() > MAX_BASE58_LEN); - assert_eq!( - input_too_big.parse::(), - Err(ParseHashError::WrongSize) - ); - - let mut hash_base58_str = bs58::encode(hash.0).into_string(); - assert_eq!(hash_base58_str.parse::(), Ok(hash)); - - // throw some non-base58 stuff in there - hash_base58_str.replace_range(..1, "I"); - assert_eq!( - hash_base58_str.parse::(), - Err(ParseHashError::Invalid) - ); - } - - #[test] - fn test_extend_and_hash() { + fn test_hashv() { let val = "gHiljKpq"; let val_hash = hash(val.as_bytes()); + let ext = "lM890t"; - let hash_ext = [&val_hash.0, ext.as_bytes()].concat(); - let ext_hash = extend_and_hash(&val_hash, ext.as_bytes()); + let ext_hash = hashv(&[&val_hash.to_bytes(), ext.as_bytes()]); + + let hash_ext = [&val_hash.to_bytes(), ext.as_bytes()].concat(); assert!(ext_hash == hash(&hash_ext)); } } diff --git a/hash/src/lib.rs b/hash/src/lib.rs index d499cffdb..05249da42 100644 --- a/hash/src/lib.rs +++ b/hash/src/lib.rs @@ -139,9 +139,13 @@ impl Hash { Self::new_from_array(b) } - pub fn to_bytes(self) -> [u8; HASH_BYTES] { + pub const fn to_bytes(self) -> [u8; HASH_BYTES] { self.0 } + + pub const fn as_bytes(&self) -> &[u8; HASH_BYTES] { + &self.0 + } } #[cfg(target_arch = "wasm32")] diff --git a/keccak-hasher/Cargo.toml b/keccak-hasher/Cargo.toml index 01faff511..7026d7a35 100644 --- a/keccak-hasher/Cargo.toml +++ b/keccak-hasher/Cargo.toml @@ -15,33 +15,15 @@ all-features = true rustdoc-args = ["--cfg=docsrs"] [features] -borsh = ["dep:borsh", "std"] -frozen-abi = ["dep:solana-frozen-abi", "dep:solana-frozen-abi-macro", "std"] -serde = ["dep:serde", "dep:serde_derive"] sha3 = ["dep:sha3"] -std = ["solana-hash/std"] [dependencies] -borsh = { workspace = true, optional = true } -serde = { workspace = true, optional = true } -serde_derive = { workspace = true, optional = true } -solana-frozen-abi = { workspace = true, optional = true, features = [ - "frozen-abi", -] } -solana-frozen-abi-macro = { workspace = true, optional = true, features = [ - "frozen-abi", -] } solana-hash = { workspace = true } -solana-sanitize = { workspace = true } [target.'cfg(not(target_os = "solana"))'.dependencies] -sha3 = { workspace = true } +sha3 = { workspace = true, optional = true } [target.'cfg(target_os = "solana")'.dependencies] -# sha3 should be removed in the next breaking release, -# as there's no reason to use the crate instead of the syscall -# onchain -sha3 = { workspace = true, optional = true } solana-define-syscall = { workspace = true } [lints] diff --git a/keccak-hasher/src/lib.rs b/keccak-hasher/src/lib.rs index e252e7263..fcc67ed70 100644 --- a/keccak-hasher/src/lib.rs +++ b/keccak-hasher/src/lib.rs @@ -2,50 +2,19 @@ //! //! [keccak]: https://keccak.team/keccak.html #![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![cfg_attr(feature = "frozen-abi", feature(min_specialization))] #![no_std] -#[cfg(feature = "std")] -extern crate std; -#[cfg(any(feature = "sha3", not(target_os = "solana")))] +#[cfg(all(feature = "sha3", not(target_os = "solana")))] use sha3::{Digest, Keccak256}; -pub use solana_hash::{ParseHashError, HASH_BYTES, MAX_BASE58_LEN}; -#[cfg(feature = "borsh")] -use { - borsh::{BorshDeserialize, BorshSchema, BorshSerialize}, - std::string::ToString, -}; -use { - core::{fmt, str::FromStr}, - solana_sanitize::Sanitize, -}; +pub use solana_hash::{Hash, ParseHashError, HASH_BYTES, MAX_BASE58_LEN}; -// TODO: replace this with `solana_hash::Hash` in the -// next breaking change. -// It's a breaking change because the field is public -// here and private in `solana_hash`, and making -// it public in `solana_hash` would break wasm-bindgen -#[cfg_attr(feature = "frozen-abi", derive(solana_frozen_abi_macro::AbiExample))] -#[cfg_attr( - feature = "borsh", - derive(BorshSerialize, BorshDeserialize, BorshSchema), - borsh(crate = "borsh") -)] -#[cfg_attr( - feature = "serde", - derive(serde_derive::Deserialize, serde_derive::Serialize) -)] -#[derive(Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] -#[repr(transparent)] -pub struct Hash(pub [u8; HASH_BYTES]); - -#[cfg(any(feature = "sha3", not(target_os = "solana")))] #[derive(Clone, Default)] +#[cfg(all(feature = "sha3", not(target_os = "solana")))] pub struct Hasher { hasher: Keccak256, } -#[cfg(any(feature = "sha3", not(target_os = "solana")))] +#[cfg(all(feature = "sha3", not(target_os = "solana")))] impl Hasher { pub fn hash(&mut self, val: &[u8]) { self.hasher.update(val); @@ -56,65 +25,7 @@ impl Hasher { } } pub fn result(self) -> Hash { - Hash(self.hasher.finalize().into()) - } -} - -impl From for Hash { - fn from(val: solana_hash::Hash) -> Self { - Self(val.to_bytes()) - } -} - -impl From for solana_hash::Hash { - fn from(val: Hash) -> Self { - Self::new_from_array(val.0) - } -} - -impl Sanitize for Hash {} - -impl AsRef<[u8]> for Hash { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl fmt::Debug for Hash { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let converted: solana_hash::Hash = (*self).into(); - fmt::Debug::fmt(&converted, f) - } -} - -impl fmt::Display for Hash { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let converted: solana_hash::Hash = (*self).into(); - fmt::Display::fmt(&converted, f) - } -} - -impl FromStr for Hash { - type Err = ParseHashError; - - fn from_str(s: &str) -> Result { - let unconverted = solana_hash::Hash::from_str(s)?; - Ok(unconverted.into()) - } -} - -impl Hash { - pub const fn new_from_array(hash_array: [u8; HASH_BYTES]) -> Self { - Self(hash_array) - } - - /// unique Hash for tests and benchmarks. - pub fn new_unique() -> Self { - Self::from(solana_hash::Hash::new_unique()) - } - - pub fn to_bytes(self) -> [u8; HASH_BYTES] { - self.0 + Hash::new_from_array(self.hasher.finalize().into()) } } @@ -124,9 +35,17 @@ pub fn hashv(vals: &[&[u8]]) -> Hash { // not supported #[cfg(not(target_os = "solana"))] { - let mut hasher = Hasher::default(); - hasher.hashv(vals); - hasher.result() + #[cfg(feature = "sha3")] + { + let mut hasher = Hasher::default(); + hasher.hashv(vals); + hasher.result() + } + #[cfg(not(feature = "sha3"))] + { + core::hint::black_box(vals); + panic!("hashv is only available on target `solana` or with the `sha3` feature enabled on this crate") + } } // Call via a system call to perform the calculation #[cfg(target_os = "solana")] @@ -147,11 +66,3 @@ pub fn hashv(vals: &[&[u8]]) -> Hash { pub fn hash(val: &[u8]) -> Hash { hashv(&[val]) } - -#[cfg(feature = "std")] -/// Return the hash of the given hash extended with the given value. -pub fn extend_and_hash(id: &Hash, val: &[u8]) -> Hash { - let mut hash_data = id.as_ref().to_vec(); - hash_data.extend_from_slice(val); - hash(&hash_data) -} diff --git a/offchain-message/Cargo.toml b/offchain-message/Cargo.toml index 0933cc009..20aabebda 100644 --- a/offchain-message/Cargo.toml +++ b/offchain-message/Cargo.toml @@ -24,7 +24,7 @@ solana-hash = { workspace = true } solana-packet = { workspace = true } solana-pubkey = { workspace = true, optional = true } solana-sanitize = { workspace = true } -solana-sha256-hasher = { workspace = true } +solana-sha256-hasher = { workspace = true, features = ["sha2"] } solana-signature = { workspace = true } solana-signer = { workspace = true } diff --git a/program/src/hash.rs b/program/src/hash.rs index 990f6c184..47be382ff 100644 --- a/program/src/hash.rs +++ b/program/src/hash.rs @@ -3,7 +3,9 @@ //! [SHA-256]: https://en.wikipedia.org/wiki/SHA-2 //! [`Hash`]: struct@Hash +#[cfg(not(target_os = "solana"))] +pub use solana_sha256_hasher::Hasher; pub use { solana_hash::{Hash, ParseHashError, HASH_BYTES}, - solana_sha256_hasher::{extend_and_hash, hash, hashv, Hasher}, + solana_sha256_hasher::{extend_and_hash, hash, hashv}, }; diff --git a/secp256k1-program/src/lib.rs b/secp256k1-program/src/lib.rs index 329a33ce5..6516f883f 100644 --- a/secp256k1-program/src/lib.rs +++ b/secp256k1-program/src/lib.rs @@ -738,7 +738,7 @@ //! hasher.hash(&message); //! hasher.result() //! }; -//! let secp_message = libsecp256k1::Message::parse(&message_hash.0); +//! let secp_message = libsecp256k1::Message::parse(message_hash.as_bytes()); //! let (signature, recovery_id) = libsecp256k1::sign(&secp_message, &secret_key); //! let signature = signature.serialize(); //! let recovery_id = recovery_id.serialize(); diff --git a/secp256k1-recover/src/lib.rs b/secp256k1-recover/src/lib.rs index 1cc31d0d8..9e302b9ff 100644 --- a/secp256k1-recover/src/lib.rs +++ b/secp256k1-recover/src/lib.rs @@ -312,7 +312,7 @@ pub use solana_define_syscall::definitions::sol_secp256k1_recover; /// } /// /// let recovered_pubkey = secp256k1_recover( -/// &message_hash.0, +/// message_hash.as_bytes(), /// instruction.recovery_id, /// &instruction.signature, /// ) @@ -365,7 +365,7 @@ pub use solana_define_syscall::definitions::sol_secp256k1_recover; /// hasher.result() /// }; /// -/// let secp_message = libsecp256k1::Message::parse(&message_hash.0); +/// let secp_message = libsecp256k1::Message::parse(message_hash.as_bytes()); /// let (signature, recovery_id) = libsecp256k1::sign(&secp_message, &secp256k1_secret_key); /// /// let signature = signature.serialize(); diff --git a/sha256-hasher/Cargo.toml b/sha256-hasher/Cargo.toml index 5951e38f5..17d278c13 100644 --- a/sha256-hasher/Cargo.toml +++ b/sha256-hasher/Cargo.toml @@ -19,14 +19,13 @@ sha2 = ["dep:sha2"] solana-hash = { workspace = true } [target.'cfg(not(target_os = "solana"))'.dependencies] -sha2 = { workspace = true } +sha2 = { workspace = true, optional = true } [target.'cfg(target_os = "solana")'.dependencies] -# sha2 should be removed in the next breaking release, -# as there's no reason to use the crate instead of the syscall -# onchain -sha2 = { workspace = true, optional = true } solana-define-syscall = { workspace = true } +[dev-dependencies] +solana-sha256-hasher = { path = ".", features = ["sha2"] } + [lints] workspace = true diff --git a/sha256-hasher/src/lib.rs b/sha256-hasher/src/lib.rs index 04c71d918..1c142f613 100644 --- a/sha256-hasher/src/lib.rs +++ b/sha256-hasher/src/lib.rs @@ -1,15 +1,15 @@ #![no_std] -#[cfg(any(feature = "sha2", not(target_os = "solana")))] +#[cfg(all(feature = "sha2", not(target_os = "solana")))] use sha2::{Digest, Sha256}; use solana_hash::Hash; -#[cfg(any(feature = "sha2", not(target_os = "solana")))] +#[cfg(all(feature = "sha2", not(target_os = "solana")))] #[derive(Clone, Default)] pub struct Hasher { hasher: Sha256, } -#[cfg(any(feature = "sha2", not(target_os = "solana")))] +#[cfg(all(feature = "sha2", not(target_os = "solana")))] impl Hasher { pub fn hash(&mut self, val: &[u8]) { self.hasher.update(val); @@ -34,9 +34,17 @@ pub fn hashv(vals: &[&[u8]]) -> Hash { // not supported #[cfg(not(target_os = "solana"))] { - let mut hasher = Hasher::default(); - hasher.hashv(vals); - hasher.result() + #[cfg(feature = "sha2")] + { + let mut hasher = Hasher::default(); + hasher.hashv(vals); + hasher.result() + } + #[cfg(not(feature = "sha2"))] + { + core::hint::black_box(vals); + panic!("hashv is only available on target `solana` or with the `sha2` feature enabled on this crate") + } } // Call via a system call to perform the calculation #[cfg(target_os = "solana")]