func (mp *TxPool) isOrphanInPool(hash *chainhash.Hash) bool {
	if _, exists := mp.orphans[*hash]; exists {
		return true
	}
	return false
}
isOrphanInPool returns whether or not the passed transaction already exists
in the orphan pool.

This function MUST be called with the mempool lock held (for reads).
package mempool
import (
	"container/list"
	"fmt"
	"math"
	"sync"
	"sync/atomic"
	"time"
	"github.com/soteria-dag/soterd/blockdag"
	"github.com/soteria-dag/soterd/blockdag/indexers"
	"github.com/soteria-dag/soterd/chaincfg"
	"github.com/soteria-dag/soterd/chaincfg/chainhash"
	"github.com/soteria-dag/soterd/miningdag"
	"github.com/soteria-dag/soterd/soterjson"
	"github.com/soteria-dag/soterd/soterutil"
	"github.com/soteria-dag/soterd/txscript"
	"github.com/soteria-dag/soterd/wire"
)
const (
	DefaultBlockPrioritySize = 50000
	orphanTTL = time.Minute * 15
	orphanExpireScanInterval = time.Minute * 5
)
type Tag uint64
type Config struct {
	Policy Policy
	ChainParams *chaincfg.Params
	FetchUtxoView func(*soterutil.Tx) (*blockdag.UtxoViewpoint, error)
	BestHeight func() int32
	MedianTimePast func() time.Time
	CalcSequenceLock func(*soterutil.Tx, *blockdag.UtxoViewpoint) (*blockdag.SequenceLock, error)
	IsDeploymentActive func(deploymentID uint32) (bool, error)
	SigCache *txscript.SigCache
	HashCache *txscript.HashCache
	AddrIndex *dagindexers.AddrIndex
	FeeEstimator *FeeEstimator
}
type Policy struct {
	MaxTxVersion int32
	DisableRelayPriority bool
	AcceptNonStd bool
	FreeTxRelayLimit float64
	MaxOrphanTxs int
	MaxOrphanTxSize int
	MaxSigOpCostPerTx int
	MinRelayTxFee soterutil.Amount
}
type TxDesc struct {
	miningdag.TxDesc
	StartingPriority float64
}
type orphanTx struct {
	tx         *soterutil.Tx
	tag        Tag
	expiration time.Time
}
type TxPool struct {
	lastUpdated int64  
	mtx           sync.RWMutex
	cfg           Config
	pool          map[chainhash.Hash]*TxDesc
	orphans       map[chainhash.Hash]*orphanTx
	orphansByPrev map[wire.OutPoint]map[chainhash.Hash]*soterutil.Tx
	outpoints     map[wire.OutPoint]*soterutil.Tx
	pennyTotal    float64  
	lastPennyUnix int64    
	nextExpireScan time.Time
}
var _ miningdag.TxSource = (*TxPool)(nil)
func (mp *TxPool) removeOrphan(tx *soterutil.Tx, removeRedeemers bool) {
	txHash := tx.Hash()
	otx, exists := mp.orphans[*txHash]
	if !exists {
		return
	}
	for _, txIn := range otx.tx.MsgTx().TxIn {
		orphans, exists := mp.orphansByPrev[txIn.PreviousOutPoint]
		if exists {
			delete(orphans, *txHash)
			if len(orphans) == 0 {
				delete(mp.orphansByPrev, txIn.PreviousOutPoint)
			}
		}
	}
	if removeRedeemers {
		prevOut := wire.OutPoint{Hash: *txHash}
		for txOutIdx := range tx.MsgTx().TxOut {
			prevOut.Index = uint32(txOutIdx)
			for _, orphan := range mp.orphansByPrev[prevOut] {
				mp.removeOrphan(orphan, true)
			}
		}
	}
	delete(mp.orphans, *txHash)
}
func (mp *TxPool) RemoveOrphan(tx *soterutil.Tx) {
	mp.mtx.Lock()
	mp.removeOrphan(tx, false)
	mp.mtx.Unlock()
}
func (mp *TxPool) RemoveOrphansByTag(tag Tag) uint64 {
	var numEvicted uint64
	mp.mtx.Lock()
	for _, otx := range mp.orphans {
		if otx.tag == tag {
			mp.removeOrphan(otx.tx, true)
			numEvicted++
		}
	}
	mp.mtx.Unlock()
	return numEvicted
}
func (mp *TxPool) limitNumOrphans() error {
	if now := time.Now(); now.After(mp.nextExpireScan) {
		origNumOrphans := len(mp.orphans)
		for _, otx := range mp.orphans {
			if now.After(otx.expiration) {
				mp.removeOrphan(otx.tx, true)
			}
		}
		mp.nextExpireScan = now.Add(orphanExpireScanInterval)
		numOrphans := len(mp.orphans)
		if numExpired := origNumOrphans - numOrphans; numExpired > 0 {
			log.Debugf("Expired %d %s (remaining: %d)", numExpired,
				pickNoun(numExpired, "orphan", "orphans"),
				numOrphans)
		}
	}
	if len(mp.orphans)+1 <= mp.cfg.Policy.MaxOrphanTxs {
		return nil
	}
	for _, otx := range mp.orphans {
		mp.removeOrphan(otx.tx, false)
		break
	}
	return nil
}
func (mp *TxPool) addOrphan(tx *soterutil.Tx, tag Tag) {
	if mp.cfg.Policy.MaxOrphanTxs <= 0 {
		return
	}
	mp.limitNumOrphans()
	mp.orphans[*tx.Hash()] = &orphanTx{
		tx:         tx,
		tag:        tag,
		expiration: time.Now().Add(orphanTTL),
	}
	for _, txIn := range tx.MsgTx().TxIn {
		if _, exists := mp.orphansByPrev[txIn.PreviousOutPoint]; !exists {
			mp.orphansByPrev[txIn.PreviousOutPoint] =
				make(map[chainhash.Hash]*soterutil.Tx)
		}
		mp.orphansByPrev[txIn.PreviousOutPoint][*tx.Hash()] = tx
	}
	log.Debugf("Stored orphan transaction %v (total: %d)", tx.Hash(),
		len(mp.orphans))
}
func (mp *TxPool) maybeAddOrphan(tx *soterutil.Tx, tag Tag) error {
	serializedLen := tx.MsgTx().SerializeSize()
	if serializedLen > mp.cfg.Policy.MaxOrphanTxSize {
		str := fmt.Sprintf("orphan transaction size of %d bytes is "+
			"larger than max allowed size of %d bytes",
			serializedLen, mp.cfg.Policy.MaxOrphanTxSize)
		return txRuleError(wire.RejectNonstandard, str)
	}
	mp.addOrphan(tx, tag)
	return nil
}
func (mp *TxPool) removeOrphanDoubleSpends(tx *soterutil.Tx) {
	msgTx := tx.MsgTx()
	for _, txIn := range msgTx.TxIn {
		for _, orphan := range mp.orphansByPrev[txIn.PreviousOutPoint] {
			mp.removeOrphan(orphan, true)
		}
	}
}
func (mp *TxPool) isTransactionInPool(hash *chainhash.Hash) bool {
	if _, exists := mp.pool[*hash]; exists {
		return true
	}
	return false
}
func (mp *TxPool) IsTransactionInPool(hash *chainhash.Hash) bool {
	mp.mtx.RLock()
	inPool := mp.isTransactionInPool(hash)
	mp.mtx.RUnlock()
	return inPool
}