{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} module Blockchain.Database.MerklePatricia.StateRoot ( StateRoot(..), emptyTriePtr, sha2StateRoot, unboxStateRoot, formatStateRoot ) where import Control.Monad import qualified Data.ByteString.Base16 as B16 import Data.ByteArray (convert) import Crypto.Hash as Crypto import Data.Binary import qualified Data.ByteString as B import Data.String import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8) import Blockchain.Data.RLP import Text.PrettyPrint.ANSI.Leijen hiding ((<$>)) import GHC.Generics -- | Internal nodes are indexed in the underlying database by their 256-bit SHA3 hash. -- This types represents said hash. -- -- The stateRoot is of this type, -- (ie- the pointer to the full set of key/value pairs at a particular time in history), and -- will be of interest if you need to refer to older or parallel version of the data. newtype StateRoot = StateRoot B.ByteString deriving (Show, Eq, Read, Generic, IsString) formatStateRoot :: StateRoot -> String formatStateRoot (StateRoot sr) = T.unpack . decodeUtf8 . B16.encode $ sr instance Pretty StateRoot where pretty = text . formatStateRoot instance Binary StateRoot where put (StateRoot x) = sequence_ $ put <$> B.unpack x get = StateRoot <$> B.pack <$> replicateM 32 get instance RLPSerializable StateRoot where rlpEncode (StateRoot x) = rlpEncode x rlpDecode x = StateRoot $ rlpDecode x -- | The stateRoot of the empty database. emptyTriePtr::StateRoot emptyTriePtr = let root = rlpEncode (0::Integer) rootHash = convert $ (Crypto.hash . rlpSerialize $ root :: Crypto.Digest Crypto.Keccak_256) in StateRoot rootHash sha2StateRoot::Digest Crypto.Keccak_256 -> StateRoot sha2StateRoot = StateRoot . convert unboxStateRoot :: StateRoot -> B.ByteString unboxStateRoot (StateRoot b) = b