{-# LANGUAGE OverloadedStrings #-} module Blockchain.Data.AddressState ( AddressState(..), blankAddressState, getAddressState, getAllAddressStates, putAddressState ) where import Data.Binary import qualified Data.ByteString.Lazy as BL import Data.Functor import Data.List import Numeric import Text.PrettyPrint.ANSI.Leijen hiding ((<$>)) import Blockchain.Data.Address import qualified Blockchain.Colors as CL import Blockchain.Context import Blockchain.ExtDBs import Blockchain.Format import qualified Data.NibbleString as N import Blockchain.Data.RLP import Blockchain.SHA import Blockchain.Util --import Debug.Trace data AddressState = AddressState { addressStateNonce::Integer, balance::Integer, contractRoot::SHAPtr, codeHash::SHA } deriving (Show) blankAddressState::AddressState blankAddressState = AddressState { addressStateNonce=0, balance=0, contractRoot=emptyTriePtr, codeHash=hash "" } instance Format AddressState where format a = CL.blue "AddressState" ++ tab("\nnonce: " ++ showHex (addressStateNonce a) "" ++ "\nbalance: " ++ show (toInteger $ balance a) ++ "\ncontractRoot: " ++ show (pretty $ contractRoot a) ++ "\ncodeHash: " ++ show (pretty $ codeHash a)) instance RLPSerializable AddressState where rlpEncode a | balance a < 0 = error $ "Error in cal to rlpEncode for AddressState: AddressState has negative balance: " ++ format a rlpEncode a = RLPArray [ rlpEncode $ toInteger $ addressStateNonce a, rlpEncode $ toInteger $ balance a, rlpEncode $ contractRoot a, rlpEncode $ codeHash a ] rlpDecode (RLPArray [n, b, cr, ch]) = AddressState { addressStateNonce=fromInteger $ rlpDecode n, balance=fromInteger $ rlpDecode b, contractRoot=rlpDecode cr, codeHash=rlpDecode ch } rlpDecode x = error $ "Missing case in rlpDecode for AddressState: " ++ show (pretty x) addressAsNibbleString::Address->N.NibbleString addressAsNibbleString (Address s) = N.EvenNibbleString $ BL.toStrict $ encode s getAddressState::Address->ContextM AddressState getAddressState address = do states <- getKeyVals $ addressAsNibbleString address case states of [] -> return blankAddressState [state] -> return $ rlpDecode $ rlpDeserialize $ rlpDecode $ snd state _ -> error ("getAddressStates found multiple states for: " ++ show (pretty address) ++ "\n" ++ intercalate "\n" (show . pretty <$> states)) getAllAddressStates::ContextM [(N.NibbleString, AddressState)] getAllAddressStates = do states <- getKeyVals "" return $ fmap rlpDecode <$> states putAddressState::Address->AddressState->ContextM () putAddressState address newState = putKeyVal (addressAsNibbleString address) $ rlpEncode $ rlpSerialize $ rlpEncode newState