func (mem *Mempool) CheckTx(tx agtypes.Tx) (err error) {
	if mem.cache.Exists(tx) {
		return errors.New("Duplicate transaction (ignored)")
	}
	if mem.config.GetBool("mempool_enable_txs_limits") && mem.txs.Len() > mem.txLimit {
		return errors.New("Too many unsolved TX (rejected)")
	}
	if err := mem.checkTxWithFilters(tx); err != nil {
		return errors.New("plugin checktx failed with error: " + err.Error())
	}
	if mem.wal != nil {
		mem.wal.Write([]byte(tx))
		mem.wal.Write([]byte("\n"))
	}
	mem.cache.Push(tx)
	nc := atomic.AddInt64(&mem.counter, 1)
	memTx := &mempoolTx{
		counter: nc,
		height:  atomic.LoadInt64(&mem.height),
		tx:      tx,
	}
	mem.txs.PushBack(memTx)
	return nil
}
Try a new transaction in the mempool.
Potentially blocking if we're blocking on Update() or Reap().
cb: A callback from the CheckTx command.
It gets called from another goroutine.
CONTRACT: Either cb will get called, or err returned.
package mempool
import (
	"container/list"
	"errors"
	"sync"
	"sync/atomic"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"time"
	agtypes "github.com/annchain/annchain/angine/types"
	auto "github.com/annchain/annchain/module/lib/go-autofile"
	"github.com/annchain/annchain/module/lib/go-clist"
	cmn "github.com/annchain/annchain/module/lib/go-common"
	"github.com/annchain/annchain/module/xlib/def"
	"github.com/annchain/annchain/types"
	"github.com/annchain/anth/rlp"
)
const cacheSize = 100000
type IFilter interface {
	CheckTx(agtypes.Tx) (bool, error)
}
type Mempool struct {
	config  *viper.Viper
	mtx     sync.Mutex
	txs     *clist.CList  
	counter def.INT       
	height  def.INT       
	cache *txCache
	wal *auto.AutoFile  
	txLimit int
	txFilters []IFilter
	logger *zap.Logger
}
func NewMempool(logger *zap.Logger, config *viper.Viper) *Mempool {
	mempool := &Mempool{
		config:  config,
		txs:     clist.New(),
		counter: 0,
		height:  0,
		cache:   newTxCache(cacheSize),
		txLimit: config.GetInt("block_max_txs") * 2,
		logger:  logger,
	}
	mempool.initWAL()
	blockSortInterval := config.GetInt("mempool_block_sort_interval")
	if blockSortInterval > 0 {
		go func() {
			t := time.Tick(time.Millisecond * time.Duration(blockSortInterval))
			for {
				select {
				case <-t:
					mempool.sortTxs()
				}
			}
		}()
	}
	return mempool
}
func (mem *Mempool) RegisterFilter(filter IFilter) {
	mem.txFilters = append(mem.txFilters, filter)
}
func (mem *Mempool) Lock() {
	mem.mtx.Lock()
}
func (mem *Mempool) Unlock() {
	mem.mtx.Unlock()
}
func (mem *Mempool) Size() int {
	return mem.txs.Len()
}
func (mem *Mempool) Flush() {
	mem.Lock()
	mem.cache.Reset()
	for e := mem.txs.Front(); e != nil; e = e.Next() {
		mem.txs.Remove(e)
		e.DetachPrev()
	}
	mem.Unlock()
}
func (mem *Mempool) TxsFrontWait() *clist.CElement {
	return mem.txs.FrontWait()
}