module Blockchain.SHA (
SHA(..),
hash,
rlp2Word512,
word5122RLP,
padZeros,
sha2SHAPtr
) where
import Control.Monad
import qualified Crypto.Hash.SHA3 as C
import Data.Binary
import qualified Data.ByteString.Base16 as B16
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BC
import qualified Data.ByteString.Lazy.Char8 as BLC
import Network.Haskoin.Internals
import Numeric
import Text.PrettyPrint.ANSI.Leijen hiding ((<$>))
import Blockchain.Data.RLP
import Blockchain.Database.MerklePatricia
import Blockchain.Util
newtype SHA = SHA Word256 deriving (Show, Eq)
instance Pretty SHA where
pretty (SHA x) = yellow $ text $ padZeros 64 $ showHex x ""
instance Binary SHA where
put (SHA x) = sequence_ $ fmap put $ word256ToBytes $ fromIntegral x
get = do
bytes <- replicateM 32 get
let byteString = B.pack bytes
return (SHA $ fromInteger $ byteString2Integer byteString)
instance RLPSerializable SHA where
rlpDecode (RLPString s) | length s == 32 = SHA $ decode $ BLC.pack s
rlpDecode (RLPScalar 0) = SHA 0 --special case seems to be allowed, even if length of zeros is wrong
rlpDecode x = error ("Missing case in rlpDecode for SHA: " ++ show x)
--rlpEncode (SHA 0) = RLPNumber 0
rlpEncode (SHA val) = RLPString $ BC.unpack $ fst $ B16.decode $ BC.pack $ padZeros 64 $ showHex val ""
sha2SHAPtr::SHA->SHAPtr
sha2SHAPtr (SHA x) = SHAPtr $ B.pack $ word256ToBytes x
hash::BC.ByteString->SHA
hash = SHA . fromIntegral . byteString2Integer . C.hash 256
--------------------- Word512 stuff
rlp2Word512::RLPObject->Word512
rlp2Word512 (RLPString s) | length s == 64 = decode $ BLC.pack s
rlp2Word512 x = error ("Missing case in rlp2Word512: " ++ show x)
word5122RLP::Word512->RLPObject
word5122RLP val = RLPString $ BLC.unpack $ encode val