@ -20,6 +20,9 @@ import (
"github.com/tendermint/tendermint/types"
)
// TxKeySize is the size of the transaction key index
const TxKeySize = sha256 . Size
//--------------------------------------------------------------------------------
// CListMempool is an ordered in-memory pool for transactions before they are
@ -255,7 +258,7 @@ func (mem *CListMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo Tx
// Note it's possible a tx is still in the cache but no longer in the mempool
// (eg. after committing a block, txs are removed from mempool but not cache),
// so we only record the sender for txs still in the mempool.
if e , ok := mem . txsMap . Load ( t xKey( tx ) ) ; ok {
if e , ok := mem . txsMap . Load ( T xKey( tx ) ) ; ok {
memTx := e . ( * clist . CElement ) . Value . ( * mempoolTx )
memTx . senders . LoadOrStore ( txInfo . SenderID , true )
// TODO: consider punishing peer for dups,
@ -351,7 +354,7 @@ func (mem *CListMempool) reqResCb(
// - resCbFirstTime (lock not held) if tx is valid
func ( mem * CListMempool ) addTx ( memTx * mempoolTx ) {
e := mem . txs . PushBack ( memTx )
mem . txsMap . Store ( t xKey( memTx . tx ) , e )
mem . txsMap . Store ( T xKey( memTx . tx ) , e )
atomic . AddInt64 ( & mem . txsBytes , int64 ( len ( memTx . tx ) ) )
mem . metrics . TxSizeBytes . Observe ( float64 ( len ( memTx . tx ) ) )
}
@ -362,7 +365,7 @@ func (mem *CListMempool) addTx(memTx *mempoolTx) {
func ( mem * CListMempool ) removeTx ( tx types . Tx , elem * clist . CElement , removeFromCache bool ) {
mem . txs . Remove ( elem )
elem . DetachPrev ( )
mem . txsMap . Delete ( t xKey( tx ) )
mem . txsMap . Delete ( T xKey( tx ) )
atomic . AddInt64 ( & mem . txsBytes , int64 ( - len ( tx ) ) )
if removeFromCache {
@ -370,6 +373,16 @@ func (mem *CListMempool) removeTx(tx types.Tx, elem *clist.CElement, removeFromC
}
}
// RemoveTxByKey removes a transaction from the mempool by its TxKey index.
func ( mem * CListMempool ) RemoveTxByKey ( txKey [ TxKeySize ] byte , removeFromCache bool ) {
if e , ok := mem . txsMap . Load ( txKey ) ; ok {
memTx := e . ( * clist . CElement ) . Value . ( * mempoolTx )
if memTx != nil {
mem . removeTx ( memTx . tx , e . ( * clist . CElement ) , removeFromCache )
}
}
}
func ( mem * CListMempool ) isFull ( txSize int ) error {
var (
memSize = mem . Size ( )
@ -593,7 +606,7 @@ func (mem *CListMempool) Update(
// Mempool after:
// 100
// https://github.com/tendermint/tendermint/issues/3322.
if e , ok := mem . txsMap . Load ( t xKey( tx ) ) ; ok {
if e , ok := mem . txsMap . Load ( T xKey( tx ) ) ; ok {
mem . removeTx ( tx , e . ( * clist . CElement ) , false )
}
}
@ -670,7 +683,7 @@ type txCache interface {
type mapTxCache struct {
mtx sync . Mutex
size int
cacheMap map [ [ sha256 . Size ] byte ] * list . Element
cacheMap map [ [ TxKey Size] byte ] * list . Element
list * list . List
}
@ -680,7 +693,7 @@ var _ txCache = (*mapTxCache)(nil)
func newMapTxCache ( cacheSize int ) * mapTxCache {
return & mapTxCache {
size : cacheSize ,
cacheMap : make ( map [ [ sha256 . Size ] byte ] * list . Element , cacheSize ) ,
cacheMap : make ( map [ [ TxKey Size] byte ] * list . Element , cacheSize ) ,
list : list . New ( ) ,
}
}
@ -688,7 +701,7 @@ func newMapTxCache(cacheSize int) *mapTxCache {
// Reset resets the cache to an empty state.
func ( cache * mapTxCache ) Reset ( ) {
cache . mtx . Lock ( )
cache . cacheMap = make ( map [ [ sha256 . Size ] byte ] * list . Element , cache . size )
cache . cacheMap = make ( map [ [ TxKey Size] byte ] * list . Element , cache . size )
cache . list . Init ( )
cache . mtx . Unlock ( )
}
@ -700,7 +713,7 @@ func (cache *mapTxCache) Push(tx types.Tx) bool {
defer cache . mtx . Unlock ( )
// Use the tx hash in the cache
txHash := t xKey( tx )
txHash := T xKey( tx )
if moved , exists := cache . cacheMap [ txHash ] ; exists {
cache . list . MoveToBack ( moved )
return false
@ -709,7 +722,7 @@ func (cache *mapTxCache) Push(tx types.Tx) bool {
if cache . list . Len ( ) >= cache . size {
popped := cache . list . Front ( )
if popped != nil {
poppedTxHash := popped . Value . ( [ sha256 . Size ] byte )
poppedTxHash := popped . Value . ( [ TxKey Size] byte )
delete ( cache . cacheMap , poppedTxHash )
cache . list . Remove ( popped )
}
@ -722,7 +735,7 @@ func (cache *mapTxCache) Push(tx types.Tx) bool {
// Remove removes the given tx from the cache.
func ( cache * mapTxCache ) Remove ( tx types . Tx ) {
cache . mtx . Lock ( )
txHash := t xKey( tx )
txHash := T xKey( tx )
popped := cache . cacheMap [ txHash ]
delete ( cache . cacheMap , txHash )
if popped != nil {
@ -742,8 +755,8 @@ func (nopTxCache) Remove(types.Tx) {}
//--------------------------------------------------------------------------------
// txKey is the fixed length array sha256 hash used as the key in maps.
func t xKey( tx types . Tx ) [ sha256 . Size ] byte {
// TxKey is the fixed length array hash used as the key in maps.
func T xKey( tx types . Tx ) [ TxKey Size] byte {
return sha256 . Sum256 ( tx )
}