diff --git a/sdk/src/hash.rs b/sdk/src/hash.rs index 4c7553847..ffe008fa1 100644 --- a/sdk/src/hash.rs +++ b/sdk/src/hash.rs @@ -5,6 +5,8 @@ use generic_array::typenum::U32; use generic_array::GenericArray; use sha2::{Digest, Sha256}; use std::fmt; +use std::mem; +use std::str::FromStr; #[derive(Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Hash(GenericArray); @@ -50,11 +52,33 @@ impl fmt::Display for Hash { } } +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ParseHashError { + WrongSize, + Invalid, +} + +impl FromStr for Hash { + type Err = ParseHashError; + + fn from_str(s: &str) -> Result { + let bytes = bs58::decode(s) + .into_vec() + .map_err(|_| ParseHashError::Invalid)?; + if bytes.len() != mem::size_of::() { + Err(ParseHashError::WrongSize) + } else { + Ok(Hash::new(&bytes)) + } + } +} + impl Hash { pub fn new(hash_slice: &[u8]) -> Self { Hash(GenericArray::clone_from_slice(&hash_slice)) } } + /// Return a Sha256 hash for the given data. pub fn hashv(vals: &[&[u8]]) -> Hash { let mut hasher = Hasher::default(); @@ -73,3 +97,44 @@ pub fn extend_and_hash(id: &Hash, val: &[u8]) -> Hash { hash_data.extend_from_slice(val); hash(&hash_data) } + +#[cfg(test)] +mod tests { + use super::*; + use bs58; + + #[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 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) + ); + } + +} diff --git a/sdk/src/pubkey.rs b/sdk/src/pubkey.rs index ea95ec955..768075911 100644 --- a/sdk/src/pubkey.rs +++ b/sdk/src/pubkey.rs @@ -65,8 +65,6 @@ mod tests { let pubkey = Keypair::new().pubkey(); let mut pubkey_base58_str = bs58::encode(pubkey.0).into_string(); - dbg!(&pubkey_base58_str); - assert_eq!(pubkey_base58_str.parse::(), Ok(pubkey)); pubkey_base58_str.push_str(&bs58::encode(pubkey.0).into_string());