func (was *WriteAheadState) ApplyTransaction(
	tx *EVMLTransaction,
	txIndex int,
	blockHash common.Hash,
	coinbase common.Address) error {
	txHash := tx.Hash()
	err := was.BaseState.ApplyTransaction(tx, txIndex, blockHash, coinbase, false)
	if err != nil || tx.receipt == nil {
		was.logger.WithError(err).Error("Applying transaction to WAS")
		if promise, ok := was.receiptPromises[txHash]; ok {
			promise.Respond(nil, err)
			delete(was.receiptPromises, txHash)
		}
		return err
	}
	was.txIndex++
	was.txs[txHash] = tx
	was.allLogs = append(was.allLogs, tx.receipt.Logs...)
	if was.logger.Level > logrus.InfoLevel {
		was.logger.WithField("hash", txHash.Hex()).Debug("Applied tx to WAS")
	}
	return nil
}
ApplyTransaction executes the transaction on the WAS BaseState. If the
transaction returns a "consensus" error (an error that is not due to EVM
execution), it will not produce a receipt, and will not be saved; if there is
a promise attached to it, we quickly resolve it with an error. If the
transaction did not return a "consensus" error, we record it and its receipt,
even if its status is "failed".
package state
import (
	"fmt"
	"sync"
	"github.com/ethereum/go-ethereum/common"
	ethTypes "github.com/ethereum/go-ethereum/core/types"
	"github.com/sirupsen/logrus"
)
type WriteAheadState struct {
	BaseState
	txIndex int
	txs     map[common.Hash]*EVMLTransaction
	allLogs []*ethTypes.Log
	receiptPromises map[common.Hash]*ReceiptPromise
	promiseLock     sync.Mutex
	logger *logrus.Entry
}
func NewWriteAheadState(base BaseState, logger *logrus.Entry) *WriteAheadState {
	return &WriteAheadState{
		BaseState:       base,
		txs:             make(map[common.Hash]*EVMLTransaction),
		receiptPromises: make(map[common.Hash]*ReceiptPromise),
		logger:          logger,
	}
}
func (was *WriteAheadState) Reset(root common.Hash) error {
	err := was.BaseState.Reset(root)
	if err != nil {
		return err
	}
	was.txIndex = 0
	was.txs = make(map[common.Hash]*EVMLTransaction)
	was.allLogs = []*ethTypes.Log{}
	return nil
}
func (was *WriteAheadState) CreateReceiptPromise(hash common.Hash) *ReceiptPromise {
	was.promiseLock.Lock()
	defer was.promiseLock.Unlock()
	p := NewReceiptPromise(hash)
	was.receiptPromises[hash] = p
	return p
}