func (s *State) GetReceipt(txHash common.Hash) (*ethTypes.Receipt, error) {
	return s.was.GetReceipt(txHash)
}
GetReceipt fetches a transaction's receipt from the WAS
package state
import (
	"encoding/hex"
	"encoding/json"
	"io/ioutil"
	"math/big"
	"os"
	"strings"
	"github.com/ethereum/go-ethereum/common"
	ethTypes "github.com/ethereum/go-ethereum/core/types"
	ethState "github.com/ethereum/go-ethereum/core/state"
	"github.com/ethereum/go-ethereum/core/vm"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/sirupsen/logrus"
	bcommon "github.com/mosaicnetworks/evm-lite/src/common"
)
var (
	_fdLimit  = 8192
	_gasLimit = uint64(1000000000000000000)
)
type State struct {
	main   BaseState
	was    *WriteAheadState
	txPool *TxPool
	genesisFile string
	logger *logrus.Entry
}
func NewState(dbFile string, dbCache int, genesisFile string, logger *logrus.Entry) (*State, error) {
	db, err := ethdb.NewLDBDatabase(dbFile, dbCache, _fdLimit)
	if err != nil {
		return nil, err
	}
	main := NewBaseState(db,
		common.Hash{},
		ethTypes.NewEIP155Signer(CustomChainConfig.ChainID),
		CustomChainConfig,
		vm.Config{Tracer: vm.NewStructLogger(nil)},
		_gasLimit,
	)
	s := &State{
		main:        main,
		was:         NewWriteAheadState(main.Copy(), logger),
		txPool:      NewTxPool(main.Copy(), logger),
		genesisFile: genesisFile,
		logger:      logger,
	}
	err = s.CreateGenesisAccounts()
	if err != nil {
		return nil, err
	}
	return s, nil
}
func (s *State) CreateGenesisAccounts() error {
	genesis, err := s.GetGenesis()
	if err != nil {
		if os.IsNotExist(err) {
			return nil
		}
		return err
	}
	for addr, account := range genesis.Alloc {
		address := common.HexToAddress(addr)
		s.was.CreateAccount(address,
			account.Code,
			account.Storage,
			account.Balance,
			account.Nonce)
		s.logger.WithFields(logrus.Fields{"address": addr,
			"nonce": account.Nonce}).Debug("Adding account")
	}
	if string(genesis.Poa.Address) != "" {
		address := common.HexToAddress(genesis.Poa.Address)
		s.was.CreateAccount(address,
			genesis.Poa.Code,
			genesis.Poa.Storage,
			genesis.Poa.Balance,
			genesis.Poa.Nonce)
		setPOAADDR(genesis.Poa.Address)
		setPOAABI(genesis.Poa.Abi)
		s.logger.WithField("address", genesis.Poa.Address).Debug("Adding POA smart-contract account")
	}
	if _, err = s.Commit(); err != nil {
		return err
	}
	return nil
}
func (s *State) ApplyTransaction(
	txBytes []byte,
	txIndex int,
	blockHash common.Hash,
	coinbase common.Address) error {
	t, err := NewEVMLTransaction(txBytes, s.GetSigner())
	if err != nil {
		s.logger.WithError(err).Error("Decoding Transaction")
		return err
	}
	if s.logger.Level > logrus.InfoLevel {
		s.logger.WithField("hash", t.Hash().Hex()).Debug("Decoded tx")
	}
	return s.was.ApplyTransaction(t, txIndex, blockHash, coinbase)
}
func (s *State) Commit() (common.Hash, error) {
	root, err := s.was.Commit()
	if err != nil {
		s.logger.WithError(err).Error("Committing WAS")
		return root, err
	}
	if err := s.main.Reset(root); err != nil {
		s.logger.WithError(err).Error("Resetting main StateDB")
		return root, err
	}
	if s.logger.Level > logrus.InfoLevel {
		s.logger.WithField("root", root.Hex()).Debug("Committed")
	}
	if err := s.was.Reset(root); err != nil {
		s.logger.WithError(err).Error("Resetting WAS")
		return root, err
	}
	s.logger.Debug("Reset WAS")
	if err := s.txPool.Reset(root); err != nil {
		s.logger.WithError(err).Error("Resetting TxPool")
		return root, err
	}
	s.logger.Debug("Reset TxPool")
	return root, nil
}
func (s *State) GetGasLimit() uint64 {
	return s.main.gasLimit
}
func (s *State) GetGenesis() (bcommon.Genesis, error) {
	if _, err := os.Stat(s.genesisFile); err != nil {
		return bcommon.Genesis{}, err
	}
	contents, err := ioutil.ReadFile(s.genesisFile)
	if err != nil {
		return bcommon.Genesis{}, err
	}
	var genesis bcommon.Genesis
	if err := json.Unmarshal(contents, &genesis); err != nil {
		return bcommon.Genesis{}, err
	}
	return genesis, nil
}
func (s *State) GetAuthorisingAccount() string {
	return POAADDR.String()
}
func (s *State) GetAuthorisingABI() string {
	return POAABISTRING
}
func (s *State) GetSigner() ethTypes.Signer {
	return s.main.signer
}
func (s *State) Call(callMsg ethTypes.Message) ([]byte, error) {
	res, err := s.was.Call(callMsg)
	if err != nil {
		s.logger.WithError(err).Error("Executing Call on WAS")
		return nil, err
	}
	return res, err
}
func (s *State) CreateReceiptPromise(hash common.Hash) *ReceiptPromise {
	return s.was.CreateReceiptPromise(hash)
}
func (s *State) CheckTx(tx *EVMLTransaction) error {
	return s.txPool.CheckTx(tx)
}
func (s *State) GetBalance(addr common.Address, fromPool bool) *big.Int {
	if fromPool {
		return s.txPool.GetBalance(addr)
	}
	return s.main.GetBalance(addr)
}
func (s *State) GetNonce(addr common.Address, fromPool bool) uint64 {
	if fromPool {
		return s.txPool.GetNonce(addr)
	}
	return s.main.GetNonce(addr)
}
func (s *State) GetCode(addr common.Address, fromPool bool) []byte {
	if fromPool {
		return s.txPool.GetCode(addr)
	}
	return s.main.GetCode(addr)
}
func (s *State) GetStorage(addr common.Address, fromPool bool) map[string]string {
	if fromPool {
		return s.txPool.GetStorage(addr)
	}
	return s.main.GetStorage(addr)
}
func (s *State) GetTransaction(txHash common.Hash) (*ethTypes.Transaction, error) {
	return s.was.GetTransaction(txHash)
}