packages feed

ethereum-client-haskell-0.0.2: src/Blockchain/Data/Transaction.hs

{-# LANGUAGE OverloadedStrings #-}

module Blockchain.Data.Transaction (
  Transaction(..),
  codeOrDataLength,
  zeroBytesLength
  ) where

import qualified Data.ByteString as B
import Text.PrettyPrint.ANSI.Leijen

import Blockchain.Data.Address
import Blockchain.VM.Code
import qualified Blockchain.Colors as CL
import Blockchain.Format
import Blockchain.Data.RLP
import Blockchain.Util
--import VM

--import Debug.Trace


data Transaction =
  MessageTX {
    tNonce::Integer,
    gasPrice::Integer,
    tGasLimit::Integer,
    to::Address,
    value::Integer,
    tData::B.ByteString
    } |
  ContractCreationTX {
    tNonce::Integer,
    gasPrice::Integer,
    tGasLimit::Integer,
    value::Integer,
    tInit::Code
    } deriving (Show)

instance Format Transaction where
  format MessageTX{tNonce=n, gasPrice=gp, tGasLimit=gl, to=to', value=v, tData=d} =
    CL.blue "Message Transaction" ++
    tab (
      "\n" ++
      "tNonce: " ++ show n ++ "\n" ++
      "gasPrice: " ++ show gp ++ "\n" ++
      "tGasLimit: " ++ show gl ++ "\n" ++
      "to: " ++ show (pretty to') ++ "\n" ++
      "value: " ++ show v ++ "\n" ++
      "tData: " ++ tab ("\n" ++ format d) ++ "\n")
  format ContractCreationTX{tNonce=n, gasPrice=gp, tGasLimit=gl, value=v, tInit=init'} =
    CL.blue "Contract Creation Transaction" ++
    tab (
      "\n" ++
      "tNonce: " ++ show n ++ "\n" ++
      "gasPrice: " ++ show gp ++ "\n" ++
      "tGasLimit: " ++ show gl ++ "\n" ++
      "value: " ++ show v ++ "\n" ++
      "tInit: " ++ tab ("\n" ++ show (pretty init')) ++ "\n")

instance RLPSerializable Transaction where
  rlpDecode (RLPArray [n, gp, gl, RLPString "", val, i]) =
  --rlpDecode (RLPArray [n, gp, gl, toAddr, val, i]) | rlpDecode toAddr == (0::Integer) && not (null $ (rlpDecode i::String)) =
    ContractCreationTX {
      tNonce = rlpDecode n,
      gasPrice = rlpDecode gp,
      tGasLimit = rlpDecode gl,
      value = rlpDecode val,
      tInit = rlpDecode i
      }
  rlpDecode (RLPArray [n, gp, gl, toAddr, val, i]) =
    MessageTX {
      tNonce = rlpDecode n,
      gasPrice = rlpDecode gp,
      tGasLimit = rlpDecode gl,
      to = rlpDecode toAddr,
      value = rlpDecode val,
      tData = rlpDecode i
      }
  rlpDecode x = error ("rlpDecode for Transaction called on non block object: " ++ show x)

  rlpEncode MessageTX{tNonce=n, gasPrice=gp, tGasLimit=gl, to=to', value=v, tData=d} =
      RLPArray [
        rlpEncode n,
        rlpEncode gp,
        rlpEncode gl,
        rlpEncode to',
        rlpEncode v,
        rlpEncode d
        ]
  rlpEncode ContractCreationTX{tNonce=n, gasPrice=gp, tGasLimit=gl, value=v, tInit=init'} =
      RLPArray [
        rlpEncode n,
        rlpEncode gp,
        rlpEncode gl,
        rlpEncode (0::Integer),
        rlpEncode v,
        rlpEncode init'
        ]

codeOrDataLength::Transaction->Int
codeOrDataLength MessageTX{tData=d} = B.length d
codeOrDataLength ContractCreationTX{tInit=d} = codeLength d

zeroBytesLength::Transaction->Int
zeroBytesLength MessageTX{tData=d} = length $ filter (==0) $ B.unpack d
zeroBytesLength ContractCreationTX{tInit=Code d} = length $ filter (==0) $ B.unpack d