From 473937e74a5cae7b8d034915cf7b6b232d11ec97 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Fri, 5 Apr 2024 10:51:37 +0200 Subject: [PATCH 01/47] feat: add tx status in mempool --- mempool/mempool.go | 6 ++++++ mempool/v1/mempool.go | 39 ++++++++++++++++++++++++++++++++++++- rpc/core/blocks.go | 11 +---------- rpc/core/txstatus.go | 38 ++++++++++++++++++++++++++++++++++++ rpc/core/types/responses.go | 5 +++-- 5 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 rpc/core/txstatus.go diff --git a/mempool/mempool.go b/mempool/mempool.go index 0f1b32d280..e5fa64bc2d 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -91,6 +91,12 @@ type Mempool interface { // trigger once every height when transactions are available. EnableTxsAvailable() + GetTxByKey(key types.TxKey) (types.Tx, bool) + + GetTxRejected(key types.TxKey) bool + + GetTxEvicted(key types.TxKey) bool + // Size returns the number of transactions in the mempool. Size() int diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index c7191fad9c..0861295c63 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -58,6 +58,10 @@ type TxMempool struct { txs *clist.CList // valid transactions (passed CheckTx) txByKey map[types.TxKey]*clist.CElement txBySender map[string]*clist.CElement // for sender != "" + evictedTxs map[types.TxKey]bool // for tracking evicted transactions + rejectedTxs map[types.TxKey]bool // for tracking rejected transactions + + traceClient *trace.Client } @@ -204,6 +208,7 @@ func (txmp *TxMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo memp if txmp.preCheck != nil { if err := txmp.preCheck(tx); err != nil { txmp.metrics.FailedTxs.With(mempool.TypeLabel, mempool.FailedPrecheck).Add(1) + txmp.rejectedTxs[tx.Key()] = true schema.WriteMempoolRejected(txmp.traceClient, err.Error()) return 0, mempool.ErrPreCheck{Reason: err} } @@ -261,6 +266,31 @@ func (txmp *TxMempool) RemoveTxByKey(txKey types.TxKey) error { return txmp.removeTxByKey(txKey) } +func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { + txmp.mtx.RLock() + defer txmp.mtx.RUnlock() + + if elt, ok := txmp.txByKey[txKey]; ok { + return elt.Value.(*WrappedTx).tx, true + } + return nil, false +} + +// figure out how to flush rejected and evicted transactions +func (txmp *TxMempool) GetTxRejected(txKey types.TxKey) bool { + txmp.mtx.RLock() + defer txmp.mtx.RUnlock() + + return txmp.rejectedTxs[txKey] +} + +func (txmp *TxMempool) GetTxEvicted(txKey types.TxKey) bool { + txmp.mtx.RLock() + defer txmp.mtx.RUnlock() + + return txmp.evictedTxs[txKey] +} + // removeTxByKey removes the specified transaction key from the mempool. // The caller must hold txmp.mtx excluxively. func (txmp *TxMempool) removeTxByKey(key types.TxKey) error { @@ -493,6 +523,9 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon ) schema.WriteMempoolRejected(txmp.traceClient, reason) + // add it to rejected transactions list + txmp.rejectedTxs[wtx.tx.Key()] = true + // Remove the invalid transaction from the cache, unless the operator has // instructed us to keep invalid transactions. if !txmp.config.KeepInvalidTxsInCache { @@ -560,6 +593,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon fmt.Sprintf("rejected valid incoming transaction; mempool is full (%X)", wtx.tx.Hash()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedNewTxFullMempool).Add(1) + txmp.evictedTxs[wtx.tx.Key()] = true return } @@ -592,7 +626,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon txmp.removeTxByElement(vic) txmp.cache.Remove(w.tx) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedExistingTxFullMempool).Add(1) - + txmp.evictedTxs[w.tx.Key()] = true // We may not need to evict all the eligible transactions. Bail out // early if we have made enough room. evictedBytes += w.Size() @@ -670,6 +704,7 @@ func (txmp *TxMempool) handleRecheckResult(tx types.Tx, checkTxRes *abci.Respons ) txmp.removeTxByElement(elt) txmp.metrics.FailedTxs.With(mempool.TypeLabel, mempool.FailedRecheck).Add(1) + txmp.rejectedTxs[wtx.tx.Key()] = true if !txmp.config.KeepInvalidTxsInCache { txmp.cache.Remove(wtx.tx) if err != nil { @@ -786,10 +821,12 @@ func (txmp *TxMempool) purgeExpiredTxs(blockHeight int64) { txmp.removeTxByElement(cur) txmp.cache.Remove(w.tx) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedTxExpiredBlocks).Add(1) + txmp.evictedTxs[w.tx.Key()] = true } else if txmp.config.TTLDuration > 0 && now.Sub(w.timestamp) > txmp.config.TTLDuration { txmp.removeTxByElement(cur) txmp.cache.Remove(w.tx) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedTxExpiredTime).Add(1) + txmp.evictedTxs[w.tx.Key()] = true } cur = next } diff --git a/rpc/core/blocks.go b/rpc/core/blocks.go index e3dd3b71de..d0b6995d65 100644 --- a/rpc/core/blocks.go +++ b/rpc/core/blocks.go @@ -178,16 +178,7 @@ func BlockByHash(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultBlock, error return &ctypes.ResultBlock{BlockID: blockMeta.BlockID, Block: block}, nil } -// TxStatus retrieves the status of a transaction given its hash. It returns a ResultTxStatus -// containing the height and index of the transaction within the block. -func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error) { - env := GetEnvironment() - txInfo := env.BlockStore.LoadTxInfo(hash) - if txInfo == nil { - return &ctypes.ResultTxStatus{}, nil - } - return &ctypes.ResultTxStatus{Height: txInfo.Height, Index: txInfo.Index}, nil -} + // Commit gets block commit at a given height. // If no height is provided, it will fetch the commit for the latest block. diff --git a/rpc/core/txstatus.go b/rpc/core/txstatus.go new file mode 100644 index 0000000000..0f65e9c50c --- /dev/null +++ b/rpc/core/txstatus.go @@ -0,0 +1,38 @@ +package core + +import ( + ctypes "github.com/cometbft/cometbft/rpc/core/types" + rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" + types "github.com/cometbft/cometbft/types" +) + +// TxStatus retrieves the status of a transaction given its hash. It returns a ResultTxStatus +// containing the height and index of the transaction within the block. +func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error) { + env := GetEnvironment() + // not committed + txKey, err := types.TxKeyFromBytes(hash) + if err != nil { + return nil, err + } + // TODO replace this with exists _, + txInMempool, _ := env.Mempool.GetTxByKey(txKey) + if txInMempool != nil { + return &ctypes.ResultTxStatus{Status: "PENDING"}, nil + } + txRejected := env.Mempool.GetTxRejected(txKey) + if txRejected { + return &ctypes.ResultTxStatus{Status: "REJECTED"}, nil + } + isEvicted := env.Mempool.GetTxEvicted(txKey) + if isEvicted { + return &ctypes.ResultTxStatus{Status: "EVICTED"}, nil + } + // committed + txInfo := env.BlockStore.LoadTxInfo(hash) + if txInfo != nil { + return &ctypes.ResultTxStatus{Height: txInfo.Height, Index: txInfo.Index, Status: "COMMITTED"}, nil + } + + return &ctypes.ResultTxStatus{Status: "UNKNOWN"}, nil +} diff --git a/rpc/core/types/responses.go b/rpc/core/types/responses.go index be30c15e7a..d465563973 100644 --- a/rpc/core/types/responses.go +++ b/rpc/core/types/responses.go @@ -62,8 +62,9 @@ type ResultCommit struct { // ResultTxStatus contains info to locate a tx in a committed block. type ResultTxStatus struct { - Height int64 `json:"height"` - Index int64 `json:"index"` + Height int64 `json:"height"` + Index int64 `json:"index"` + Status string `json:"status"` } // ABCI results from a block From 33355a01c490293b31f33d1c29950d3dccb95974 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 18 Apr 2024 18:55:27 +0200 Subject: [PATCH 02/47] refactor: LRUTxCache to take tx key instead of tx --- mempool/cache.go | 23 ++++++++++------------- mempool/v0/clist_mempool.go | 12 ++++++------ mempool/v1/mempool.go | 20 ++++++++++---------- 3 files changed, 26 insertions(+), 29 deletions(-) diff --git a/mempool/cache.go b/mempool/cache.go index 3ed2b27b14..d39c4594c8 100644 --- a/mempool/cache.go +++ b/mempool/cache.go @@ -18,14 +18,14 @@ type TxCache interface { // Push adds the given raw transaction to the cache and returns true if it was // newly added. Otherwise, it returns false. - Push(tx types.Tx) bool + Push(tx types.TxKey) bool // Remove removes the given raw transaction from the cache. - Remove(tx types.Tx) + Remove(tx types.TxKey) // Has reports whether tx is present in the cache. Checking for presence is // not treated as an access of the value. - Has(tx types.Tx) bool + Has(tx types.TxKey) bool } var _ TxCache = (*LRUTxCache)(nil) @@ -61,12 +61,10 @@ func (c *LRUTxCache) Reset() { c.list.Init() } -func (c *LRUTxCache) Push(tx types.Tx) bool { +func (c *LRUTxCache) Push(key types.TxKey) bool { c.mtx.Lock() defer c.mtx.Unlock() - key := tx.Key() - moved, ok := c.cacheMap[key] if ok { c.list.MoveToBack(moved) @@ -88,8 +86,7 @@ func (c *LRUTxCache) Push(tx types.Tx) bool { return true } -func (c *LRUTxCache) Remove(tx types.Tx) { - key := tx.Key() +func (c *LRUTxCache) Remove(key types.TxKey) { c.RemoveTxByKey(key) } @@ -105,11 +102,11 @@ func (c *LRUTxCache) RemoveTxByKey(key types.TxKey) { } } -func (c *LRUTxCache) Has(tx types.Tx) bool { +func (c *LRUTxCache) Has(key types.TxKey) bool { c.mtx.Lock() defer c.mtx.Unlock() - _, ok := c.cacheMap[tx.Key()] + _, ok := c.cacheMap[key] return ok } @@ -119,6 +116,6 @@ type NopTxCache struct{} var _ TxCache = (*NopTxCache)(nil) func (NopTxCache) Reset() {} -func (NopTxCache) Push(types.Tx) bool { return true } -func (NopTxCache) Remove(types.Tx) {} -func (NopTxCache) Has(types.Tx) bool { return false } +func (NopTxCache) Push(types.TxKey) bool { return true } +func (NopTxCache) Remove(types.TxKey) {} +func (NopTxCache) Has(types.TxKey) bool { return false } diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index e81083cac8..11bbbf7ef1 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -236,7 +236,7 @@ func (mem *CListMempool) CheckTx( return err } - if !mem.cache.Push(tx) { // if the transaction already exists in the cache + if !mem.cache.Push(tx.Key()) { // if the transaction already exists in the cache // Record a new sender for a tx we've already seen. // 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), @@ -336,7 +336,7 @@ func (mem *CListMempool) removeTx(tx types.Tx, elem *clist.CElement, removeFromC atomic.AddInt64(&mem.txsBytes, int64(-len(tx))) if removeFromCache { - mem.cache.Remove(tx) + mem.cache.Remove(tx.Key()) } } @@ -392,7 +392,7 @@ func (mem *CListMempool) resCbFirstTime( // limits. if err := mem.isFull(len(tx)); err != nil { // remove from cache (mempool might have a space later) - mem.cache.Remove(tx) + mem.cache.Remove(types.Tx(tx).Key()) mem.logger.Error(err.Error()) return } @@ -425,7 +425,7 @@ func (mem *CListMempool) resCbFirstTime( if !mem.config.KeepInvalidTxsInCache { // remove from cache (it might be good later) - mem.cache.Remove(tx) + mem.cache.Remove(types.Tx(tx).Key()) } } @@ -604,10 +604,10 @@ func (mem *CListMempool) Update( for i, tx := range txs { if deliverTxResponses[i].Code == abci.CodeTypeOK { // Add valid committed tx to the cache (if missing). - _ = mem.cache.Push(tx) + _ = mem.cache.Push(tx.Key()) } else if !mem.config.KeepInvalidTxsInCache { // Allow invalid transactions to be resubmitted. - mem.cache.Remove(tx) + mem.cache.Remove(tx.Key()) } // Remove committed tx from the mempool. diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index 0861295c63..ebf1bb35e2 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -222,7 +222,7 @@ func (txmp *TxMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo memp txKey := tx.Key() // Check for the transaction in the cache. - if !txmp.cache.Push(tx) { + if !txmp.cache.Push(tx.Key()) { // If the cached transaction is also in the pool, record its sender. if elt, ok := txmp.txByKey[txKey]; ok { txmp.metrics.AlreadySeenTxs.Add(1) @@ -240,7 +240,7 @@ func (txmp *TxMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo memp // Invoke an ABCI CheckTx for this transaction. rsp, err := txmp.proxyAppConn.CheckTxSync(abci.RequestCheckTx{Tx: tx}) if err != nil { - txmp.cache.Remove(tx) + txmp.cache.Remove(tx.Key()) return err } wtx := &WrappedTx{ @@ -453,9 +453,9 @@ func (txmp *TxMempool) Update( // already present). Transactions that failed to commit are removed from // the cache unless the operator has explicitly requested we keep them. if deliverTxResponses[i].Code == abci.CodeTypeOK { - _ = txmp.cache.Push(tx) + _ = txmp.cache.Push(tx.Key()) } else if !txmp.config.KeepInvalidTxsInCache { - txmp.cache.Remove(tx) + txmp.cache.Remove(tx.Key()) } // Regardless of success, remove the transaction from the mempool. @@ -529,7 +529,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon // Remove the invalid transaction from the cache, unless the operator has // instructed us to keep invalid transactions. if !txmp.config.KeepInvalidTxsInCache { - txmp.cache.Remove(wtx.tx) + txmp.cache.Remove(wtx.tx.Key()) } // If there was a post-check error, record its text in the result for @@ -583,7 +583,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon // those candidates is not enough to make room for the new transaction, // drop the new one. if len(victims) == 0 || victimBytes < wtx.Size() { - txmp.cache.Remove(wtx.tx) + txmp.cache.Remove(wtx.tx.Key()) txmp.logger.Error( "rejected valid incoming transaction; mempool is full", "tx", fmt.Sprintf("%X", wtx.tx.Hash()), @@ -624,7 +624,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon "old_priority", w.priority, ) txmp.removeTxByElement(vic) - txmp.cache.Remove(w.tx) + txmp.cache.Remove(w.tx.Key()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedExistingTxFullMempool).Add(1) txmp.evictedTxs[w.tx.Key()] = true // We may not need to evict all the eligible transactions. Bail out @@ -706,7 +706,7 @@ func (txmp *TxMempool) handleRecheckResult(tx types.Tx, checkTxRes *abci.Respons txmp.metrics.FailedTxs.With(mempool.TypeLabel, mempool.FailedRecheck).Add(1) txmp.rejectedTxs[wtx.tx.Key()] = true if !txmp.config.KeepInvalidTxsInCache { - txmp.cache.Remove(wtx.tx) + txmp.cache.Remove(wtx.tx.Key()) if err != nil { schema.WriteMempoolRejected(txmp.traceClient, err.Error()) } @@ -819,12 +819,12 @@ func (txmp *TxMempool) purgeExpiredTxs(blockHeight int64) { w := cur.Value.(*WrappedTx) if txmp.config.TTLNumBlocks > 0 && (blockHeight-w.height) > txmp.config.TTLNumBlocks { txmp.removeTxByElement(cur) - txmp.cache.Remove(w.tx) + txmp.cache.Remove(w.tx.Key()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedTxExpiredBlocks).Add(1) txmp.evictedTxs[w.tx.Key()] = true } else if txmp.config.TTLDuration > 0 && now.Sub(w.timestamp) > txmp.config.TTLDuration { txmp.removeTxByElement(cur) - txmp.cache.Remove(w.tx) + txmp.cache.Remove(w.tx.Key()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedTxExpiredTime).Add(1) txmp.evictedTxs[w.tx.Key()] = true } From d4a86e32883eab907e15acc07a58d46d68632b80 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Fri, 19 Apr 2024 16:51:50 +0200 Subject: [PATCH 03/47] feat: add the same methods to other mempools to build (wip) --- consensus/replay_stubs.go | 7 +++++-- mempool/cat/pool.go | 15 +++++++++++++++ mempool/v0/clist_mempool.go | 18 ++++++++++++++++++ mempool/v1/mempool.go | 24 +++++++++++++----------- 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/consensus/replay_stubs.go b/consensus/replay_stubs.go index a39fbbc989..383e2c3990 100644 --- a/consensus/replay_stubs.go +++ b/consensus/replay_stubs.go @@ -47,8 +47,11 @@ func (emptyMempool) TxsBytes() int64 { return 0 } func (emptyMempool) TxsFront() *clist.CElement { return nil } func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } -func (emptyMempool) InitWAL() error { return nil } -func (emptyMempool) CloseWAL() {} +func (emptyMempool) InitWAL() error { return nil } +func (emptyMempool) CloseWAL() {} +func (emptyMempool) GetTxByKey(types.TxKey) (types.Tx, bool) { return nil, false} +func (emptyMempool) GetTxRejected(types.TxKey) bool { return false } +func (emptyMempool) GetTxEvicted(types.TxKey) (bool) { return false } //----------------------------------------------------------------------------- // mockProxyApp uses ABCIResponses to give the right results. diff --git a/mempool/cat/pool.go b/mempool/cat/pool.go index a1a86e1ef4..2a865e2c27 100644 --- a/mempool/cat/pool.go +++ b/mempool/cat/pool.go @@ -141,6 +141,21 @@ func (txmp *TxPool) Size() int { return txmp.store.size() } // mempool. It is thread-safe. func (txmp *TxPool) SizeBytes() int64 { return txmp.store.totalBytes() } +func (txmp *TxPool) GetTxByKey(key types.TxKey) (types.Tx, bool) { + // e, ok := me.Load(key) + tx := txmp.store.get(key) + return tx.tx, true +} + +func (mem *TxPool) GetTxEvicted(key types.TxKey) bool { + return false +} + +// TODO: Investigate this since i think +func (mem *TxPool) GetTxRejected(key types.TxKey) bool { + return false +} + // FlushAppConn executes FlushSync on the mempool's proxyAppConn. // // The caller must hold an exclusive mempool lock (by calling txmp.Lock) before diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index 11bbbf7ef1..3c71df1593 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -183,6 +183,24 @@ func (mem *CListMempool) TxsFront() *clist.CElement { return mem.txs.Front() } +func (mem *CListMempool) GetTxByKey(key types.TxKey) (types.Tx, bool) { + e, ok := mem.txsMap.Load(key) + memTx := e.(*clist.CElement).Value.(*mempoolTx) + + if !ok { + return nil, false + } + return memTx.tx, true +} + +func (mem *CListMempool) GetTxEvicted(key types.TxKey) bool { + return false +} + +func (mem *CListMempool) GetTxRejected(key types.TxKey) bool { + return false +} + // TxsWaitChan returns a channel to wait on transactions. It will be closed // once the mempool is not empty (ie. the internal `mem.txs` has at least one // element) diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index ebf1bb35e2..4a43da9189 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -58,8 +58,8 @@ type TxMempool struct { txs *clist.CList // valid transactions (passed CheckTx) txByKey map[types.TxKey]*clist.CElement txBySender map[string]*clist.CElement // for sender != "" - evictedTxs map[types.TxKey]bool // for tracking evicted transactions - rejectedTxs map[types.TxKey]bool // for tracking rejected transactions + evictedTxs mempool.TxCache // for tracking evicted transactions + rejectedTxs mempool.TxCache // for tracking rejected transactions @@ -91,6 +91,8 @@ func NewTxMempool( } if cfg.CacheSize > 0 { txmp.cache = mempool.NewLRUTxCache(cfg.CacheSize) + txmp.rejectedTxs = mempool.NewLRUTxCache(cfg.CacheSize) + txmp.evictedTxs = mempool.NewLRUTxCache(cfg.CacheSize) } for _, opt := range options { @@ -208,7 +210,7 @@ func (txmp *TxMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo memp if txmp.preCheck != nil { if err := txmp.preCheck(tx); err != nil { txmp.metrics.FailedTxs.With(mempool.TypeLabel, mempool.FailedPrecheck).Add(1) - txmp.rejectedTxs[tx.Key()] = true + txmp.rejectedTxs.Push(tx.Key()) schema.WriteMempoolRejected(txmp.traceClient, err.Error()) return 0, mempool.ErrPreCheck{Reason: err} } @@ -281,14 +283,14 @@ func (txmp *TxMempool) GetTxRejected(txKey types.TxKey) bool { txmp.mtx.RLock() defer txmp.mtx.RUnlock() - return txmp.rejectedTxs[txKey] + return txmp.rejectedTxs.Has(txKey) } func (txmp *TxMempool) GetTxEvicted(txKey types.TxKey) bool { txmp.mtx.RLock() defer txmp.mtx.RUnlock() - return txmp.evictedTxs[txKey] + return txmp.evictedTxs.Has(txKey) } // removeTxByKey removes the specified transaction key from the mempool. @@ -524,7 +526,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon schema.WriteMempoolRejected(txmp.traceClient, reason) // add it to rejected transactions list - txmp.rejectedTxs[wtx.tx.Key()] = true + txmp.rejectedTxs.Push(wtx.tx.Key()) // Remove the invalid transaction from the cache, unless the operator has // instructed us to keep invalid transactions. @@ -593,7 +595,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon fmt.Sprintf("rejected valid incoming transaction; mempool is full (%X)", wtx.tx.Hash()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedNewTxFullMempool).Add(1) - txmp.evictedTxs[wtx.tx.Key()] = true + txmp.evictedTxs.Push(wtx.tx.Key()) return } @@ -626,7 +628,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon txmp.removeTxByElement(vic) txmp.cache.Remove(w.tx.Key()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedExistingTxFullMempool).Add(1) - txmp.evictedTxs[w.tx.Key()] = true + txmp.evictedTxs.Push(w.tx.Key()) // We may not need to evict all the eligible transactions. Bail out // early if we have made enough room. evictedBytes += w.Size() @@ -704,7 +706,7 @@ func (txmp *TxMempool) handleRecheckResult(tx types.Tx, checkTxRes *abci.Respons ) txmp.removeTxByElement(elt) txmp.metrics.FailedTxs.With(mempool.TypeLabel, mempool.FailedRecheck).Add(1) - txmp.rejectedTxs[wtx.tx.Key()] = true + txmp.rejectedTxs.Push(wtx.tx.Key()) if !txmp.config.KeepInvalidTxsInCache { txmp.cache.Remove(wtx.tx.Key()) if err != nil { @@ -821,12 +823,12 @@ func (txmp *TxMempool) purgeExpiredTxs(blockHeight int64) { txmp.removeTxByElement(cur) txmp.cache.Remove(w.tx.Key()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedTxExpiredBlocks).Add(1) - txmp.evictedTxs[w.tx.Key()] = true + txmp.evictedTxs.Push(w.tx.Key()) } else if txmp.config.TTLDuration > 0 && now.Sub(w.timestamp) > txmp.config.TTLDuration { txmp.removeTxByElement(cur) txmp.cache.Remove(w.tx.Key()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedTxExpiredTime).Add(1) - txmp.evictedTxs[w.tx.Key()] = true + txmp.evictedTxs.Push(w.tx.Key()) } cur = next } From cd2859394a9da8acc00d30954036ee3e083db6d4 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Fri, 17 May 2024 11:05:51 +0200 Subject: [PATCH 04/47] chore: fix go sum entry error --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index 0aaee895eb..ff36496557 100644 --- a/go.sum +++ b/go.sum @@ -1452,8 +1452,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From aff84b822233ec12a229c569ff4ef28ef6156724 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 6 Jun 2024 00:27:41 +0200 Subject: [PATCH 05/47] (wip): remove rejected, evicted txs works --- consensus/replay_stubs.go | 9 +++--- mempool/cache.go | 2 +- mempool/cache_bench_test.go | 8 +++-- mempool/cache_test.go | 4 +-- mempool/cat/pool.go | 26 ++++++++-------- mempool/cat/pool_test.go | 16 ++++++++-- mempool/cat/store.go | 5 +++- mempool/cat/store_test.go | 4 +-- mempool/mempool.go | 4 +-- mempool/mock/mempool.go | 3 ++ mempool/v0/clist_mempool.go | 10 ++----- mempool/v0/clist_mempool_test.go | 2 +- mempool/v1/mempool.go | 36 ++++++---------------- mempool/v1/mempool_test.go | 40 ++++++++++++++++++++----- rpc/core/blocks.go | 2 -- rpc/core/txstatus.go | 11 ++----- state/mocks/block_store.go | 2 +- test/maverick/consensus/replay_stubs.go | 3 ++ 18 files changed, 103 insertions(+), 84 deletions(-) diff --git a/consensus/replay_stubs.go b/consensus/replay_stubs.go index 383e2c3990..6de28b455c 100644 --- a/consensus/replay_stubs.go +++ b/consensus/replay_stubs.go @@ -47,11 +47,10 @@ func (emptyMempool) TxsBytes() int64 { return 0 } func (emptyMempool) TxsFront() *clist.CElement { return nil } func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } -func (emptyMempool) InitWAL() error { return nil } -func (emptyMempool) CloseWAL() {} -func (emptyMempool) GetTxByKey(types.TxKey) (types.Tx, bool) { return nil, false} -func (emptyMempool) GetTxRejected(types.TxKey) bool { return false } -func (emptyMempool) GetTxEvicted(types.TxKey) (bool) { return false } +func (emptyMempool) InitWAL() error { return nil } +func (emptyMempool) CloseWAL() {} +func (emptyMempool) GetTxByKey(types.TxKey) types.Tx { return nil } +func (emptyMempool) GetTxEvicted(types.TxKey) bool { return false } //----------------------------------------------------------------------------- // mockProxyApp uses ABCIResponses to give the right results. diff --git a/mempool/cache.go b/mempool/cache.go index d39c4594c8..41e8275791 100644 --- a/mempool/cache.go +++ b/mempool/cache.go @@ -115,7 +115,7 @@ type NopTxCache struct{} var _ TxCache = (*NopTxCache)(nil) -func (NopTxCache) Reset() {} +func (NopTxCache) Reset() {} func (NopTxCache) Push(types.TxKey) bool { return true } func (NopTxCache) Remove(types.TxKey) {} func (NopTxCache) Has(types.TxKey) bool { return false } diff --git a/mempool/cache_bench_test.go b/mempool/cache_bench_test.go index 1c26999d10..4b235092ba 100644 --- a/mempool/cache_bench_test.go +++ b/mempool/cache_bench_test.go @@ -3,6 +3,8 @@ package mempool import ( "encoding/binary" "testing" + + "github.com/cometbft/cometbft/types" ) func BenchmarkCacheInsertTime(b *testing.B) { @@ -17,7 +19,7 @@ func BenchmarkCacheInsertTime(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - cache.Push(txs[i]) + cache.Push(types.Tx(txs[i]).Key()) } } @@ -30,12 +32,12 @@ func BenchmarkCacheRemoveTime(b *testing.B) { for i := 0; i < b.N; i++ { txs[i] = make([]byte, 8) binary.BigEndian.PutUint64(txs[i], uint64(i)) - cache.Push(txs[i]) + cache.Push(types.Tx(txs[i]).Key()) } b.ResetTimer() for i := 0; i < b.N; i++ { - cache.Remove(txs[i]) + cache.Remove(types.Tx(txs[i]).Key()) } } diff --git a/mempool/cache_test.go b/mempool/cache_test.go index b69fb40b7c..0cc7e09d8c 100644 --- a/mempool/cache_test.go +++ b/mempool/cache_test.go @@ -21,7 +21,7 @@ func populate(cache TxCache, numTxs int) ([][]byte, error) { } txs[i] = txBytes - cache.Push(txBytes) + cache.Push(types.Tx(txBytes).Key()) } return txs, nil @@ -37,7 +37,7 @@ func TestCacheRemove(t *testing.T) { require.Equal(t, numTxs, cache.list.Len()) for i := 0; i < numTxs; i++ { - cache.Remove(txs[i]) + cache.Remove(types.Tx(txs[i]).Key()) // make sure its removed from both the map and the linked list require.Equal(t, numTxs-(i+1), len(cache.cacheMap)) require.Equal(t, numTxs-(i+1), cache.list.Len()) diff --git a/mempool/cat/pool.go b/mempool/cat/pool.go index 2a865e2c27..fcc1bab70a 100644 --- a/mempool/cat/pool.go +++ b/mempool/cat/pool.go @@ -64,6 +64,8 @@ type TxPool struct { // Thread-safe cache of rejected transactions for quick look-up rejectedTxCache *LRUTxCache + // Thread-safe cache of evicted transactions for quick look-up + evictedTxCache *LRUTxCache // Thread-safe list of transactions peers have seen that we have not yet seen seenByPeersSet *SeenTxSet @@ -92,6 +94,7 @@ func NewTxPool( proxyAppConn: proxyAppConn, metrics: mempool.NopMetrics(), rejectedTxCache: NewLRUTxCache(cfg.CacheSize), + evictedTxCache: NewLRUTxCache(cfg.CacheSize), seenByPeersSet: NewSeenTxSet(), height: height, preCheckFn: func(_ types.Tx) error { return nil }, @@ -141,19 +144,16 @@ func (txmp *TxPool) Size() int { return txmp.store.size() } // mempool. It is thread-safe. func (txmp *TxPool) SizeBytes() int64 { return txmp.store.totalBytes() } -func (txmp *TxPool) GetTxByKey(key types.TxKey) (types.Tx, bool) { +func (txmp *TxPool) GetTxByKey(key types.TxKey) types.Tx { // e, ok := me.Load(key) tx := txmp.store.get(key) - return tx.tx, true + return tx.tx } -func (mem *TxPool) GetTxEvicted(key types.TxKey) bool { - return false -} - -// TODO: Investigate this since i think -func (mem *TxPool) GetTxRejected(key types.TxKey) bool { - return false +// IsEvicted returns true is the transaction was recently evicted and is +// currently within the cache +func (txmp *TxPool) GetTxEvicted(txKey types.TxKey) bool { + return txmp.evictedTxCache.Has(txKey) } // FlushAppConn executes FlushSync on the mempool's proxyAppConn. @@ -212,7 +212,7 @@ func (txmp *TxPool) CheckToPurgeExpiredTxs() { expirationAge := time.Now().Add(-txmp.config.TTLDuration) // a height of 0 means no transactions will be removed because of height // (in other words, no transaction has a height less than 0) - numExpired := txmp.store.purgeExpiredTxs(0, expirationAge) + numExpired := txmp.store.purgeExpiredTxs(0, expirationAge, txmp.evictedTxCache) txmp.metrics.EvictedTxs.Add(float64(numExpired)) txmp.lastPurgeTime = time.Now() } @@ -374,7 +374,6 @@ func (txmp *TxPool) RemoveTxByKey(txKey types.TxKey) error { } func (txmp *TxPool) removeTxByKey(txKey types.TxKey) { - txmp.rejectedTxCache.Push(txKey) _ = txmp.store.remove(txKey) txmp.seenByPeersSet.RemoveKey(txKey) } @@ -388,6 +387,7 @@ func (txmp *TxPool) Flush() { txmp.store.reset() txmp.seenByPeersSet.Reset() txmp.rejectedTxCache.Reset() + txmp.evictedTxCache.Reset() txmp.metrics.EvictedTxs.Add(float64(size)) txmp.broadcastMtx.Lock() defer txmp.broadcastMtx.Unlock() @@ -552,6 +552,7 @@ func (txmp *TxPool) addNewTransaction(wtx *wrappedTx, checkTxRes *abci.ResponseC // drop the new one. if len(victims) == 0 || victimBytes < wtx.size() { txmp.metrics.EvictedTxs.Add(1) + txmp.evictedTxCache.Push(wtx.key) checkTxRes.MempoolError = fmt.Sprintf("rejected valid incoming transaction; mempool is full (%X)", wtx.key) return fmt.Errorf("rejected valid incoming transaction; mempool is full (%X). Size: (%d:%d)", @@ -606,6 +607,7 @@ func (txmp *TxPool) addNewTransaction(wtx *wrappedTx, checkTxRes *abci.ResponseC func (txmp *TxPool) evictTx(wtx *wrappedTx) { txmp.store.remove(wtx.key) + txmp.evictedTxCache.Push(wtx.key) txmp.metrics.EvictedTxs.Add(1) txmp.logger.Debug( "evicted valid existing transaction; mempool full", @@ -735,7 +737,7 @@ func (txmp *TxPool) purgeExpiredTxs(blockHeight int64) { expirationAge = time.Time{} } - numExpired := txmp.store.purgeExpiredTxs(expirationHeight, expirationAge) + numExpired := txmp.store.purgeExpiredTxs(expirationHeight, expirationAge, txmp.evictedTxCache) txmp.metrics.EvictedTxs.Add(float64(numExpired)) // purge old evicted and seen transactions diff --git a/mempool/cat/pool_test.go b/mempool/cat/pool_test.go index ec67ab907a..82ab10415a 100644 --- a/mempool/cat/pool_test.go +++ b/mempool/cat/pool_test.go @@ -100,7 +100,6 @@ func setup(t testing.TB, cacheSize int, options ...TxPoolOption) *TxPool { os.RemoveAll(cfg.RootDir) require.NoError(t, appConnMem.Stop()) }) - return NewTxPool(log.TestingLogger().With("test", t.Name()), cfg, appConnMem, 1, options...) } @@ -244,6 +243,7 @@ func TestTxPool_Eviction(t *testing.T) { mustCheckTx(t, txmp, "key1=0000=25") require.True(t, txExists("key1=0000=25")) require.False(t, txExists(bigTx)) + require.True(t, txmp.GetTxEvicted(types.Tx(bigTx).Key())) require.Equal(t, int64(len("key1=0000=25")), txmp.SizeBytes()) // Now fill up the rest of the slots with other transactions. @@ -257,23 +257,27 @@ func TestTxPool_Eviction(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "mempool is full") require.False(t, txExists("key6=0005=1")) + require.True(t, txmp.GetTxEvicted(types.Tx("key6=0005=1").Key())) // A new transaction with higher priority should evict key5, which is the // newest of the two transactions with lowest priority. mustCheckTx(t, txmp, "key7=0006=7") require.True(t, txExists("key7=0006=7")) // new transaction added require.False(t, txExists("key5=0004=3")) // newest low-priority tx evicted - require.True(t, txExists("key4=0003=3")) // older low-priority tx retained + require.True(t, txmp.GetTxEvicted(types.Tx("key5=0004=3").Key())) + require.True(t, txExists("key4=0003=3")) // older low-priority tx retained // Another new transaction evicts the other low-priority element. mustCheckTx(t, txmp, "key8=0007=20") require.True(t, txExists("key8=0007=20")) require.False(t, txExists("key4=0003=3")) + require.True(t, txmp.GetTxEvicted(types.Tx("key4=0003=3").Key())) // Now the lowest-priority tx is 5, so that should be the next to go. mustCheckTx(t, txmp, "key9=0008=9") require.True(t, txExists("key9=0008=9")) require.False(t, txExists("key2=0001=5")) + require.True(t, txmp.GetTxEvicted(types.Tx("key2=0001=5").Key())) // Add a transaction that requires eviction of multiple lower-priority // entries, in order to fit the size of the element. @@ -282,8 +286,11 @@ func TestTxPool_Eviction(t *testing.T) { require.True(t, txExists("key8=0007=20")) require.True(t, txExists("key10=0123456789abcdef=11")) require.False(t, txExists("key3=0002=10")) + require.True(t, txmp.GetTxEvicted(types.Tx("key3=0002=10").Key())) require.False(t, txExists("key9=0008=9")) + require.True(t, txmp.GetTxEvicted(types.Tx("key9=0008=9").Key())) require.False(t, txExists("key7=0006=7")) + require.True(t, txmp.GetTxEvicted(types.Tx("key7=0006=7").Key())) // Free up some space so we can add back previously evicted txs err = txmp.Update(1, types.Txs{types.Tx("key10=0123456789abcdef=11")}, []*abci.ResponseDeliverTx{{Code: abci.CodeTypeOK}}, nil, nil) @@ -296,6 +303,7 @@ func TestTxPool_Eviction(t *testing.T) { // space for the previously evicted tx require.NoError(t, txmp.RemoveTxByKey(types.Tx("key8=0007=20").Key())) require.False(t, txExists("key8=0007=20")) + require.False(t, txmp.GetTxEvicted(types.Tx("key8=0007=20").Key())) } func TestTxPool_Flush(t *testing.T) { @@ -567,6 +575,10 @@ func TestTxPool_ExpiredTxs_Timestamp(t *testing.T) { // All the transactions in the original set should have been purged. for _, tx := range added1 { + // Check that it was added to the evictedTxCache store + evicted := txmp.GetTxEvicted(tx.tx.Key()) + require.True(t, evicted) + if txmp.store.has(tx.tx.Key()) { t.Errorf("Transaction %X should have been purged for TTL", tx.tx.Key()) } diff --git a/mempool/cat/store.go b/mempool/cat/store.go index 8972186797..5638f5ce9d 100644 --- a/mempool/cat/store.go +++ b/mempool/cat/store.go @@ -142,7 +142,7 @@ func (s *store) getTxsBelowPriority(priority int64) ([]*wrappedTx, int64) { // purgeExpiredTxs removes all transactions that are older than the given height // and time. Returns the amount of transactions that were removed -func (s *store) purgeExpiredTxs(expirationHeight int64, expirationAge time.Time) int { +func (s *store) purgeExpiredTxs(expirationHeight int64, expirationAge time.Time, evictedTxCache *LRUTxCache) int { s.mtx.Lock() defer s.mtx.Unlock() counter := 0 @@ -150,6 +150,9 @@ func (s *store) purgeExpiredTxs(expirationHeight int64, expirationAge time.Time) if tx.height < expirationHeight || tx.timestamp.Before(expirationAge) { s.bytes -= tx.size() delete(s.txs, key) + if evictedTxCache != nil { + evictedTxCache.Push(key) + } counter++ } } diff --git a/mempool/cat/store_test.go b/mempool/cat/store_test.go index 7813eddba6..75ea3f9c45 100644 --- a/mempool/cat/store_test.go +++ b/mempool/cat/store_test.go @@ -173,7 +173,7 @@ func TestStoreExpiredTxs(t *testing.T) { } // half of them should get purged - store.purgeExpiredTxs(int64(numTxs/2), time.Time{}) + store.purgeExpiredTxs(int64(numTxs/2), time.Time{}, nil) remainingTxs := store.getAllTxs() require.Equal(t, numTxs/2, len(remainingTxs)) @@ -181,6 +181,6 @@ func TestStoreExpiredTxs(t *testing.T) { require.GreaterOrEqual(t, tx.height, int64(numTxs/2)) } - store.purgeExpiredTxs(int64(0), time.Now().Add(time.Second)) + store.purgeExpiredTxs(int64(0), time.Now().Add(time.Second), nil) require.Empty(t, store.getAllTxs()) } diff --git a/mempool/mempool.go b/mempool/mempool.go index e5fa64bc2d..c1a4019664 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -91,9 +91,7 @@ type Mempool interface { // trigger once every height when transactions are available. EnableTxsAvailable() - GetTxByKey(key types.TxKey) (types.Tx, bool) - - GetTxRejected(key types.TxKey) bool + GetTxByKey(key types.TxKey) types.Tx GetTxEvicted(key types.TxKey) bool diff --git a/mempool/mock/mempool.go b/mempool/mock/mempool.go index 986c28ffca..29cfba6c60 100644 --- a/mempool/mock/mempool.go +++ b/mempool/mock/mempool.go @@ -36,6 +36,9 @@ func (Mempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) } func (Mempool) EnableTxsAvailable() {} func (Mempool) SizeBytes() int64 { return 0 } +func (Mempool) GetTxByKey(txKey types.TxKey) types.Tx { return nil } +func (Mempool) GetTxEvicted(txKey types.TxKey) bool { return false } + func (Mempool) TxsFront() *clist.CElement { return nil } func (Mempool) TxsWaitChan() <-chan struct{} { return nil } diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index 3c71df1593..e9614ef79d 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -183,24 +183,20 @@ func (mem *CListMempool) TxsFront() *clist.CElement { return mem.txs.Front() } -func (mem *CListMempool) GetTxByKey(key types.TxKey) (types.Tx, bool) { +func (mem *CListMempool) GetTxByKey(key types.TxKey) types.Tx { e, ok := mem.txsMap.Load(key) memTx := e.(*clist.CElement).Value.(*mempoolTx) if !ok { - return nil, false + return nil } - return memTx.tx, true + return memTx.tx } func (mem *CListMempool) GetTxEvicted(key types.TxKey) bool { return false } -func (mem *CListMempool) GetTxRejected(key types.TxKey) bool { - return false -} - // TxsWaitChan returns a channel to wait on transactions. It will be closed // once the mempool is not empty (ie. the internal `mem.txs` has at least one // element) diff --git a/mempool/v0/clist_mempool_test.go b/mempool/v0/clist_mempool_test.go index 0c303714c9..58f3fc2acb 100644 --- a/mempool/v0/clist_mempool_test.go +++ b/mempool/v0/clist_mempool_test.go @@ -342,7 +342,7 @@ func TestMempool_KeepInvalidTxsInCache(t *testing.T) { binary.BigEndian.PutUint64(a, 0) // remove a from the cache to test (2) - mp.cache.Remove(a) + mp.cache.Remove(types.Tx(a).Key()) err := mp.CheckTx(a, nil, mempool.TxInfo{}) require.NoError(t, err) diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index 4a43da9189..90f3284c0e 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -58,10 +58,7 @@ type TxMempool struct { txs *clist.CList // valid transactions (passed CheckTx) txByKey map[types.TxKey]*clist.CElement txBySender map[string]*clist.CElement // for sender != "" - evictedTxs mempool.TxCache // for tracking evicted transactions - rejectedTxs mempool.TxCache // for tracking rejected transactions - - + evictedTxs mempool.TxCache // for tracking evicted transactions traceClient *trace.Client } @@ -91,7 +88,6 @@ func NewTxMempool( } if cfg.CacheSize > 0 { txmp.cache = mempool.NewLRUTxCache(cfg.CacheSize) - txmp.rejectedTxs = mempool.NewLRUTxCache(cfg.CacheSize) txmp.evictedTxs = mempool.NewLRUTxCache(cfg.CacheSize) } @@ -210,7 +206,6 @@ func (txmp *TxMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo memp if txmp.preCheck != nil { if err := txmp.preCheck(tx); err != nil { txmp.metrics.FailedTxs.With(mempool.TypeLabel, mempool.FailedPrecheck).Add(1) - txmp.rejectedTxs.Push(tx.Key()) schema.WriteMempoolRejected(txmp.traceClient, err.Error()) return 0, mempool.ErrPreCheck{Reason: err} } @@ -268,28 +263,17 @@ func (txmp *TxMempool) RemoveTxByKey(txKey types.TxKey) error { return txmp.removeTxByKey(txKey) } -func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { +func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) types.Tx { txmp.mtx.RLock() defer txmp.mtx.RUnlock() if elt, ok := txmp.txByKey[txKey]; ok { - return elt.Value.(*WrappedTx).tx, true + return elt.Value.(*WrappedTx).tx } - return nil, false -} - -// figure out how to flush rejected and evicted transactions -func (txmp *TxMempool) GetTxRejected(txKey types.TxKey) bool { - txmp.mtx.RLock() - defer txmp.mtx.RUnlock() - - return txmp.rejectedTxs.Has(txKey) + return nil } func (txmp *TxMempool) GetTxEvicted(txKey types.TxKey) bool { - txmp.mtx.RLock() - defer txmp.mtx.RUnlock() - return txmp.evictedTxs.Has(txKey) } @@ -525,9 +509,6 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon ) schema.WriteMempoolRejected(txmp.traceClient, reason) - // add it to rejected transactions list - txmp.rejectedTxs.Push(wtx.tx.Key()) - // Remove the invalid transaction from the cache, unless the operator has // instructed us to keep invalid transactions. if !txmp.config.KeepInvalidTxsInCache { @@ -587,14 +568,15 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon if len(victims) == 0 || victimBytes < wtx.Size() { txmp.cache.Remove(wtx.tx.Key()) txmp.logger.Error( - "rejected valid incoming transaction; mempool is full", + "evicted valid incoming transaction; mempool is full", "tx", fmt.Sprintf("%X", wtx.tx.Hash()), "err", err.Error(), ) checkTxRes.MempoolError = - fmt.Sprintf("rejected valid incoming transaction; mempool is full (%X)", + fmt.Sprintf("evicted valid incoming transaction; mempool is full (%X)", wtx.tx.Hash()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedNewTxFullMempool).Add(1) + // Add it to evicted transactions cache txmp.evictedTxs.Push(wtx.tx.Key()) return } @@ -628,6 +610,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon txmp.removeTxByElement(vic) txmp.cache.Remove(w.tx.Key()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedExistingTxFullMempool).Add(1) + // Add it to evicted transactions cache txmp.evictedTxs.Push(w.tx.Key()) // We may not need to evict all the eligible transactions. Bail out // early if we have made enough room. @@ -706,7 +689,6 @@ func (txmp *TxMempool) handleRecheckResult(tx types.Tx, checkTxRes *abci.Respons ) txmp.removeTxByElement(elt) txmp.metrics.FailedTxs.With(mempool.TypeLabel, mempool.FailedRecheck).Add(1) - txmp.rejectedTxs.Push(wtx.tx.Key()) if !txmp.config.KeepInvalidTxsInCache { txmp.cache.Remove(wtx.tx.Key()) if err != nil { @@ -827,8 +809,8 @@ func (txmp *TxMempool) purgeExpiredTxs(blockHeight int64) { } else if txmp.config.TTLDuration > 0 && now.Sub(w.timestamp) > txmp.config.TTLDuration { txmp.removeTxByElement(cur) txmp.cache.Remove(w.tx.Key()) - txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedTxExpiredTime).Add(1) txmp.evictedTxs.Push(w.tx.Key()) + txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedTxExpiredTime).Add(1) } cur = next } diff --git a/mempool/v1/mempool_test.go b/mempool/v1/mempool_test.go index 7623ecbc90..1b8333789b 100644 --- a/mempool/v1/mempool_test.go +++ b/mempool/v1/mempool_test.go @@ -108,6 +108,7 @@ func mustCheckTx(t *testing.T, txmp *TxMempool, spec string) { <-done } +// checkTxs func checkTxs(t *testing.T, txmp *TxMempool, numTxs int, peerID uint16) []testTx { txs := make([]testTx, numTxs) txInfo := mempool.TxInfo{SenderID: peerID} @@ -239,7 +240,9 @@ func TestTxMempool_Eviction(t *testing.T) { mustCheckTx(t, txmp, "key1=0000=25") require.True(t, txExists("key1=0000=25")) require.False(t, txExists(bigTx)) - require.False(t, txmp.cache.Has([]byte(bigTx))) + bigTxKey := types.Tx((bigTx)).Key() + require.False(t, txmp.cache.Has(bigTxKey)) + require.True(t, txmp.GetTxEvicted(bigTxKey)) // bigTx evicted require.Equal(t, int64(len("key1=0000=25")), txmp.SizeBytes()) // Now fill up the rest of the slots with other transactions. @@ -251,13 +254,15 @@ func TestTxMempool_Eviction(t *testing.T) { // A new transaction with low priority should be discarded. mustCheckTx(t, txmp, "key6=0005=1") require.False(t, txExists("key6=0005=1")) + require.True(t, txmp.GetTxEvicted(types.Tx(("key6=0005=1")).Key())) // key6 evicted // A new transaction with higher priority should evict key5, which is the // newest of the two transactions with lowest priority. mustCheckTx(t, txmp, "key7=0006=7") - require.True(t, txExists("key7=0006=7")) // new transaction added - require.False(t, txExists("key5=0004=3")) // newest low-priority tx evicted - require.True(t, txExists("key4=0003=3")) // older low-priority tx retained + require.True(t, txExists("key7=0006=7")) // new transaction added + require.False(t, txExists("key5=0004=3")) // newest low-priority tx evicted + require.True(t, txmp.GetTxEvicted(types.Tx(("key5=0004=3")).Key())) // key5 evicted + require.True(t, txExists("key4=0003=3")) // older low-priority tx retained // Another new transaction evicts the other low-priority element. mustCheckTx(t, txmp, "key8=0007=20") @@ -268,6 +273,7 @@ func TestTxMempool_Eviction(t *testing.T) { mustCheckTx(t, txmp, "key9=0008=9") require.True(t, txExists("key9=0008=9")) require.False(t, txExists("key2=0001=5")) + require.True(t, txmp.GetTxEvicted(types.Tx(("key2=0001=5")).Key())) // key2 evicted // Add a transaction that requires eviction of multiple lower-priority // entries, in order to fit the size of the element. @@ -276,8 +282,11 @@ func TestTxMempool_Eviction(t *testing.T) { require.True(t, txExists("key8=0007=20")) require.True(t, txExists("key10=0123456789abcdef=11")) require.False(t, txExists("key3=0002=10")) + require.True(t, txmp.GetTxEvicted(types.Tx(("key3=0002=10")).Key())) // key3 evicted require.False(t, txExists("key9=0008=9")) + require.True(t, txmp.GetTxEvicted(types.Tx(("key9=0008=9")).Key())) // key9 evicted require.False(t, txExists("key7=0006=7")) + require.True(t, txmp.GetTxEvicted(types.Tx(("key7=0006=7")).Key())) // key7 evicted } func TestTxMempool_Flush(t *testing.T) { @@ -431,7 +440,7 @@ func TestTxMempool_ReapMaxTxs(t *testing.T) { } func TestTxMempool_CheckTxExceedsMaxSize(t *testing.T) { - txmp := setup(t, 0) + txmp := setup(t, 1) rng := rand.New(rand.NewSource(time.Now().UnixNano())) tx := make([]byte, txmp.config.MaxTxBytes+1) @@ -580,10 +589,14 @@ func TestTxMempool_ExpiredTxs_Timestamp(t *testing.T) { // All the transactions in the original set should have been purged. for _, tx := range added1 { + // Check that they were adding to the evicted cache. + evicted := txmp.GetTxEvicted(tx.tx.Key()) + require.True(t, evicted) + if _, ok := txmp.txByKey[tx.tx.Key()]; ok { t.Errorf("Transaction %X should have been purged for TTL", tx.tx.Key()) } - if txmp.cache.Has(tx.tx) { + if txmp.cache.Has(tx.tx.Key()) { t.Errorf("Transaction %X should have been removed from the cache", tx.tx.Key()) } } @@ -596,6 +609,19 @@ func TestTxMempool_ExpiredTxs_Timestamp(t *testing.T) { } } +func TestGetTxByKey_GetsTx(t *testing.T) { + txmp := setup(t, 500) + txs := checkTxs(t, txmp, 100, 0) + + for _, tx := range txs { + txKey := tx.tx.Key() + txFromMempool := txmp.GetTxByKey(txKey) + require.Equal(t, tx.tx, txFromMempool) + exists := txmp.GetTxEvicted(txKey) + require.False(t, exists) + } +} + func TestTxMempool_ExpiredTxs_NumBlocks(t *testing.T) { txmp := setup(t, 500) txmp.height = 100 @@ -662,7 +688,7 @@ func TestTxMempool_CheckTxPostCheckError(t *testing.T) { postCheckFn := func(_ types.Tx, _ *abci.ResponseCheckTx) error { return testCase.err } - txmp := setup(t, 0, WithPostCheck(postCheckFn)) + txmp := setup(t, 1, WithPostCheck(postCheckFn)) rng := rand.New(rand.NewSource(time.Now().UnixNano())) tx := make([]byte, txmp.config.MaxTxBytes-1) _, err := rng.Read(tx) diff --git a/rpc/core/blocks.go b/rpc/core/blocks.go index d0b6995d65..c6ae1a2571 100644 --- a/rpc/core/blocks.go +++ b/rpc/core/blocks.go @@ -178,8 +178,6 @@ func BlockByHash(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultBlock, error return &ctypes.ResultBlock{BlockID: blockMeta.BlockID, Block: block}, nil } - - // Commit gets block commit at a given height. // If no height is provided, it will fetch the commit for the latest block. // More: https://docs.cometbft.com/v0.34/rpc/#/Info/commit diff --git a/rpc/core/txstatus.go b/rpc/core/txstatus.go index 0f65e9c50c..4b5902cb0f 100644 --- a/rpc/core/txstatus.go +++ b/rpc/core/txstatus.go @@ -15,24 +15,19 @@ func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error if err != nil { return nil, err } - // TODO replace this with exists _, - txInMempool, _ := env.Mempool.GetTxByKey(txKey) + txInMempool := env.Mempool.GetTxByKey(txKey) if txInMempool != nil { return &ctypes.ResultTxStatus{Status: "PENDING"}, nil } - txRejected := env.Mempool.GetTxRejected(txKey) - if txRejected { - return &ctypes.ResultTxStatus{Status: "REJECTED"}, nil - } isEvicted := env.Mempool.GetTxEvicted(txKey) if isEvicted { return &ctypes.ResultTxStatus{Status: "EVICTED"}, nil } // committed txInfo := env.BlockStore.LoadTxInfo(hash) - if txInfo != nil { + if txInfo != nil { return &ctypes.ResultTxStatus{Height: txInfo.Height, Index: txInfo.Index, Status: "COMMITTED"}, nil } - + return &ctypes.ResultTxStatus{Status: "UNKNOWN"}, nil } diff --git a/state/mocks/block_store.go b/state/mocks/block_store.go index 98f47dc320..21fe049f5f 100644 --- a/state/mocks/block_store.go +++ b/state/mocks/block_store.go @@ -3,9 +3,9 @@ package mocks import ( - mock "github.com/stretchr/testify/mock" cmtstore "github.com/cometbft/cometbft/proto/tendermint/store" types "github.com/cometbft/cometbft/types" + mock "github.com/stretchr/testify/mock" ) // BlockStore is an autogenerated mock type for the BlockStore type diff --git a/test/maverick/consensus/replay_stubs.go b/test/maverick/consensus/replay_stubs.go index d8ea335c12..f088d1dbe1 100644 --- a/test/maverick/consensus/replay_stubs.go +++ b/test/maverick/consensus/replay_stubs.go @@ -40,6 +40,9 @@ func (emptyMempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) func (emptyMempool) EnableTxsAvailable() {} func (emptyMempool) TxsBytes() int64 { return 0 } +func (emptyMempool) GetTxByKey(txKey types.TxKey) types.Tx { return nil } +func (emptyMempool) GetTxEvicted(txKey types.TxKey) bool { return false } + func (emptyMempool) TxsFront() *clist.CElement { return nil } func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } From 4039a5652c68d42a766c355a8896bea1c30144f3 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 6 Jun 2024 13:14:55 +0200 Subject: [PATCH 06/47] refactor: tests and functions to make it cleaner --- blockchain/v0/reactor_test.go | 2 +- blockchain/v1/reactor_test.go | 2 +- blockchain/v2/reactor_test.go | 4 +- consensus/replay_stubs.go | 2 +- mempool/cat/pool.go | 22 ++--- mempool/cat/reactor.go | 2 +- mempool/mempool.go | 2 +- mempool/mock/mempool.go | 31 +++++-- mempool/v0/clist_mempool.go | 6 +- mempool/v1/mempool.go | 6 +- mempool/v1/mempool_test.go | 5 +- rpc/core/blocks_test.go | 48 +++++------ rpc/core/txstatus.go | 8 +- rpc/core/txstatus_test.go | 105 ++++++++++++++++++++++++ state/execution_test.go | 14 ++-- state/validation_test.go | 6 +- test/maverick/consensus/replay_stubs.go | 2 +- 17 files changed, 193 insertions(+), 74 deletions(-) create mode 100644 rpc/core/txstatus_test.go diff --git a/blockchain/v0/reactor_test.go b/blockchain/v0/reactor_test.go index d93b61035f..2f2d05dd45 100644 --- a/blockchain/v0/reactor_test.go +++ b/blockchain/v0/reactor_test.go @@ -91,7 +91,7 @@ func newBlockchainReactor( DiscardABCIResponses: false, }) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - mock.Mempool{}, sm.EmptyEvidencePool{}) + &mock.Mempool{}, sm.EmptyEvidencePool{}) if err = stateStore.Save(state); err != nil { panic(err) } diff --git a/blockchain/v1/reactor_test.go b/blockchain/v1/reactor_test.go index b3650cbda5..5bcbe661c9 100644 --- a/blockchain/v1/reactor_test.go +++ b/blockchain/v1/reactor_test.go @@ -123,7 +123,7 @@ func newBlockchainReactor( DiscardABCIResponses: false, }) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - mock.Mempool{}, sm.EmptyEvidencePool{}) + &mock.Mempool{}, sm.EmptyEvidencePool{}) if err = stateStore.Save(state); err != nil { panic(err) } diff --git a/blockchain/v2/reactor_test.go b/blockchain/v2/reactor_test.go index 633d512f10..15f63eaef3 100644 --- a/blockchain/v2/reactor_test.go +++ b/blockchain/v2/reactor_test.go @@ -146,7 +146,7 @@ func newTestReactor(p testReactorParams) *BlockchainReactor { stateStore := sm.NewStore(db, sm.StoreOptions{ DiscardABCIResponses: false, }) - appl = sm.NewBlockExecutor(stateStore, p.logger, proxyApp.Consensus(), mock.Mempool{}, sm.EmptyEvidencePool{}) + appl = sm.NewBlockExecutor(stateStore, p.logger, proxyApp.Consensus(), &mock.Mempool{}, sm.EmptyEvidencePool{}) if err = stateStore.Save(state); err != nil { panic(err) } @@ -540,7 +540,7 @@ func newReactorStore( }, ) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - mock.Mempool{}, sm.EmptyEvidencePool{}) + &mock.Mempool{}, sm.EmptyEvidencePool{}) if err = stateStore.Save(state); err != nil { panic(err) } diff --git a/consensus/replay_stubs.go b/consensus/replay_stubs.go index 6de28b455c..a52af13bb2 100644 --- a/consensus/replay_stubs.go +++ b/consensus/replay_stubs.go @@ -49,7 +49,7 @@ func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } func (emptyMempool) InitWAL() error { return nil } func (emptyMempool) CloseWAL() {} -func (emptyMempool) GetTxByKey(types.TxKey) types.Tx { return nil } +func (emptyMempool) GetTxByKey(types.TxKey) (types.Tx, bool) { return nil, false } func (emptyMempool) GetTxEvicted(types.TxKey) bool { return false } //----------------------------------------------------------------------------- diff --git a/mempool/cat/pool.go b/mempool/cat/pool.go index fcc1bab70a..f2c7fc4905 100644 --- a/mempool/cat/pool.go +++ b/mempool/cat/pool.go @@ -144,18 +144,6 @@ func (txmp *TxPool) Size() int { return txmp.store.size() } // mempool. It is thread-safe. func (txmp *TxPool) SizeBytes() int64 { return txmp.store.totalBytes() } -func (txmp *TxPool) GetTxByKey(key types.TxKey) types.Tx { - // e, ok := me.Load(key) - tx := txmp.store.get(key) - return tx.tx -} - -// IsEvicted returns true is the transaction was recently evicted and is -// currently within the cache -func (txmp *TxPool) GetTxEvicted(txKey types.TxKey) bool { - return txmp.evictedTxCache.Has(txKey) -} - // FlushAppConn executes FlushSync on the mempool's proxyAppConn. // // The caller must hold an exclusive mempool lock (by calling txmp.Lock) before @@ -186,9 +174,9 @@ func (txmp *TxPool) Has(txKey types.TxKey) bool { return txmp.store.has(txKey) } -// Get retrieves a transaction based on the key. It returns a bool +// GetTxByKey retrieves a transaction based on the key. It returns a bool // if the transaction exists or not -func (txmp *TxPool) Get(txKey types.TxKey) (types.Tx, bool) { +func (txmp *TxPool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { wtx := txmp.store.get(txKey) if wtx != nil { return wtx.tx, true @@ -196,6 +184,12 @@ func (txmp *TxPool) Get(txKey types.TxKey) (types.Tx, bool) { return types.Tx{}, false } +// IsEvicted returns true is the transaction was recently evicted and is +// currently within the cache +func (txmp *TxPool) GetTxEvicted(txKey types.TxKey) bool { + return txmp.evictedTxCache.Has(txKey) +} + // IsRejectedTx returns true if the transaction was recently rejected and is // currently within the cache func (txmp *TxPool) IsRejectedTx(txKey types.TxKey) bool { diff --git a/mempool/cat/reactor.go b/mempool/cat/reactor.go index abfdfd56d9..4acffcf3f8 100644 --- a/mempool/cat/reactor.go +++ b/mempool/cat/reactor.go @@ -320,7 +320,7 @@ func (memR *Reactor) ReceiveEnvelope(e p2p.Envelope) { memR.Switch.StopPeerForError(e.Src, err) return } - tx, has := memR.mempool.Get(txKey) + tx, has := memR.mempool.GetTxByKey(txKey) if has && !memR.opts.ListenOnly { peerID := memR.ids.GetIDForPeer(e.Src.ID()) schema.WriteMempoolTx( diff --git a/mempool/mempool.go b/mempool/mempool.go index c1a4019664..0c8e61ff08 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -91,7 +91,7 @@ type Mempool interface { // trigger once every height when transactions are available. EnableTxsAvailable() - GetTxByKey(key types.TxKey) types.Tx + GetTxByKey(key types.TxKey) (types.Tx, bool) GetTxEvicted(key types.TxKey) bool diff --git a/mempool/mock/mempool.go b/mempool/mock/mempool.go index 29cfba6c60..d167cdc964 100644 --- a/mempool/mock/mempool.go +++ b/mempool/mock/mempool.go @@ -8,17 +8,31 @@ import ( ) // Mempool is an empty implementation of a Mempool, useful for testing. -type Mempool struct{} +type Mempool struct { + txs map[types.TxKey]types.Tx + evictedTxs map[types.TxKey]bool +} -var _ mempool.Mempool = Mempool{} +var _ mempool.Mempool = &Mempool{} func (Mempool) Lock() {} func (Mempool) Unlock() {} func (Mempool) Size() int { return 0 } -func (Mempool) CheckTx(_ types.Tx, _ func(*abci.Response), _ mempool.TxInfo) error { +func (m *Mempool) CheckTx(tx types.Tx, _ func(*abci.Response), _ mempool.TxInfo) error { + if m.txs == nil { + m.txs = make(map[types.TxKey]types.Tx) + } + if m.evictedTxs == nil { + m.evictedTxs = make(map[types.TxKey]bool) + } + m.txs[tx.Key()] = tx + return nil +} +func (m *Mempool) RemoveTxByKey(txKey types.TxKey) error { + delete(m.txs, txKey) + m.evictedTxs[txKey] = true return nil } -func (Mempool) RemoveTxByKey(txKey types.TxKey) error { return nil } func (Mempool) ReapMaxBytesMaxGas(_, _ int64) types.Txs { return types.Txs{} } func (Mempool) ReapMaxTxs(n int) types.Txs { return types.Txs{} } func (Mempool) Update( @@ -36,8 +50,13 @@ func (Mempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) } func (Mempool) EnableTxsAvailable() {} func (Mempool) SizeBytes() int64 { return 0 } -func (Mempool) GetTxByKey(txKey types.TxKey) types.Tx { return nil } -func (Mempool) GetTxEvicted(txKey types.TxKey) bool { return false } +func (m Mempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { + tx, ok := m.txs[txKey] + return tx, ok +} +func (m Mempool) GetTxEvicted(txKey types.TxKey) bool { + return m.evictedTxs[txKey] +} func (Mempool) TxsFront() *clist.CElement { return nil } func (Mempool) TxsWaitChan() <-chan struct{} { return nil } diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index e9614ef79d..bc6a26c389 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -183,14 +183,14 @@ func (mem *CListMempool) TxsFront() *clist.CElement { return mem.txs.Front() } -func (mem *CListMempool) GetTxByKey(key types.TxKey) types.Tx { +func (mem *CListMempool) GetTxByKey(key types.TxKey) (types.Tx, bool) { e, ok := mem.txsMap.Load(key) memTx := e.(*clist.CElement).Value.(*mempoolTx) if !ok { - return nil + return nil, false } - return memTx.tx + return memTx.tx, true } func (mem *CListMempool) GetTxEvicted(key types.TxKey) bool { diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index 90f3284c0e..83b3cf2d6f 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -263,14 +263,14 @@ func (txmp *TxMempool) RemoveTxByKey(txKey types.TxKey) error { return txmp.removeTxByKey(txKey) } -func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) types.Tx { +func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { txmp.mtx.RLock() defer txmp.mtx.RUnlock() if elt, ok := txmp.txByKey[txKey]; ok { - return elt.Value.(*WrappedTx).tx + return elt.Value.(*WrappedTx).tx, true } - return nil + return nil, false } func (txmp *TxMempool) GetTxEvicted(txKey types.TxKey) bool { diff --git a/mempool/v1/mempool_test.go b/mempool/v1/mempool_test.go index 1b8333789b..703d08f2b5 100644 --- a/mempool/v1/mempool_test.go +++ b/mempool/v1/mempool_test.go @@ -615,9 +615,10 @@ func TestGetTxByKey_GetsTx(t *testing.T) { for _, tx := range txs { txKey := tx.tx.Key() - txFromMempool := txmp.GetTxByKey(txKey) + txFromMempool, exists := txmp.GetTxByKey(txKey) require.Equal(t, tx.tx, txFromMempool) - exists := txmp.GetTxEvicted(txKey) + require.True(t, exists) + exists = txmp.GetTxEvicted(txKey) require.False(t, exists) } } diff --git a/rpc/core/blocks_test.go b/rpc/core/blocks_test.go index 54a2cf4f64..04c0ef67f8 100644 --- a/rpc/core/blocks_test.go +++ b/rpc/core/blocks_test.go @@ -126,30 +126,30 @@ func TestBlockResults(t *testing.T) { } } -func TestTxStatus(t *testing.T) { - env := &Environment{} - height := int64(50) - - blocks := randomBlocks(height) - blockStore := mockBlockStore{ - height: height, - blocks: blocks, - } - env.BlockStore = blockStore - - SetEnvironment(env) - - // Iterate over each block - for _, block := range blocks { - // Iterate over each transaction in the block - for i, tx := range block.Data.Txs { - txStatus, _ := TxStatus(&rpctypes.Context{}, tx.Hash()) - assert.Equal(t, block.Height, txStatus.Height) - assert.Equal(t, int64(i), txStatus.Index) - } - } - -} +// func TestTxStatus(t *testing.T) { +// env := &Environment{} +// height := int64(50) + +// blocks := randomBlocks(height) +// blockStore := mockBlockStore{ +// height: height, +// blocks: blocks, +// } +// env.BlockStore = blockStore + +// SetEnvironment(env) + +// // Iterate over each block +// for _, block := range blocks { +// // Iterate over each transaction in the block +// for i, tx := range block.Data.Txs { +// txStatus, _ := TxStatus(&rpctypes.Context{}, tx.Hash()) +// assert.Equal(t, block.Height, txStatus.Height) +// assert.Equal(t, int64(i), txStatus.Index) +// } +// } + +// } func TestEncodeDataRootTuple(t *testing.T) { height := uint64(2) diff --git a/rpc/core/txstatus.go b/rpc/core/txstatus.go index 4b5902cb0f..365ecee67d 100644 --- a/rpc/core/txstatus.go +++ b/rpc/core/txstatus.go @@ -15,8 +15,8 @@ func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error if err != nil { return nil, err } - txInMempool := env.Mempool.GetTxByKey(txKey) - if txInMempool != nil { + txInMempool, ok := env.Mempool.GetTxByKey(txKey) + if txInMempool != nil && ok{ return &ctypes.ResultTxStatus{Status: "PENDING"}, nil } isEvicted := env.Mempool.GetTxEvicted(txKey) @@ -25,9 +25,9 @@ func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error } // committed txInfo := env.BlockStore.LoadTxInfo(hash) - if txInfo != nil { + if txInfo != nil { return &ctypes.ResultTxStatus{Height: txInfo.Height, Index: txInfo.Index, Status: "COMMITTED"}, nil } - + return &ctypes.ResultTxStatus{Status: "UNKNOWN"}, nil } diff --git a/rpc/core/txstatus_test.go b/rpc/core/txstatus_test.go new file mode 100644 index 0000000000..e165f8e15b --- /dev/null +++ b/rpc/core/txstatus_test.go @@ -0,0 +1,105 @@ +package core + +import ( + "testing" + + mempl "github.com/cometbft/cometbft/mempool" + "github.com/cometbft/cometbft/mempool/mock" + rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" + types "github.com/cometbft/cometbft/types" + "github.com/stretchr/testify/assert" +) + +func TestTxStatus(t *testing.T) { + env := &Environment{} + mempool := mock.Mempool{} + env.Mempool = &mempool + blockStore := mockBlockStore{ + height: 0, + blocks: nil, + } + env.BlockStore = blockStore + SetEnvironment(env) + + tests := []struct { + name string + setup func(*Environment, []types.Tx) + expectedStatus string + }{ + { + name: "Committed", + setup: func(env *Environment, txs []types.Tx) { + height := int64(50) + blocks := randomBlocks(height) + blockStore = mockBlockStore{ + height: height, + blocks: blocks, + } + env.BlockStore = blockStore + }, + expectedStatus: "COMMITTED", + }, + { + name: "Unknown", + setup: func(env *Environment, txs []types.Tx) { + env.BlockStore = mockBlockStore{ + height: 0, + blocks: nil, + } + }, + expectedStatus: "UNKNOWN", + }, + { + name: "Pending", + setup: func(env *Environment, txs []types.Tx) { + env.BlockStore = mockBlockStore{ + height: 0, + blocks: nil, + } + for _, tx := range txs { + mempool.CheckTx(tx, nil, mempl.TxInfo{}) + } + }, + expectedStatus: "PENDING", + }, + { + name: "Evicted", + setup: func(env *Environment, txs []types.Tx) { + env.BlockStore = mockBlockStore{ + height: 0, + blocks: nil, + } + for _, tx := range txs { + mempool.CheckTx(tx, nil, mempl.TxInfo{}) + mempool.RemoveTxByKey(tx.Key()) + } + }, + expectedStatus: "EVICTED", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + txs := makeTxs(2) + + tt.setup(env, txs) + + // Check the status of each transaction + for _, tx := range txs { + txStatus, _ := TxStatus(&rpctypes.Context{}, tx.Hash()) + assert.Equal(t, tt.expectedStatus, txStatus.Status) + } + + // Check the height and index of each transaction if they are committed + if blockStore.height > 0 && tt.expectedStatus == "COMMITTED" { + for _, block := range blockStore.blocks { + for i, tx := range block.Txs { + txStatus, _ := TxStatus(&rpctypes.Context{}, tx.Hash()) + assert.Equal(t, block.Height, txStatus.Height) + assert.Equal(t, int64(i), txStatus.Index) + } + } + } + }) + } +} diff --git a/state/execution_test.go b/state/execution_test.go index 4f03832a09..94b14dc55e 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -58,7 +58,7 @@ func TestApplyBlock(t *testing.T) { }) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - mmock.Mempool{}, sm.EmptyEvidencePool{}) + &mmock.Mempool{}, sm.EmptyEvidencePool{}) block := makeBlock(state, 1) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} @@ -223,7 +223,7 @@ func TestBeginBlockByzantineValidators(t *testing.T) { evpool.On("CheckEvidence", mock.AnythingOfType("types.EvidenceList")).Return(nil) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - mmock.Mempool{}, evpool) + &mmock.Mempool{}, evpool) block := makeBlock(state, 1) block.Evidence = types.EvidenceData{Evidence: ev} @@ -254,7 +254,7 @@ func TestProcessProposal(t *testing.T) { }) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - mmock.Mempool{}, sm.EmptyEvidencePool{}) + &mmock.Mempool{}, sm.EmptyEvidencePool{}) block := sf.MakeBlock(state, int64(height), new(types.Commit)) block.Txs = txs @@ -336,7 +336,7 @@ func makeBlockExec(t *testing.T, testName string, block *types.Block, stateDB db }), log.TestingLogger(), proxyApp.Consensus(), - mmock.Mempool{}, + &mmock.Mempool{}, sm.EmptyEvidencePool{}, sm.BlockExecutorWithMetrics(metrics), ) @@ -506,7 +506,7 @@ func TestEndBlockValidatorUpdates(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - mmock.Mempool{}, + &mmock.Mempool{}, sm.EmptyEvidencePool{}, ) @@ -578,7 +578,7 @@ func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - mmock.Mempool{}, + &mmock.Mempool{}, sm.EmptyEvidencePool{}, ) @@ -615,7 +615,7 @@ func TestFireEventSignedBlockEvent(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - mmock.Mempool{}, + &mmock.Mempool{}, sm.EmptyEvidencePool{}, ) eventBus := types.NewEventBus() diff --git a/state/validation_test.go b/state/validation_test.go index dbb94cbb1d..c075652484 100644 --- a/state/validation_test.go +++ b/state/validation_test.go @@ -36,7 +36,7 @@ func TestValidateBlockHeader(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - memmock.Mempool{}, + &memmock.Mempool{}, sm.EmptyEvidencePool{}, ) lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) @@ -121,7 +121,7 @@ func TestValidateBlockCommit(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - memmock.Mempool{}, + &memmock.Mempool{}, sm.EmptyEvidencePool{}, ) lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) @@ -259,7 +259,7 @@ func TestValidateBlockEvidence(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - memmock.Mempool{}, + &memmock.Mempool{}, evpool, ) lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) diff --git a/test/maverick/consensus/replay_stubs.go b/test/maverick/consensus/replay_stubs.go index f088d1dbe1..76a81c10fe 100644 --- a/test/maverick/consensus/replay_stubs.go +++ b/test/maverick/consensus/replay_stubs.go @@ -40,7 +40,7 @@ func (emptyMempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) func (emptyMempool) EnableTxsAvailable() {} func (emptyMempool) TxsBytes() int64 { return 0 } -func (emptyMempool) GetTxByKey(txKey types.TxKey) types.Tx { return nil } +func (emptyMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { return nil, false } func (emptyMempool) GetTxEvicted(txKey types.TxKey) bool { return false } func (emptyMempool) TxsFront() *clist.CElement { return nil } From 6fb9af9da1f45c3c6ad132c4f0584f907b2d3c16 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 6 Jun 2024 13:50:57 +0200 Subject: [PATCH 07/47] fix: build --- mempool/v1/mempool.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index 86842198bf..518c6ae1ef 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -680,9 +680,6 @@ func (txmp *TxMempool) handleRecheckResult(tx types.Tx, checkTxRes *abci.Respons txmp.metrics.FailedTxs.With(mempool.TypeLabel, mempool.FailedRecheck).Add(1) if !txmp.config.KeepInvalidTxsInCache { txmp.cache.Remove(wtx.tx.Key()) - if err != nil { - schema.WriteMempoolRejected(txmp.traceClient, err.Error()) - } } txmp.metrics.Size.Set(float64(txmp.Size())) txmp.metrics.SizeBytes.Set(float64(txmp.SizeBytes())) From 2f38c2b939d0ae5a52b2ecc0cf58d246f605bcaf Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 6 Jun 2024 15:41:52 +0200 Subject: [PATCH 08/47] test: more tests --- rpc/client/rpc_test.go | 60 +++++++++++++------ rpc/core/{txstatus.go => tx_status.go} | 17 ++++-- .../{txstatus_test.go => tx_status_test.go} | 0 3 files changed, 54 insertions(+), 23 deletions(-) rename rpc/core/{txstatus.go => tx_status.go} (75%) rename rpc/core/{txstatus_test.go => tx_status_test.go} (100%) diff --git a/rpc/client/rpc_test.go b/rpc/client/rpc_test.go index 6d6c96056e..98831bc033 100644 --- a/rpc/client/rpc_test.go +++ b/rpc/client/rpc_test.go @@ -538,30 +538,52 @@ func TestBlockSearch(t *testing.T) { func TestTxStatus(t *testing.T) { c := getHTTPClient() + require := require.New(t) + mempool := node.Mempool() - // first we broadcast a few txs - var txHashes [][]byte - var txHeights []int64 - for i := 0; i < 10; i++ { - _, _, tx := MakeTxKV() + // Create a new transaction + _, _, tx := MakeTxKV() - result, err := c.BroadcastTxCommit(context.Background(), tx) - require.NoError(t, err) - txHashes = append(txHashes, result.Hash) - txHeights = append(txHeights, result.Height) - } + // Get the initial size of the mempool + initMempoolSize := mempool.Size() - require.NoError(t, client.WaitForHeight(c, 5, nil)) + // Add the transaction to the mempool + err := mempool.CheckTx(tx, nil, mempl.TxInfo{}) + require.NoError(err) - // check the status of each transaction - for i, hash := range txHashes { - result, err := c.TxStatus(context.Background(), hash) - require.NoError(t, err) + // Check if the size of the mempool has increased + require.Equal(initMempoolSize+1, mempool.Size()) - expectedIndex := int64(0) - require.Equal(t, txHeights[i], result.Height) - require.Equal(t, expectedIndex, result.Index) - } + // Get the tx status from the mempool + result, err := c.TxStatus(context.Background(), types.Tx(tx).Hash()) + require.NoError(err) + require.EqualValues(0, result.Height) + require.EqualValues(0, result.Index) + require.Equal("PENDING", result.Status) + + // Flush the mempool + mempool.Flush() + require.Equal(0, mempool.Size()) + + // Get tx status after flushing it from the mempool + result, err = c.TxStatus(context.Background(), types.Tx(tx).Hash()) + require.NoError(err) + require.EqualValues(0, result.Height) + require.EqualValues(0, result.Index) + require.Equal("UNKNOWN", result.Status) + + // Broadcast the tx again + bres, err := c.BroadcastTxCommit(context.Background(), tx) + require.NoError(err) + require.True(bres.CheckTx.IsOK()) + require.True(bres.DeliverTx.IsOK()) + + // Get the tx status + result, err = c.TxStatus(context.Background(), types.Tx(tx).Hash()) + require.NoError(err) + require.EqualValues(bres.Height, result.Height) + require.EqualValues(0, result.Index) + require.Equal("COMMITTED", result.Status) } func TestTxSearch(t *testing.T) { diff --git a/rpc/core/txstatus.go b/rpc/core/tx_status.go similarity index 75% rename from rpc/core/txstatus.go rename to rpc/core/tx_status.go index 365ecee67d..ce7e05e3b4 100644 --- a/rpc/core/txstatus.go +++ b/rpc/core/tx_status.go @@ -1,33 +1,42 @@ package core import ( + "fmt" + ctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" types "github.com/cometbft/cometbft/types" ) // TxStatus retrieves the status of a transaction given its hash. It returns a ResultTxStatus -// containing the height and index of the transaction within the block. +// containing the height and index of the transaction within the block(if committed). func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error) { env := GetEnvironment() - // not committed + + // Get the tx key from the hash txKey, err := types.TxKeyFromBytes(hash) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get tx key from hash: %v", err) } + + // Check if the tx is in the mempool txInMempool, ok := env.Mempool.GetTxByKey(txKey) if txInMempool != nil && ok{ return &ctypes.ResultTxStatus{Status: "PENDING"}, nil } + + // Check if the tx is evicted isEvicted := env.Mempool.GetTxEvicted(txKey) if isEvicted { return &ctypes.ResultTxStatus{Status: "EVICTED"}, nil } - // committed + + // Check if the tx has been committed txInfo := env.BlockStore.LoadTxInfo(hash) if txInfo != nil { return &ctypes.ResultTxStatus{Height: txInfo.Height, Index: txInfo.Index, Status: "COMMITTED"}, nil } + // If the tx is not in the mempool, evicted, or committed, return unknown return &ctypes.ResultTxStatus{Status: "UNKNOWN"}, nil } diff --git a/rpc/core/txstatus_test.go b/rpc/core/tx_status_test.go similarity index 100% rename from rpc/core/txstatus_test.go rename to rpc/core/tx_status_test.go From edbcdae76c534749fa9fd43a4896f4e84b5af720 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 6 Jun 2024 15:50:13 +0200 Subject: [PATCH 09/47] style: lint --- consensus/replay_stubs.go | 6 +++--- mempool/cat/reactor.go | 3 +-- rpc/core/tx_status.go | 8 ++++---- rpc/core/tx_status_test.go | 10 +++++++--- test/maverick/consensus/replay_stubs.go | 2 +- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/consensus/replay_stubs.go b/consensus/replay_stubs.go index a52af13bb2..86af9ed857 100644 --- a/consensus/replay_stubs.go +++ b/consensus/replay_stubs.go @@ -47,10 +47,10 @@ func (emptyMempool) TxsBytes() int64 { return 0 } func (emptyMempool) TxsFront() *clist.CElement { return nil } func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } -func (emptyMempool) InitWAL() error { return nil } -func (emptyMempool) CloseWAL() {} +func (emptyMempool) InitWAL() error { return nil } +func (emptyMempool) CloseWAL() {} func (emptyMempool) GetTxByKey(types.TxKey) (types.Tx, bool) { return nil, false } -func (emptyMempool) GetTxEvicted(types.TxKey) bool { return false } +func (emptyMempool) GetTxEvicted(types.TxKey) bool { return false } //----------------------------------------------------------------------------- // mockProxyApp uses ABCIResponses to give the right results. diff --git a/mempool/cat/reactor.go b/mempool/cat/reactor.go index d66b23c387..6c57e1de60 100644 --- a/mempool/cat/reactor.go +++ b/mempool/cat/reactor.go @@ -311,7 +311,6 @@ func (memR *Reactor) ReceiveEnvelope(e p2p.Envelope) { memR.Switch.StopPeerForError(e.Src, err) return } - schema.WriteMempoolPeerState( memR.traceClient, string(e.Src.ID()), @@ -319,7 +318,7 @@ func (memR *Reactor) ReceiveEnvelope(e p2p.Envelope) { txKey[:], schema.Download, ) - tx, has := memR.mempool.GetTxByKey(txKey) + tx, has := memR.mempool.GetTxByKey(txKey) if has && !memR.opts.ListenOnly { peerID := memR.ids.GetIDForPeer(e.Src.ID()) diff --git a/rpc/core/tx_status.go b/rpc/core/tx_status.go index ce7e05e3b4..27e6980454 100644 --- a/rpc/core/tx_status.go +++ b/rpc/core/tx_status.go @@ -12,7 +12,7 @@ import ( // containing the height and index of the transaction within the block(if committed). func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error) { env := GetEnvironment() - + // Get the tx key from the hash txKey, err := types.TxKeyFromBytes(hash) if err != nil { @@ -21,7 +21,7 @@ func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error // Check if the tx is in the mempool txInMempool, ok := env.Mempool.GetTxByKey(txKey) - if txInMempool != nil && ok{ + if txInMempool != nil && ok { return &ctypes.ResultTxStatus{Status: "PENDING"}, nil } @@ -33,10 +33,10 @@ func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error // Check if the tx has been committed txInfo := env.BlockStore.LoadTxInfo(hash) - if txInfo != nil { + if txInfo != nil { return &ctypes.ResultTxStatus{Height: txInfo.Height, Index: txInfo.Index, Status: "COMMITTED"}, nil } - + // If the tx is not in the mempool, evicted, or committed, return unknown return &ctypes.ResultTxStatus{Status: "UNKNOWN"}, nil } diff --git a/rpc/core/tx_status_test.go b/rpc/core/tx_status_test.go index e165f8e15b..70b6f90495 100644 --- a/rpc/core/tx_status_test.go +++ b/rpc/core/tx_status_test.go @@ -8,6 +8,7 @@ import ( rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" types "github.com/cometbft/cometbft/types" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestTxStatus(t *testing.T) { @@ -57,7 +58,8 @@ func TestTxStatus(t *testing.T) { blocks: nil, } for _, tx := range txs { - mempool.CheckTx(tx, nil, mempl.TxInfo{}) + err := mempool.CheckTx(tx, nil, mempl.TxInfo{}) + require.NoError(t, err) } }, expectedStatus: "PENDING", @@ -70,8 +72,10 @@ func TestTxStatus(t *testing.T) { blocks: nil, } for _, tx := range txs { - mempool.CheckTx(tx, nil, mempl.TxInfo{}) - mempool.RemoveTxByKey(tx.Key()) + err := mempool.CheckTx(tx, nil, mempl.TxInfo{}) + require.NoError(t, err) + err = mempool.RemoveTxByKey(tx.Key()) + require.NoError(t, err) } }, expectedStatus: "EVICTED", diff --git a/test/maverick/consensus/replay_stubs.go b/test/maverick/consensus/replay_stubs.go index 76a81c10fe..e300fb1641 100644 --- a/test/maverick/consensus/replay_stubs.go +++ b/test/maverick/consensus/replay_stubs.go @@ -41,7 +41,7 @@ func (emptyMempool) EnableTxsAvailable() {} func (emptyMempool) TxsBytes() int64 { return 0 } func (emptyMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { return nil, false } -func (emptyMempool) GetTxEvicted(txKey types.TxKey) bool { return false } +func (emptyMempool) GetTxEvicted(txKey types.TxKey) bool { return false } func (emptyMempool) TxsFront() *clist.CElement { return nil } func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } From 652f814d4d920760c1609d3c68ec1d404b656638 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 6 Jun 2024 17:09:17 +0200 Subject: [PATCH 10/47] style: cleanup --- mempool/cache_bench_test.go | 1 - mempool/cat/pool.go | 7 ++++--- mempool/cat/pool_test.go | 1 + mempool/cat/reactor.go | 1 - mempool/mempool.go | 8 +++++++- mempool/v0/clist_mempool.go | 10 +++------- mempool/v1/mempool.go | 8 ++++++-- mempool/v1/mempool_test.go | 12 ++++++++---- rpc/core/blocks_test.go | 25 ------------------------- rpc/core/tx_status.go | 3 ++- rpc/core/tx_status_test.go | 7 ++++++- 11 files changed, 37 insertions(+), 46 deletions(-) diff --git a/mempool/cache_bench_test.go b/mempool/cache_bench_test.go index 4b235092ba..f8082e0605 100644 --- a/mempool/cache_bench_test.go +++ b/mempool/cache_bench_test.go @@ -3,7 +3,6 @@ package mempool import ( "encoding/binary" "testing" - "github.com/cometbft/cometbft/types" ) diff --git a/mempool/cat/pool.go b/mempool/cat/pool.go index f2c7fc4905..5bb61faab7 100644 --- a/mempool/cat/pool.go +++ b/mempool/cat/pool.go @@ -175,7 +175,7 @@ func (txmp *TxPool) Has(txKey types.TxKey) bool { } // GetTxByKey retrieves a transaction based on the key. It returns a bool -// if the transaction exists or not +// indicating whether transaction was found in the cache. func (txmp *TxPool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { wtx := txmp.store.get(txKey) if wtx != nil { @@ -184,8 +184,8 @@ func (txmp *TxPool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { return types.Tx{}, false } -// IsEvicted returns true is the transaction was recently evicted and is -// currently within the cache +// GetTxEvicted returns a bool indicating whether the transaction with +// the specified key was recently evicted and is currently within the cache func (txmp *TxPool) GetTxEvicted(txKey types.TxKey) bool { return txmp.evictedTxCache.Has(txKey) } @@ -368,6 +368,7 @@ func (txmp *TxPool) RemoveTxByKey(txKey types.TxKey) error { } func (txmp *TxPool) removeTxByKey(txKey types.TxKey) { + txmp.rejectedTxCache.Push(txKey) _ = txmp.store.remove(txKey) txmp.seenByPeersSet.RemoveKey(txKey) } diff --git a/mempool/cat/pool_test.go b/mempool/cat/pool_test.go index 4f4f599396..c50d79a213 100644 --- a/mempool/cat/pool_test.go +++ b/mempool/cat/pool_test.go @@ -100,6 +100,7 @@ func setup(t testing.TB, cacheSize int, options ...TxPoolOption) *TxPool { os.RemoveAll(cfg.RootDir) require.NoError(t, appConnMem.Stop()) }) + return NewTxPool(log.TestingLogger().With("test", t.Name()), cfg, appConnMem, 1, options...) } diff --git a/mempool/cat/reactor.go b/mempool/cat/reactor.go index 6c57e1de60..76c918ea23 100644 --- a/mempool/cat/reactor.go +++ b/mempool/cat/reactor.go @@ -319,7 +319,6 @@ func (memR *Reactor) ReceiveEnvelope(e p2p.Envelope) { schema.Download, ) tx, has := memR.mempool.GetTxByKey(txKey) - if has && !memR.opts.ListenOnly { peerID := memR.ids.GetIDForPeer(e.Src.ID()) memR.Logger.Debug("sending a tx in response to a want msg", "peer", peerID) diff --git a/mempool/mempool.go b/mempool/mempool.go index 0c8e61ff08..42238249cd 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -91,8 +91,14 @@ type Mempool interface { // trigger once every height when transactions are available. EnableTxsAvailable() + // GetTxByKey returns tx by its key from the mempool cache and the bool indicating its + // presence in the tx cache. + // Used in the RPC endpoint - TxStatus. GetTxByKey(key types.TxKey) (types.Tx, bool) - + + // GetTxEvicted returns true if the tx is evicted from the mempool and exists in the + // evicted cache. + // Used in the RPC endpoint - TxStatus. GetTxEvicted(key types.TxKey) bool // Size returns the number of transactions in the mempool. diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index bc6a26c389..171b14c4f3 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -183,16 +183,12 @@ func (mem *CListMempool) TxsFront() *clist.CElement { return mem.txs.Front() } +// GetTxByKey currently not enabled in v0 but it is required by the interface. func (mem *CListMempool) GetTxByKey(key types.TxKey) (types.Tx, bool) { - e, ok := mem.txsMap.Load(key) - memTx := e.(*clist.CElement).Value.(*mempoolTx) - - if !ok { - return nil, false - } - return memTx.tx, true + return nil, false } +// GetTxEvicted currently not enabled in v0 but it is required by the interface. func (mem *CListMempool) GetTxEvicted(key types.TxKey) bool { return false } diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index 518c6ae1ef..dda2f09237 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -261,6 +261,8 @@ func (txmp *TxMempool) RemoveTxByKey(txKey types.TxKey) error { return txmp.removeTxByKey(txKey) } +// GetTxByKey retrieves a transaction based on the key. It returns a bool +// indicating whether transaction was found in the cache. func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { txmp.mtx.RLock() defer txmp.mtx.RUnlock() @@ -271,6 +273,8 @@ func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { return nil, false } +// GetTxEvicted returns a bool indicating whether the transaction with +// the specified key was recently evicted and is currently within the cache func (txmp *TxMempool) GetTxEvicted(txKey types.TxKey) bool { return txmp.evictedTxs.Has(txKey) } @@ -557,12 +561,12 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon if len(victims) == 0 || victimBytes < wtx.Size() { txmp.cache.Remove(wtx.tx.Key()) txmp.logger.Error( - "evicted valid incoming transaction; mempool is full", + "rejected valid incoming transaction; mempool is full", "tx", fmt.Sprintf("%X", wtx.tx.Hash()), "err", err.Error(), ) checkTxRes.MempoolError = - fmt.Sprintf("evicted valid incoming transaction; mempool is full (%X)", + fmt.Sprintf("rejected valid incoming transaction; mempool is full (%X)", wtx.tx.Hash()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedNewTxFullMempool).Add(1) // Add it to evicted transactions cache diff --git a/mempool/v1/mempool_test.go b/mempool/v1/mempool_test.go index 703d08f2b5..2bcc1739e0 100644 --- a/mempool/v1/mempool_test.go +++ b/mempool/v1/mempool_test.go @@ -108,7 +108,8 @@ func mustCheckTx(t *testing.T, txmp *TxMempool, spec string) { <-done } -// checkTxs +// checkTxs generates a specified number of txs, checks them into the mempool, +// and returns them. func checkTxs(t *testing.T, txmp *TxMempool, numTxs int, peerID uint16) []testTx { txs := make([]testTx, numTxs) txInfo := mempool.TxInfo{SenderID: peerID} @@ -612,15 +613,18 @@ func TestTxMempool_ExpiredTxs_Timestamp(t *testing.T) { func TestGetTxByKey_GetsTx(t *testing.T) { txmp := setup(t, 500) txs := checkTxs(t, txmp, 100, 0) - + + // Test that it gets all valid txs for _, tx := range txs { txKey := tx.tx.Key() txFromMempool, exists := txmp.GetTxByKey(txKey) require.Equal(t, tx.tx, txFromMempool) require.True(t, exists) - exists = txmp.GetTxEvicted(txKey) - require.False(t, exists) } + + // Test that a non-existent tx returns false + _, exists := txmp.GetTxByKey(types.Tx("non-existent-tx").Key()) + require.False(t, exists) } func TestTxMempool_ExpiredTxs_NumBlocks(t *testing.T) { diff --git a/rpc/core/blocks_test.go b/rpc/core/blocks_test.go index 04c0ef67f8..7bddc82a88 100644 --- a/rpc/core/blocks_test.go +++ b/rpc/core/blocks_test.go @@ -126,31 +126,6 @@ func TestBlockResults(t *testing.T) { } } -// func TestTxStatus(t *testing.T) { -// env := &Environment{} -// height := int64(50) - -// blocks := randomBlocks(height) -// blockStore := mockBlockStore{ -// height: height, -// blocks: blocks, -// } -// env.BlockStore = blockStore - -// SetEnvironment(env) - -// // Iterate over each block -// for _, block := range blocks { -// // Iterate over each transaction in the block -// for i, tx := range block.Data.Txs { -// txStatus, _ := TxStatus(&rpctypes.Context{}, tx.Hash()) -// assert.Equal(t, block.Height, txStatus.Height) -// assert.Equal(t, int64(i), txStatus.Index) -// } -// } - -// } - func TestEncodeDataRootTuple(t *testing.T) { height := uint64(2) dataRoot, err := hex.DecodeString("82dc1607d84557d3579ce602a45f5872e821c36dbda7ec926dfa17ebc8d5c013") diff --git a/rpc/core/tx_status.go b/rpc/core/tx_status.go index 27e6980454..ba59b096ed 100644 --- a/rpc/core/tx_status.go +++ b/rpc/core/tx_status.go @@ -9,7 +9,8 @@ import ( ) // TxStatus retrieves the status of a transaction given its hash. It returns a ResultTxStatus -// containing the height and index of the transaction within the block(if committed). +// containing the height and index of the transaction within the block(if committed) +// or whether the transaction is pending, evicted in the mempool otherwise unknown. func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error) { env := GetEnvironment() diff --git a/rpc/core/tx_status_test.go b/rpc/core/tx_status_test.go index 70b6f90495..6e0d9b9f9e 100644 --- a/rpc/core/tx_status_test.go +++ b/rpc/core/tx_status_test.go @@ -11,8 +11,13 @@ import ( "github.com/stretchr/testify/require" ) +// TestTxStatus tests the TxStatus function in the RPC core +// making sure it fetches the correct status for each transaction. func TestTxStatus(t *testing.T) { + // Create a new environment env := &Environment{} + + // Create a new mempool and block store mempool := mock.Mempool{} env.Mempool = &mempool blockStore := mockBlockStore{ @@ -94,7 +99,7 @@ func TestTxStatus(t *testing.T) { assert.Equal(t, tt.expectedStatus, txStatus.Status) } - // Check the height and index of each transaction if they are committed + // Check the height and index of transactions that are committed if blockStore.height > 0 && tt.expectedStatus == "COMMITTED" { for _, block := range blockStore.blocks { for i, tx := range block.Txs { From 2cede15773ea78497284e389f79865007332da76 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 6 Jun 2024 17:15:12 +0200 Subject: [PATCH 11/47] style: lint --- go.mod | 16 ++++++++-------- go.sum | 15 +++++++++++++++ mempool/mempool.go | 4 ++-- mempool/v1/mempool_test.go | 2 +- rpc/core/tx_status.go | 2 +- 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 97ff458c46..43120082c4 100644 --- a/go.mod +++ b/go.mod @@ -49,8 +49,8 @@ require ( go.opentelemetry.io/otel v1.21.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 go.opentelemetry.io/otel/sdk v1.21.0 - golang.org/x/crypto v0.21.0 - golang.org/x/net v0.23.0 + golang.org/x/crypto v0.24.0 + golang.org/x/net v0.26.0 gonum.org/v1/gonum v0.8.2 google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 @@ -275,12 +275,12 @@ require ( go.uber.org/zap v1.23.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.13.0 // indirect + golang.org/x/mod v0.18.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/term v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/tools v0.22.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/go.sum b/go.sum index cb28b78e71..c940715784 100644 --- a/go.sum +++ b/go.sum @@ -991,6 +991,8 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1040,6 +1042,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1091,6 +1095,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1119,6 +1125,7 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1202,6 +1209,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1209,6 +1218,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1222,6 +1233,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1314,6 +1327,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/mempool/mempool.go b/mempool/mempool.go index 42238249cd..9ad97266c1 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -91,11 +91,11 @@ type Mempool interface { // trigger once every height when transactions are available. EnableTxsAvailable() - // GetTxByKey returns tx by its key from the mempool cache and the bool indicating its + // GetTxByKey returns tx by its key from the mempool cache and the bool indicating its // presence in the tx cache. // Used in the RPC endpoint - TxStatus. GetTxByKey(key types.TxKey) (types.Tx, bool) - + // GetTxEvicted returns true if the tx is evicted from the mempool and exists in the // evicted cache. // Used in the RPC endpoint - TxStatus. diff --git a/mempool/v1/mempool_test.go b/mempool/v1/mempool_test.go index 2bcc1739e0..80b02188e4 100644 --- a/mempool/v1/mempool_test.go +++ b/mempool/v1/mempool_test.go @@ -613,7 +613,7 @@ func TestTxMempool_ExpiredTxs_Timestamp(t *testing.T) { func TestGetTxByKey_GetsTx(t *testing.T) { txmp := setup(t, 500) txs := checkTxs(t, txmp, 100, 0) - + // Test that it gets all valid txs for _, tx := range txs { txKey := tx.tx.Key() diff --git a/rpc/core/tx_status.go b/rpc/core/tx_status.go index ba59b096ed..9c46b3dc63 100644 --- a/rpc/core/tx_status.go +++ b/rpc/core/tx_status.go @@ -9,7 +9,7 @@ import ( ) // TxStatus retrieves the status of a transaction given its hash. It returns a ResultTxStatus -// containing the height and index of the transaction within the block(if committed) +// containing the height and index of the transaction within the block(if committed) // or whether the transaction is pending, evicted in the mempool otherwise unknown. func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error) { env := GetEnvironment() From 125ef6f1e40bd82ba64da524d4440b818659d1fd Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 6 Jun 2024 17:19:58 +0200 Subject: [PATCH 12/47] style: gofumped --- mempool/cache_bench_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/cache_bench_test.go b/mempool/cache_bench_test.go index f8082e0605..d88ef5ce53 100644 --- a/mempool/cache_bench_test.go +++ b/mempool/cache_bench_test.go @@ -2,8 +2,8 @@ package mempool import ( "encoding/binary" - "testing" "github.com/cometbft/cometbft/types" + "testing" ) func BenchmarkCacheInsertTime(b *testing.B) { From 37c8cd1769da9c23e3114cfb0c478d63eee2c2c9 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 6 Jun 2024 17:26:59 +0200 Subject: [PATCH 13/47] style: goimports --- mempool/cache_bench_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mempool/cache_bench_test.go b/mempool/cache_bench_test.go index d88ef5ce53..4b235092ba 100644 --- a/mempool/cache_bench_test.go +++ b/mempool/cache_bench_test.go @@ -2,8 +2,9 @@ package mempool import ( "encoding/binary" - "github.com/cometbft/cometbft/types" "testing" + + "github.com/cometbft/cometbft/types" ) func BenchmarkCacheInsertTime(b *testing.B) { From 90f482c3247efa37930b2c821d911e299ad61904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 10:40:35 +0200 Subject: [PATCH 14/47] Update mempool/cache.go Co-authored-by: Rootul P --- mempool/cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/cache.go b/mempool/cache.go index 41e8275791..ed7866062b 100644 --- a/mempool/cache.go +++ b/mempool/cache.go @@ -16,7 +16,7 @@ type TxCache interface { // Reset resets the cache to an empty state. Reset() - // Push adds the given raw transaction to the cache and returns true if it was + // Push adds the given tx key to the cache and returns true if it was // newly added. Otherwise, it returns false. Push(tx types.TxKey) bool From 5cdd6e0fdd9cfaf3fc53381f3a75277fac71588d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 10:41:15 +0200 Subject: [PATCH 15/47] Update mempool/cache.go Co-authored-by: Rootul P --- mempool/cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/cache.go b/mempool/cache.go index ed7866062b..b6585f6205 100644 --- a/mempool/cache.go +++ b/mempool/cache.go @@ -23,7 +23,7 @@ type TxCache interface { // Remove removes the given raw transaction from the cache. Remove(tx types.TxKey) - // Has reports whether tx is present in the cache. Checking for presence is + // Has reports whether tx key is present in the cache. Checking for presence is // not treated as an access of the value. Has(tx types.TxKey) bool } From 94a4d3dc6d21a39a13a125d80b43c1c0b24c62ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 10:41:35 +0200 Subject: [PATCH 16/47] Update mempool/cache.go Co-authored-by: Rootul P --- mempool/cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/cache.go b/mempool/cache.go index b6585f6205..df4e7a3c00 100644 --- a/mempool/cache.go +++ b/mempool/cache.go @@ -20,7 +20,7 @@ type TxCache interface { // newly added. Otherwise, it returns false. Push(tx types.TxKey) bool - // Remove removes the given raw transaction from the cache. + // Remove removes the given tx key from the cache. Remove(tx types.TxKey) // Has reports whether tx key is present in the cache. Checking for presence is From 26bbd606a3de5b4f66a3c0ff13a2d1b2b8096324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 10:42:13 +0200 Subject: [PATCH 17/47] Update mempool/cat/pool.go Co-authored-by: Rootul P --- mempool/cat/pool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/cat/pool.go b/mempool/cat/pool.go index 5bb61faab7..08353fd976 100644 --- a/mempool/cat/pool.go +++ b/mempool/cat/pool.go @@ -185,7 +185,7 @@ func (txmp *TxPool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { } // GetTxEvicted returns a bool indicating whether the transaction with -// the specified key was recently evicted and is currently within the cache +// the specified key was recently evicted and is currently within the cache. func (txmp *TxPool) GetTxEvicted(txKey types.TxKey) bool { return txmp.evictedTxCache.Has(txKey) } From 770804528398ca66b4ff19a377e3f8c35aa84ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 10:42:28 +0200 Subject: [PATCH 18/47] Update mempool/mempool.go Co-authored-by: Rootul P --- mempool/mempool.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index 9ad97266c1..5da898fa04 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -91,9 +91,8 @@ type Mempool interface { // trigger once every height when transactions are available. EnableTxsAvailable() - // GetTxByKey returns tx by its key from the mempool cache and the bool indicating its - // presence in the tx cache. - // Used in the RPC endpoint - TxStatus. + // GetTxByKey gets a tx by its key from the mempool cache. Returns the tx and a bool indicating its presence in the tx cache. + // Used in the RPC endpoint: TxStatus. GetTxByKey(key types.TxKey) (types.Tx, bool) // GetTxEvicted returns true if the tx is evicted from the mempool and exists in the From 4b8918d6cab86d9c3741e4cb0171b56d66807e2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 10:42:43 +0200 Subject: [PATCH 19/47] Update mempool/mock/mempool.go Co-authored-by: Rootul P --- mempool/mock/mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/mock/mempool.go b/mempool/mock/mempool.go index d167cdc964..84df699429 100644 --- a/mempool/mock/mempool.go +++ b/mempool/mock/mempool.go @@ -7,7 +7,7 @@ import ( "github.com/cometbft/cometbft/types" ) -// Mempool is an empty implementation of a Mempool, useful for testing. +// Mempool is a mock implementation of a Mempool, useful for testing. type Mempool struct { txs map[types.TxKey]types.Tx evictedTxs map[types.TxKey]bool From 2a07da95478d622c8ac8a685b4c05c1d4ed04a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 10:43:30 +0200 Subject: [PATCH 20/47] Update mempool/v0/clist_mempool.go Co-authored-by: Rootul P --- mempool/v0/clist_mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index 171b14c4f3..b317778134 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -183,7 +183,7 @@ func (mem *CListMempool) TxsFront() *clist.CElement { return mem.txs.Front() } -// GetTxByKey currently not enabled in v0 but it is required by the interface. +// GetTxByKey is not supported by the v0 mempool but it is required to satisfy the mempool interface. func (mem *CListMempool) GetTxByKey(key types.TxKey) (types.Tx, bool) { return nil, false } From e8e634bfd40891e9183e8d8afdf5dde910dacd57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 10:43:49 +0200 Subject: [PATCH 21/47] Update mempool/v0/clist_mempool.go Co-authored-by: Rootul P --- mempool/v0/clist_mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index b317778134..d7f38befe7 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -188,7 +188,7 @@ func (mem *CListMempool) GetTxByKey(key types.TxKey) (types.Tx, bool) { return nil, false } -// GetTxEvicted currently not enabled in v0 but it is required by the interface. +// GetTxEvicted is not supported by the v0 mempool but it is required to satisfy the mempool interface. func (mem *CListMempool) GetTxEvicted(key types.TxKey) bool { return false } From e91c8f1ef4cbbbf1b0f28949f70c4401c0149067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 10:43:56 +0200 Subject: [PATCH 22/47] Update rpc/core/tx_status.go Co-authored-by: Rootul P --- rpc/core/tx_status.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/core/tx_status.go b/rpc/core/tx_status.go index 9c46b3dc63..b9d733ca12 100644 --- a/rpc/core/tx_status.go +++ b/rpc/core/tx_status.go @@ -10,7 +10,7 @@ import ( // TxStatus retrieves the status of a transaction given its hash. It returns a ResultTxStatus // containing the height and index of the transaction within the block(if committed) -// or whether the transaction is pending, evicted in the mempool otherwise unknown. +// or whether the transaction is pending, evicted from the mempool, or otherwise unknown. func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error) { env := GetEnvironment() From 9bcd19bd6df1a0c25ff1a5a9d2def0fb89c78bca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 10:44:20 +0200 Subject: [PATCH 23/47] Update mempool/v1/mempool.go Co-authored-by: Rootul P --- mempool/v1/mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index dda2f09237..6a9ed60159 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -274,7 +274,7 @@ func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { } // GetTxEvicted returns a bool indicating whether the transaction with -// the specified key was recently evicted and is currently within the cache +// the specified key was recently evicted and is currently within the cache. func (txmp *TxMempool) GetTxEvicted(txKey types.TxKey) bool { return txmp.evictedTxs.Has(txKey) } From c3700300e37b4c5832f9dfc863723540cbcb172e Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Tue, 11 Jun 2024 15:51:42 +0200 Subject: [PATCH 24/47] refactor: address review comments --- blockchain/v0/reactor_test.go | 2 +- blockchain/v1/reactor_test.go | 2 +- blockchain/v2/reactor_test.go | 4 +- go.mod | 1 + go.sum | 18 +-- mempool/cat/pool.go | 7 +- mempool/mock/mempool.go | 49 ++----- mempool/v1/mempool.go | 2 +- rpc/core/mocks/mempool.go | 240 ++++++++++++++++++++++++++++++++++ rpc/core/tx.go | 41 ++++++ rpc/core/tx_status.go | 43 ------ rpc/core/tx_status_test.go | 65 +++++---- state/execution_test.go | 14 +- state/validation_test.go | 6 +- 14 files changed, 361 insertions(+), 133 deletions(-) create mode 100644 rpc/core/mocks/mempool.go delete mode 100644 rpc/core/tx_status.go diff --git a/blockchain/v0/reactor_test.go b/blockchain/v0/reactor_test.go index 2f2d05dd45..d93b61035f 100644 --- a/blockchain/v0/reactor_test.go +++ b/blockchain/v0/reactor_test.go @@ -91,7 +91,7 @@ func newBlockchainReactor( DiscardABCIResponses: false, }) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - &mock.Mempool{}, sm.EmptyEvidencePool{}) + mock.Mempool{}, sm.EmptyEvidencePool{}) if err = stateStore.Save(state); err != nil { panic(err) } diff --git a/blockchain/v1/reactor_test.go b/blockchain/v1/reactor_test.go index 5bcbe661c9..b3650cbda5 100644 --- a/blockchain/v1/reactor_test.go +++ b/blockchain/v1/reactor_test.go @@ -123,7 +123,7 @@ func newBlockchainReactor( DiscardABCIResponses: false, }) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - &mock.Mempool{}, sm.EmptyEvidencePool{}) + mock.Mempool{}, sm.EmptyEvidencePool{}) if err = stateStore.Save(state); err != nil { panic(err) } diff --git a/blockchain/v2/reactor_test.go b/blockchain/v2/reactor_test.go index 15f63eaef3..633d512f10 100644 --- a/blockchain/v2/reactor_test.go +++ b/blockchain/v2/reactor_test.go @@ -146,7 +146,7 @@ func newTestReactor(p testReactorParams) *BlockchainReactor { stateStore := sm.NewStore(db, sm.StoreOptions{ DiscardABCIResponses: false, }) - appl = sm.NewBlockExecutor(stateStore, p.logger, proxyApp.Consensus(), &mock.Mempool{}, sm.EmptyEvidencePool{}) + appl = sm.NewBlockExecutor(stateStore, p.logger, proxyApp.Consensus(), mock.Mempool{}, sm.EmptyEvidencePool{}) if err = stateStore.Save(state); err != nil { panic(err) } @@ -540,7 +540,7 @@ func newReactorStore( }, ) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - &mock.Mempool{}, sm.EmptyEvidencePool{}) + mock.Mempool{}, sm.EmptyEvidencePool{}) if err = stateStore.Save(state); err != nil { panic(err) } diff --git a/go.mod b/go.mod index 43120082c4..1a171cfe7b 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( github.com/go-logfmt/logfmt v0.5.1 github.com/gofrs/uuid v4.3.0+incompatible github.com/gogo/protobuf v1.3.2 + github.com/golang/mock v1.4.4 github.com/golang/protobuf v1.5.3 github.com/golangci/golangci-lint v1.50.1 github.com/google/orderedcode v0.0.1 diff --git a/go.sum b/go.sum index c940715784..d1ef0dce8b 100644 --- a/go.sum +++ b/go.sum @@ -380,6 +380,7 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -989,8 +990,6 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1040,8 +1039,6 @@ golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1093,8 +1090,6 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1123,8 +1118,7 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1207,8 +1201,6 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1216,8 +1208,6 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1231,8 +1221,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1325,8 +1313,6 @@ golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/mempool/cat/pool.go b/mempool/cat/pool.go index 08353fd976..0a55c24b3d 100644 --- a/mempool/cat/pool.go +++ b/mempool/cat/pool.go @@ -174,7 +174,12 @@ func (txmp *TxPool) Has(txKey types.TxKey) bool { return txmp.store.has(txKey) } -// GetTxByKey retrieves a transaction based on the key. It returns a bool +// Gets tx by its key. Preserved to maintain API compatibility. +func (txmp *TxPool) Get(txKey types.TxKey) (types.Tx, bool) { + return txmp.GetTxByKey(txKey) +} + +// GetTxByKey retrieves a transaction based on the˝ key. It returns a bool // indicating whether transaction was found in the cache. func (txmp *TxPool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { wtx := txmp.store.get(txKey) diff --git a/mempool/mock/mempool.go b/mempool/mock/mempool.go index 84df699429..ca6385a328 100644 --- a/mempool/mock/mempool.go +++ b/mempool/mock/mempool.go @@ -7,32 +7,18 @@ import ( "github.com/cometbft/cometbft/types" ) -// Mempool is a mock implementation of a Mempool, useful for testing. -type Mempool struct { - txs map[types.TxKey]types.Tx - evictedTxs map[types.TxKey]bool -} +// Mempool is an empty implementation of a Mempool, useful for testing. +type Mempool struct{} -var _ mempool.Mempool = &Mempool{} +var _ mempool.Mempool = Mempool{} func (Mempool) Lock() {} func (Mempool) Unlock() {} func (Mempool) Size() int { return 0 } -func (m *Mempool) CheckTx(tx types.Tx, _ func(*abci.Response), _ mempool.TxInfo) error { - if m.txs == nil { - m.txs = make(map[types.TxKey]types.Tx) - } - if m.evictedTxs == nil { - m.evictedTxs = make(map[types.TxKey]bool) - } - m.txs[tx.Key()] = tx - return nil -} -func (m *Mempool) RemoveTxByKey(txKey types.TxKey) error { - delete(m.txs, txKey) - m.evictedTxs[txKey] = true +func (Mempool) CheckTx(_ types.Tx, _ func(*abci.Response), _ mempool.TxInfo) error { return nil } +func (Mempool) RemoveTxByKey(txKey types.TxKey) error { return nil } func (Mempool) ReapMaxBytesMaxGas(_, _ int64) types.Txs { return types.Txs{} } func (Mempool) ReapMaxTxs(n int) types.Txs { return types.Txs{} } func (Mempool) Update( @@ -44,22 +30,15 @@ func (Mempool) Update( ) error { return nil } -func (Mempool) Flush() {} -func (Mempool) FlushAppConn() error { return nil } -func (Mempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) } -func (Mempool) EnableTxsAvailable() {} -func (Mempool) SizeBytes() int64 { return 0 } - -func (m Mempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { - tx, ok := m.txs[txKey] - return tx, ok -} -func (m Mempool) GetTxEvicted(txKey types.TxKey) bool { - return m.evictedTxs[txKey] -} - -func (Mempool) TxsFront() *clist.CElement { return nil } -func (Mempool) TxsWaitChan() <-chan struct{} { return nil } +func (Mempool) Flush() {} +func (Mempool) FlushAppConn() error { return nil } +func (Mempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) } +func (Mempool) EnableTxsAvailable() {} +func (Mempool) SizeBytes() int64 { return 0 } +func (m Mempool) GetTxByKey(types.TxKey) (types.Tx, bool) { return nil, false } +func (m Mempool) GetTxEvicted(types.TxKey) bool { return false } +func (Mempool) TxsFront() *clist.CElement { return nil } +func (Mempool) TxsWaitChan() <-chan struct{} { return nil } func (Mempool) InitWAL() error { return nil } func (Mempool) CloseWAL() {} diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index 6a9ed60159..d4c7aee2ba 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -217,7 +217,7 @@ func (txmp *TxMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo memp txKey := tx.Key() // Check for the transaction in the cache. - if !txmp.cache.Push(tx.Key()) { + if !txmp.cache.Push(txKey) { // If the cached transaction is also in the pool, record its sender. if elt, ok := txmp.txByKey[txKey]; ok { txmp.metrics.AlreadySeenTxs.Add(1) diff --git a/rpc/core/mocks/mempool.go b/rpc/core/mocks/mempool.go new file mode 100644 index 0000000000..dfe1818416 --- /dev/null +++ b/rpc/core/mocks/mempool.go @@ -0,0 +1,240 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./mempool/mempool.go + +// Package mock_mempool is a generated GoMock package. +package mock_mempool + +import ( + reflect "reflect" + + types "github.com/cometbft/cometbft/abci/types" + mempool "github.com/cometbft/cometbft/mempool" + types0 "github.com/cometbft/cometbft/types" + gomock "github.com/golang/mock/gomock" +) + +// MockMempool is a mock of Mempool interface. +type MockMempool struct { + ctrl *gomock.Controller + recorder *MockMempoolMockRecorder +} + +// MockMempoolMockRecorder is the mock recorder for MockMempool. +type MockMempoolMockRecorder struct { + mock *MockMempool +} + +// NewMockMempool creates a new mock instance. +func NewMockMempool(ctrl *gomock.Controller) *MockMempool { + mock := &MockMempool{ctrl: ctrl} + mock.recorder = &MockMempoolMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockMempool) EXPECT() *MockMempoolMockRecorder { + return m.recorder +} + +// CheckTx mocks base method. +func (m *MockMempool) CheckTx(tx types0.Tx, callback func(*types.Response), txInfo mempool.TxInfo) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckTx", tx, callback, txInfo) + ret0, _ := ret[0].(error) + return ret0 +} + +// CheckTx indicates an expected call of CheckTx. +func (mr *MockMempoolMockRecorder) CheckTx(tx, callback, txInfo interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckTx", reflect.TypeOf((*MockMempool)(nil).CheckTx), tx, callback, txInfo) +} + +// EnableTxsAvailable mocks base method. +func (m *MockMempool) EnableTxsAvailable() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "EnableTxsAvailable") +} + +// EnableTxsAvailable indicates an expected call of EnableTxsAvailable. +func (mr *MockMempoolMockRecorder) EnableTxsAvailable() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableTxsAvailable", reflect.TypeOf((*MockMempool)(nil).EnableTxsAvailable)) +} + +// Flush mocks base method. +func (m *MockMempool) Flush() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Flush") +} + +// Flush indicates an expected call of Flush. +func (mr *MockMempoolMockRecorder) Flush() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Flush", reflect.TypeOf((*MockMempool)(nil).Flush)) +} + +// FlushAppConn mocks base method. +func (m *MockMempool) FlushAppConn() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FlushAppConn") + ret0, _ := ret[0].(error) + return ret0 +} + +// FlushAppConn indicates an expected call of FlushAppConn. +func (mr *MockMempoolMockRecorder) FlushAppConn() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FlushAppConn", reflect.TypeOf((*MockMempool)(nil).FlushAppConn)) +} + +// GetTxByKey mocks base method. +func (m *MockMempool) GetTxByKey(key types0.TxKey) (types0.Tx, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTxByKey", key) + ret0, _ := ret[0].(types0.Tx) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetTxByKey indicates an expected call of GetTxByKey. +func (mr *MockMempoolMockRecorder) GetTxByKey(key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTxByKey", reflect.TypeOf((*MockMempool)(nil).GetTxByKey), key) +} + +// GetTxEvicted mocks base method. +func (m *MockMempool) GetTxEvicted(key types0.TxKey) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTxEvicted", key) + ret0, _ := ret[0].(bool) + return ret0 +} + +// GetTxEvicted indicates an expected call of GetTxEvicted. +func (mr *MockMempoolMockRecorder) GetTxEvicted(key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTxEvicted", reflect.TypeOf((*MockMempool)(nil).GetTxEvicted), key) +} + +// Lock mocks base method. +func (m *MockMempool) Lock() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Lock") +} + +// Lock indicates an expected call of Lock. +func (mr *MockMempoolMockRecorder) Lock() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Lock", reflect.TypeOf((*MockMempool)(nil).Lock)) +} + +// ReapMaxBytesMaxGas mocks base method. +func (m *MockMempool) ReapMaxBytesMaxGas(maxBytes, maxGas int64) types0.Txs { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReapMaxBytesMaxGas", maxBytes, maxGas) + ret0, _ := ret[0].(types0.Txs) + return ret0 +} + +// ReapMaxBytesMaxGas indicates an expected call of ReapMaxBytesMaxGas. +func (mr *MockMempoolMockRecorder) ReapMaxBytesMaxGas(maxBytes, maxGas interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReapMaxBytesMaxGas", reflect.TypeOf((*MockMempool)(nil).ReapMaxBytesMaxGas), maxBytes, maxGas) +} + +// ReapMaxTxs mocks base method. +func (m *MockMempool) ReapMaxTxs(max int) types0.Txs { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReapMaxTxs", max) + ret0, _ := ret[0].(types0.Txs) + return ret0 +} + +// ReapMaxTxs indicates an expected call of ReapMaxTxs. +func (mr *MockMempoolMockRecorder) ReapMaxTxs(max interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReapMaxTxs", reflect.TypeOf((*MockMempool)(nil).ReapMaxTxs), max) +} + +// RemoveTxByKey mocks base method. +func (m *MockMempool) RemoveTxByKey(txKey types0.TxKey) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RemoveTxByKey", txKey) + ret0, _ := ret[0].(error) + return ret0 +} + +// RemoveTxByKey indicates an expected call of RemoveTxByKey. +func (mr *MockMempoolMockRecorder) RemoveTxByKey(txKey interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveTxByKey", reflect.TypeOf((*MockMempool)(nil).RemoveTxByKey), txKey) +} + +// Size mocks base method. +func (m *MockMempool) Size() int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Size") + ret0, _ := ret[0].(int) + return ret0 +} + +// Size indicates an expected call of Size. +func (mr *MockMempoolMockRecorder) Size() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Size", reflect.TypeOf((*MockMempool)(nil).Size)) +} + +// SizeBytes mocks base method. +func (m *MockMempool) SizeBytes() int64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SizeBytes") + ret0, _ := ret[0].(int64) + return ret0 +} + +// SizeBytes indicates an expected call of SizeBytes. +func (mr *MockMempoolMockRecorder) SizeBytes() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SizeBytes", reflect.TypeOf((*MockMempool)(nil).SizeBytes)) +} + +// TxsAvailable mocks base method. +func (m *MockMempool) TxsAvailable() <-chan struct{} { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TxsAvailable") + ret0, _ := ret[0].(<-chan struct{}) + return ret0 +} + +// TxsAvailable indicates an expected call of TxsAvailable. +func (mr *MockMempoolMockRecorder) TxsAvailable() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxsAvailable", reflect.TypeOf((*MockMempool)(nil).TxsAvailable)) +} + +// Unlock mocks base method. +func (m *MockMempool) Unlock() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Unlock") +} + +// Unlock indicates an expected call of Unlock. +func (mr *MockMempoolMockRecorder) Unlock() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unlock", reflect.TypeOf((*MockMempool)(nil).Unlock)) +} + +// Update mocks base method. +func (m *MockMempool) Update(blockHeight int64, blockTxs types0.Txs, deliverTxResponses []*types.ResponseDeliverTx, newPreFn mempool.PreCheckFunc, newPostFn mempool.PostCheckFunc) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", blockHeight, blockTxs, deliverTxResponses, newPreFn, newPostFn) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockMempoolMockRecorder) Update(blockHeight, blockTxs, deliverTxResponses, newPreFn, newPostFn interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockMempool)(nil).Update), blockHeight, blockTxs, deliverTxResponses, newPreFn, newPostFn) +} diff --git a/rpc/core/tx.go b/rpc/core/tx.go index 01d4cbc0b4..e8024c47c9 100644 --- a/rpc/core/tx.go +++ b/rpc/core/tx.go @@ -17,6 +17,13 @@ import ( "github.com/cometbft/cometbft/types" ) +const ( + txStatusUnknown string = "UNKNOWN" + txStatusPending string = "PENDING" + txStatusEvicted string = "EVICTED" + txStatusCommitted string = "COMMITTED" +) + // Tx allows you to query the transaction results. `nil` could mean the // transaction is in the mempool, invalidated, or was not sent in the first // place. @@ -214,6 +221,40 @@ func ProveShares( return &ctypes.ResultShareProof{Proof: shareProof}, nil } +// TxStatus retrieves the status of a transaction given its hash. It returns a ResultTxStatus +// containing the height and index of the transaction within the block(if committed) +// or whether the transaction is pending, evicted from the mempool, or otherwise unknown. +func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error) { + env := GetEnvironment() + + // Get the tx key from the hash + txKey, err := types.TxKeyFromBytes(hash) + if err != nil { + return nil, fmt.Errorf("failed to get tx key from hash: %v", err) + } + + // Check if the tx is in the mempool + txInMempool, ok := env.Mempool.GetTxByKey(txKey) + if txInMempool != nil && ok { + return &ctypes.ResultTxStatus{Status: txStatusPending}, nil + } + + // Check if the tx is evicted + isEvicted := env.Mempool.GetTxEvicted(txKey) + if isEvicted { + return &ctypes.ResultTxStatus{Status: txStatusEvicted}, nil + } + + // Check if the tx has been committed + txInfo := env.BlockStore.LoadTxInfo(hash) + if txInfo != nil { + return &ctypes.ResultTxStatus{Height: txInfo.Height, Index: txInfo.Index, Status: txStatusCommitted}, nil + } + + // If the tx is not in the mempool, evicted, or committed, return unknown + return &ctypes.ResultTxStatus{Status: txStatusUnknown}, nil +} + func loadRawBlock(bs state.BlockStore, height int64) ([]byte, error) { var blockMeta = bs.LoadBlockMeta(height) if blockMeta == nil { diff --git a/rpc/core/tx_status.go b/rpc/core/tx_status.go deleted file mode 100644 index b9d733ca12..0000000000 --- a/rpc/core/tx_status.go +++ /dev/null @@ -1,43 +0,0 @@ -package core - -import ( - "fmt" - - ctypes "github.com/cometbft/cometbft/rpc/core/types" - rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" - types "github.com/cometbft/cometbft/types" -) - -// TxStatus retrieves the status of a transaction given its hash. It returns a ResultTxStatus -// containing the height and index of the transaction within the block(if committed) -// or whether the transaction is pending, evicted from the mempool, or otherwise unknown. -func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error) { - env := GetEnvironment() - - // Get the tx key from the hash - txKey, err := types.TxKeyFromBytes(hash) - if err != nil { - return nil, fmt.Errorf("failed to get tx key from hash: %v", err) - } - - // Check if the tx is in the mempool - txInMempool, ok := env.Mempool.GetTxByKey(txKey) - if txInMempool != nil && ok { - return &ctypes.ResultTxStatus{Status: "PENDING"}, nil - } - - // Check if the tx is evicted - isEvicted := env.Mempool.GetTxEvicted(txKey) - if isEvicted { - return &ctypes.ResultTxStatus{Status: "EVICTED"}, nil - } - - // Check if the tx has been committed - txInfo := env.BlockStore.LoadTxInfo(hash) - if txInfo != nil { - return &ctypes.ResultTxStatus{Height: txInfo.Height, Index: txInfo.Index, Status: "COMMITTED"}, nil - } - - // If the tx is not in the mempool, evicted, or committed, return unknown - return &ctypes.ResultTxStatus{Status: "UNKNOWN"}, nil -} diff --git a/rpc/core/tx_status_test.go b/rpc/core/tx_status_test.go index 6e0d9b9f9e..7d59ae9886 100644 --- a/rpc/core/tx_status_test.go +++ b/rpc/core/tx_status_test.go @@ -3,23 +3,26 @@ package core import ( "testing" - mempl "github.com/cometbft/cometbft/mempool" - "github.com/cometbft/cometbft/mempool/mock" + mock "github.com/cometbft/cometbft/rpc/core/mocks" rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" types "github.com/cometbft/cometbft/types" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // TestTxStatus tests the TxStatus function in the RPC core // making sure it fetches the correct status for each transaction. func TestTxStatus(t *testing.T) { + // Create a controller + ctrl := gomock.NewController(t) + defer ctrl.Finish() + // Create a new environment env := &Environment{} // Create a new mempool and block store - mempool := mock.Mempool{} - env.Mempool = &mempool + mempool := mock.NewMockMempool(ctrl) + env.Mempool = mempool blockStore := mockBlockStore{ height: 0, blocks: nil, @@ -35,13 +38,17 @@ func TestTxStatus(t *testing.T) { { name: "Committed", setup: func(env *Environment, txs []types.Tx) { - height := int64(50) + height := int64(5) blocks := randomBlocks(height) blockStore = mockBlockStore{ height: height, blocks: blocks, } env.BlockStore = blockStore + for _, tx := range txs { + mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() + mempool.EXPECT().GetTxEvicted(tx.Key()).Return(false).AnyTimes() + } }, expectedStatus: "COMMITTED", }, @@ -52,7 +59,12 @@ func TestTxStatus(t *testing.T) { height: 0, blocks: nil, } + for _, tx := range txs { + mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() + mempool.EXPECT().GetTxEvicted(tx.Key()).Return(false).AnyTimes() + } }, + expectedStatus: "UNKNOWN", }, { @@ -62,9 +74,13 @@ func TestTxStatus(t *testing.T) { height: 0, blocks: nil, } + // Reset the mempool + mempool = mock.NewMockMempool(ctrl) + env.Mempool = mempool + for _, tx := range txs { - err := mempool.CheckTx(tx, nil, mempl.TxInfo{}) - require.NoError(t, err) + // Set up the mock mempool to return the transaction and true when GetTxByKey is called with the transaction's key + mempool.EXPECT().GetTxByKey(tx.Key()).Return(tx, true).AnyTimes() } }, expectedStatus: "PENDING", @@ -76,11 +92,13 @@ func TestTxStatus(t *testing.T) { height: 0, blocks: nil, } + // Reset the mempool + mempool = mock.NewMockMempool(ctrl) + env.Mempool = mempool + for _, tx := range txs { - err := mempool.CheckTx(tx, nil, mempl.TxInfo{}) - require.NoError(t, err) - err = mempool.RemoveTxByKey(tx.Key()) - require.NoError(t, err) + mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() + mempool.EXPECT().GetTxEvicted(tx.Key()).Return(true).AnyTimes() } }, expectedStatus: "EVICTED", @@ -89,26 +107,27 @@ func TestTxStatus(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - txs := makeTxs(2) + height := int64(2) + // Create a set of transactions on the specificed height + txs := makeTxs(height) tt.setup(env, txs) // Check the status of each transaction - for _, tx := range txs { + for i, tx := range txs { txStatus, _ := TxStatus(&rpctypes.Context{}, tx.Hash()) assert.Equal(t, tt.expectedStatus, txStatus.Status) - } - // Check the height and index of transactions that are committed - if blockStore.height > 0 && tt.expectedStatus == "COMMITTED" { - for _, block := range blockStore.blocks { - for i, tx := range block.Txs { - txStatus, _ := TxStatus(&rpctypes.Context{}, tx.Hash()) - assert.Equal(t, block.Height, txStatus.Height) - assert.Equal(t, int64(i), txStatus.Index) - } + // Check the height and index of transactions that are committed + if blockStore.height > 0 && tt.expectedStatus == "COMMITTED" { + txStatus, _ := TxStatus(&rpctypes.Context{}, tx.Hash()) + + assert.Equal(t, txStatus.Status, tt.expectedStatus) + assert.Equal(t, height, txStatus.Height) + assert.Equal(t, int64(i), txStatus.Index) } } + }) } } diff --git a/state/execution_test.go b/state/execution_test.go index 94b14dc55e..4f03832a09 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -58,7 +58,7 @@ func TestApplyBlock(t *testing.T) { }) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - &mmock.Mempool{}, sm.EmptyEvidencePool{}) + mmock.Mempool{}, sm.EmptyEvidencePool{}) block := makeBlock(state, 1) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()} @@ -223,7 +223,7 @@ func TestBeginBlockByzantineValidators(t *testing.T) { evpool.On("CheckEvidence", mock.AnythingOfType("types.EvidenceList")).Return(nil) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - &mmock.Mempool{}, evpool) + mmock.Mempool{}, evpool) block := makeBlock(state, 1) block.Evidence = types.EvidenceData{Evidence: ev} @@ -254,7 +254,7 @@ func TestProcessProposal(t *testing.T) { }) blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), - &mmock.Mempool{}, sm.EmptyEvidencePool{}) + mmock.Mempool{}, sm.EmptyEvidencePool{}) block := sf.MakeBlock(state, int64(height), new(types.Commit)) block.Txs = txs @@ -336,7 +336,7 @@ func makeBlockExec(t *testing.T, testName string, block *types.Block, stateDB db }), log.TestingLogger(), proxyApp.Consensus(), - &mmock.Mempool{}, + mmock.Mempool{}, sm.EmptyEvidencePool{}, sm.BlockExecutorWithMetrics(metrics), ) @@ -506,7 +506,7 @@ func TestEndBlockValidatorUpdates(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - &mmock.Mempool{}, + mmock.Mempool{}, sm.EmptyEvidencePool{}, ) @@ -578,7 +578,7 @@ func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - &mmock.Mempool{}, + mmock.Mempool{}, sm.EmptyEvidencePool{}, ) @@ -615,7 +615,7 @@ func TestFireEventSignedBlockEvent(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - &mmock.Mempool{}, + mmock.Mempool{}, sm.EmptyEvidencePool{}, ) eventBus := types.NewEventBus() diff --git a/state/validation_test.go b/state/validation_test.go index c075652484..dbb94cbb1d 100644 --- a/state/validation_test.go +++ b/state/validation_test.go @@ -36,7 +36,7 @@ func TestValidateBlockHeader(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - &memmock.Mempool{}, + memmock.Mempool{}, sm.EmptyEvidencePool{}, ) lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) @@ -121,7 +121,7 @@ func TestValidateBlockCommit(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - &memmock.Mempool{}, + memmock.Mempool{}, sm.EmptyEvidencePool{}, ) lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) @@ -259,7 +259,7 @@ func TestValidateBlockEvidence(t *testing.T) { stateStore, log.TestingLogger(), proxyApp.Consensus(), - &memmock.Mempool{}, + memmock.Mempool{}, evpool, ) lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) From 1cbb37d46c25d2b18ba724873a969ac4612f312d Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Tue, 11 Jun 2024 16:07:04 +0200 Subject: [PATCH 25/47] test: add more consistent comments --- rpc/core/tx_status_test.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rpc/core/tx_status_test.go b/rpc/core/tx_status_test.go index 7d59ae9886..6d472bcf8c 100644 --- a/rpc/core/tx_status_test.go +++ b/rpc/core/tx_status_test.go @@ -46,7 +46,9 @@ func TestTxStatus(t *testing.T) { } env.BlockStore = blockStore for _, tx := range txs { + // Set GetTxByKey to return nil and false for all transactions mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() + // Set GetTxEvicted to return false for all transactions mempool.EXPECT().GetTxEvicted(tx.Key()).Return(false).AnyTimes() } }, @@ -60,7 +62,9 @@ func TestTxStatus(t *testing.T) { blocks: nil, } for _, tx := range txs { + // Set GetTxByKey to return nil and false for all transactions mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() + // Set GetTxEvicted to return false for all transactions mempool.EXPECT().GetTxEvicted(tx.Key()).Return(false).AnyTimes() } }, @@ -79,7 +83,7 @@ func TestTxStatus(t *testing.T) { env.Mempool = mempool for _, tx := range txs { - // Set up the mock mempool to return the transaction and true when GetTxByKey is called with the transaction's key + // Set GetTxByKey to return the transaction and true for all transactions mempool.EXPECT().GetTxByKey(tx.Key()).Return(tx, true).AnyTimes() } }, @@ -97,7 +101,9 @@ func TestTxStatus(t *testing.T) { env.Mempool = mempool for _, tx := range txs { + // Set GetTxByKey to return nil and false for all transactions mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() + // Set GetTxEvicted to return true for all transactions mempool.EXPECT().GetTxEvicted(tx.Key()).Return(true).AnyTimes() } }, @@ -108,7 +114,7 @@ func TestTxStatus(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { height := int64(2) - // Create a set of transactions on the specificed height + // Create a set of transactions on the specified height txs := makeTxs(height) tt.setup(env, txs) From a22978d0b95249e9415bdd6e7cfed8a4e7315cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 16:18:39 +0200 Subject: [PATCH 26/47] Update pool.go --- mempool/cat/pool.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mempool/cat/pool.go b/mempool/cat/pool.go index 0a55c24b3d..5909242001 100644 --- a/mempool/cat/pool.go +++ b/mempool/cat/pool.go @@ -174,12 +174,13 @@ func (txmp *TxPool) Has(txKey types.TxKey) bool { return txmp.store.has(txKey) } -// Gets tx by its key. Preserved to maintain API compatibility. +// Get retrieves a transaction based on the key. +// Preserved to maintain API compatibility. func (txmp *TxPool) Get(txKey types.TxKey) (types.Tx, bool) { return txmp.GetTxByKey(txKey) } -// GetTxByKey retrieves a transaction based on the˝ key. It returns a bool +// GetTxByKey retrieves a transaction based on the key. It returns a bool // indicating whether transaction was found in the cache. func (txmp *TxPool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { wtx := txmp.store.get(txKey) From 33e8bf3625cbaa30f2e2153c60d17cddb7c95ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 11 Jun 2024 16:21:52 +0200 Subject: [PATCH 27/47] Update mempool.go --- mempool/mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index 5da898fa04..87c4630dae 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -97,7 +97,7 @@ type Mempool interface { // GetTxEvicted returns true if the tx is evicted from the mempool and exists in the // evicted cache. - // Used in the RPC endpoint - TxStatus. + // Used in the RPC endpoint: TxStatus. GetTxEvicted(key types.TxKey) bool // Size returns the number of transactions in the mempool. From 709e6d386cddce727dccb14ee16ffc7d59c045e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Wed, 12 Jun 2024 12:46:59 +0200 Subject: [PATCH 28/47] Update mempool/v1/mempool.go Co-authored-by: Callum Waters --- mempool/v1/mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index d4c7aee2ba..bf5948e7df 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -570,7 +570,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon wtx.tx.Hash()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedNewTxFullMempool).Add(1) // Add it to evicted transactions cache - txmp.evictedTxs.Push(wtx.tx.Key()) + txmp.evictedTxs.Push(wtx.key) return } From 39f1deb3027adc3a6e5578ec805ec66f8636d04a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Wed, 12 Jun 2024 12:47:20 +0200 Subject: [PATCH 29/47] Update mempool/v1/mempool.go Co-authored-by: Callum Waters --- mempool/v1/mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index bf5948e7df..7fbd5cfc50 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -559,7 +559,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon // those candidates is not enough to make room for the new transaction, // drop the new one. if len(victims) == 0 || victimBytes < wtx.Size() { - txmp.cache.Remove(wtx.tx.Key()) + txmp.cache.Remove(wtx.key) txmp.logger.Error( "rejected valid incoming transaction; mempool is full", "tx", fmt.Sprintf("%X", wtx.tx.Hash()), From 58929bbc2e745f714023548c8245f3a85113a89e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Wed, 12 Jun 2024 13:51:57 +0200 Subject: [PATCH 30/47] Update mempool/cat/pool_test.go Co-authored-by: Rootul P --- mempool/cat/pool_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/cat/pool_test.go b/mempool/cat/pool_test.go index c50d79a213..2bf62faa4b 100644 --- a/mempool/cat/pool_test.go +++ b/mempool/cat/pool_test.go @@ -576,7 +576,7 @@ func TestTxPool_ExpiredTxs_Timestamp(t *testing.T) { // All the transactions in the original set should have been purged. for _, tx := range added1 { - // Check that it was added to the evictedTxCache store + // Check that it was added to the evictedTxCache evicted := txmp.GetTxEvicted(tx.tx.Key()) require.True(t, evicted) From 840b61d77e5f332c886cfd7aceca7246c5ff22a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Wed, 12 Jun 2024 13:55:05 +0200 Subject: [PATCH 31/47] Update mempool/cat/pool.go Co-authored-by: Rootul P --- mempool/cat/pool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/cat/pool.go b/mempool/cat/pool.go index 5909242001..cda78c81c6 100644 --- a/mempool/cat/pool.go +++ b/mempool/cat/pool.go @@ -175,7 +175,7 @@ func (txmp *TxPool) Has(txKey types.TxKey) bool { } // Get retrieves a transaction based on the key. -// Preserved to maintain API compatibility. +// Deprecated: use GetTxByKey instead. func (txmp *TxPool) Get(txKey types.TxKey) (types.Tx, bool) { return txmp.GetTxByKey(txKey) } From d21e0849b8bc3d553e4ed2d43ff954239704b064 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 13 Jun 2024 13:19:25 +0200 Subject: [PATCH 32/47] refacotor: address review comments --- consensus/replay_stubs.go | 2 +- mempool/cache_bench_test.go | 26 ++++++++++++++++--------- mempool/cat/pool.go | 4 ++-- mempool/cat/pool_test.go | 20 +++++++++---------- mempool/mempool.go | 6 +++--- mempool/mock/mempool.go | 2 +- mempool/v0/clist_mempool.go | 4 ++-- mempool/v1/mempool.go | 9 +++++---- mempool/v1/mempool_test.go | 22 ++++++++++----------- rpc/core/mocks/mempool.go | 12 ++++++------ rpc/core/tx.go | 2 +- rpc/core/tx_status_test.go | 12 ++++++------ test/maverick/consensus/replay_stubs.go | 2 +- 13 files changed, 66 insertions(+), 57 deletions(-) diff --git a/consensus/replay_stubs.go b/consensus/replay_stubs.go index 86af9ed857..6e3d80f488 100644 --- a/consensus/replay_stubs.go +++ b/consensus/replay_stubs.go @@ -50,7 +50,7 @@ func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } func (emptyMempool) InitWAL() error { return nil } func (emptyMempool) CloseWAL() {} func (emptyMempool) GetTxByKey(types.TxKey) (types.Tx, bool) { return nil, false } -func (emptyMempool) GetTxEvicted(types.TxKey) bool { return false } +func (emptyMempool) IsTxEvicted(types.TxKey) bool { return false } //----------------------------------------------------------------------------- // mockProxyApp uses ABCIResponses to give the right results. diff --git a/mempool/cache_bench_test.go b/mempool/cache_bench_test.go index 4b235092ba..fd7609cf10 100644 --- a/mempool/cache_bench_test.go +++ b/mempool/cache_bench_test.go @@ -1,6 +1,7 @@ package mempool import ( + "crypto/rand" "encoding/binary" "testing" @@ -10,16 +11,20 @@ import ( func BenchmarkCacheInsertTime(b *testing.B) { cache := NewLRUTxCache(b.N) - txs := make([][]byte, b.N) + keys := make([][]byte, b.N) for i := 0; i < b.N; i++ { - txs[i] = make([]byte, 8) - binary.BigEndian.PutUint64(txs[i], uint64(i)) + keys[i] = make([]byte, 32) + _, err := rand.Read(keys[i]) + if err != nil { + b.Fatal(err) + } + binary.BigEndian.PutUint64(keys[i], uint64(i)) } b.ResetTimer() for i := 0; i < b.N; i++ { - cache.Push(types.Tx(txs[i]).Key()) + cache.Push(types.TxKey(keys[i])) } } @@ -28,16 +33,19 @@ func BenchmarkCacheInsertTime(b *testing.B) { func BenchmarkCacheRemoveTime(b *testing.B) { cache := NewLRUTxCache(b.N) - txs := make([][]byte, b.N) + keys := make([][]byte, b.N) for i := 0; i < b.N; i++ { - txs[i] = make([]byte, 8) - binary.BigEndian.PutUint64(txs[i], uint64(i)) - cache.Push(types.Tx(txs[i]).Key()) + keys[i] = make([]byte, 32) + _, err := rand.Read(keys[i]) + if err != nil { + b.Fatal(err) + } + cache.Push(types.TxKey(keys[i])) } b.ResetTimer() for i := 0; i < b.N; i++ { - cache.Remove(types.Tx(txs[i]).Key()) + cache.Remove(types.TxKey(keys[i])) } } diff --git a/mempool/cat/pool.go b/mempool/cat/pool.go index cda78c81c6..9584720036 100644 --- a/mempool/cat/pool.go +++ b/mempool/cat/pool.go @@ -190,9 +190,9 @@ func (txmp *TxPool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { return types.Tx{}, false } -// GetTxEvicted returns a bool indicating whether the transaction with +// IsTxEvicted returns a bool indicating whether the transaction with // the specified key was recently evicted and is currently within the cache. -func (txmp *TxPool) GetTxEvicted(txKey types.TxKey) bool { +func (txmp *TxPool) IsTxEvicted(txKey types.TxKey) bool { return txmp.evictedTxCache.Has(txKey) } diff --git a/mempool/cat/pool_test.go b/mempool/cat/pool_test.go index 2bf62faa4b..973f7e473d 100644 --- a/mempool/cat/pool_test.go +++ b/mempool/cat/pool_test.go @@ -244,7 +244,7 @@ func TestTxPool_Eviction(t *testing.T) { mustCheckTx(t, txmp, "key1=0000=25") require.True(t, txExists("key1=0000=25")) require.False(t, txExists(bigTx)) - require.True(t, txmp.GetTxEvicted(types.Tx(bigTx).Key())) + require.True(t, txmp.IsTxEvicted(types.Tx(bigTx).Key())) require.Equal(t, int64(len("key1=0000=25")), txmp.SizeBytes()) // Now fill up the rest of the slots with other transactions. @@ -258,27 +258,27 @@ func TestTxPool_Eviction(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "mempool is full") require.False(t, txExists("key6=0005=1")) - require.True(t, txmp.GetTxEvicted(types.Tx("key6=0005=1").Key())) + require.True(t, txmp.IsTxEvicted(types.Tx("key6=0005=1").Key())) // A new transaction with higher priority should evict key5, which is the // newest of the two transactions with lowest priority. mustCheckTx(t, txmp, "key7=0006=7") require.True(t, txExists("key7=0006=7")) // new transaction added require.False(t, txExists("key5=0004=3")) // newest low-priority tx evicted - require.True(t, txmp.GetTxEvicted(types.Tx("key5=0004=3").Key())) + require.True(t, txmp.IsTxEvicted(types.Tx("key5=0004=3").Key())) require.True(t, txExists("key4=0003=3")) // older low-priority tx retained // Another new transaction evicts the other low-priority element. mustCheckTx(t, txmp, "key8=0007=20") require.True(t, txExists("key8=0007=20")) require.False(t, txExists("key4=0003=3")) - require.True(t, txmp.GetTxEvicted(types.Tx("key4=0003=3").Key())) + require.True(t, txmp.IsTxEvicted(types.Tx("key4=0003=3").Key())) // Now the lowest-priority tx is 5, so that should be the next to go. mustCheckTx(t, txmp, "key9=0008=9") require.True(t, txExists("key9=0008=9")) require.False(t, txExists("key2=0001=5")) - require.True(t, txmp.GetTxEvicted(types.Tx("key2=0001=5").Key())) + require.True(t, txmp.IsTxEvicted(types.Tx("key2=0001=5").Key())) // Add a transaction that requires eviction of multiple lower-priority // entries, in order to fit the size of the element. @@ -287,11 +287,11 @@ func TestTxPool_Eviction(t *testing.T) { require.True(t, txExists("key8=0007=20")) require.True(t, txExists("key10=0123456789abcdef=11")) require.False(t, txExists("key3=0002=10")) - require.True(t, txmp.GetTxEvicted(types.Tx("key3=0002=10").Key())) + require.True(t, txmp.IsTxEvicted(types.Tx("key3=0002=10").Key())) require.False(t, txExists("key9=0008=9")) - require.True(t, txmp.GetTxEvicted(types.Tx("key9=0008=9").Key())) + require.True(t, txmp.IsTxEvicted(types.Tx("key9=0008=9").Key())) require.False(t, txExists("key7=0006=7")) - require.True(t, txmp.GetTxEvicted(types.Tx("key7=0006=7").Key())) + require.True(t, txmp.IsTxEvicted(types.Tx("key7=0006=7").Key())) // Free up some space so we can add back previously evicted txs err = txmp.Update(1, types.Txs{types.Tx("key10=0123456789abcdef=11")}, []*abci.ResponseDeliverTx{{Code: abci.CodeTypeOK}}, nil, nil) @@ -304,7 +304,7 @@ func TestTxPool_Eviction(t *testing.T) { // space for the previously evicted tx require.NoError(t, txmp.RemoveTxByKey(types.Tx("key8=0007=20").Key())) require.False(t, txExists("key8=0007=20")) - require.False(t, txmp.GetTxEvicted(types.Tx("key8=0007=20").Key())) + require.False(t, txmp.IsTxEvicted(types.Tx("key8=0007=20").Key())) } func TestTxPool_Flush(t *testing.T) { @@ -577,7 +577,7 @@ func TestTxPool_ExpiredTxs_Timestamp(t *testing.T) { // All the transactions in the original set should have been purged. for _, tx := range added1 { // Check that it was added to the evictedTxCache - evicted := txmp.GetTxEvicted(tx.tx.Key()) + evicted := txmp.IsTxEvicted(tx.tx.Key()) require.True(t, evicted) if txmp.store.has(tx.tx.Key()) { diff --git a/mempool/mempool.go b/mempool/mempool.go index 87c4630dae..f983fc45d7 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -95,10 +95,10 @@ type Mempool interface { // Used in the RPC endpoint: TxStatus. GetTxByKey(key types.TxKey) (types.Tx, bool) - // GetTxEvicted returns true if the tx is evicted from the mempool and exists in the + // IsTxEvicted returns true if the tx is evicted from the mempool and exists in the // evicted cache. - // Used in the RPC endpoint: TxStatus. - GetTxEvicted(key types.TxKey) bool + // Used in the RPC endpoint - TxStatus. + IsTxEvicted(key types.TxKey) bool // Size returns the number of transactions in the mempool. Size() int diff --git a/mempool/mock/mempool.go b/mempool/mock/mempool.go index ca6385a328..3f5711a5c1 100644 --- a/mempool/mock/mempool.go +++ b/mempool/mock/mempool.go @@ -36,7 +36,7 @@ func (Mempool) TxsAvailable() <-chan struct{} { return make(chan str func (Mempool) EnableTxsAvailable() {} func (Mempool) SizeBytes() int64 { return 0 } func (m Mempool) GetTxByKey(types.TxKey) (types.Tx, bool) { return nil, false } -func (m Mempool) GetTxEvicted(types.TxKey) bool { return false } +func (m Mempool) IsTxEvicted(types.TxKey) bool { return false } func (Mempool) TxsFront() *clist.CElement { return nil } func (Mempool) TxsWaitChan() <-chan struct{} { return nil } diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index d7f38befe7..239e1628a6 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -188,8 +188,8 @@ func (mem *CListMempool) GetTxByKey(key types.TxKey) (types.Tx, bool) { return nil, false } -// GetTxEvicted is not supported by the v0 mempool but it is required to satisfy the mempool interface. -func (mem *CListMempool) GetTxEvicted(key types.TxKey) bool { +// IsTxEvicted is not supported by the v0 mempool but it is required to satisfy the mempool interface. +func (mem *CListMempool) IsTxEvicted(key types.TxKey) bool { return false } diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index 7fbd5cfc50..091b7f6816 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -273,9 +273,9 @@ func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { return nil, false } -// GetTxEvicted returns a bool indicating whether the transaction with +// IsTxEvicted returns a bool indicating whether the transaction with // the specified key was recently evicted and is currently within the cache. -func (txmp *TxMempool) GetTxEvicted(txKey types.TxKey) bool { +func (txmp *TxMempool) IsTxEvicted(txKey types.TxKey) bool { return txmp.evictedTxs.Has(txKey) } @@ -559,7 +559,8 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon // those candidates is not enough to make room for the new transaction, // drop the new one. if len(victims) == 0 || victimBytes < wtx.Size() { - txmp.cache.Remove(wtx.key) + wtxKey := wtx.tx.Key() + txmp.cache.Remove(wtxKey) txmp.logger.Error( "rejected valid incoming transaction; mempool is full", "tx", fmt.Sprintf("%X", wtx.tx.Hash()), @@ -570,7 +571,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon wtx.tx.Hash()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedNewTxFullMempool).Add(1) // Add it to evicted transactions cache - txmp.evictedTxs.Push(wtx.key) + txmp.evictedTxs.Push(wtxKey) return } diff --git a/mempool/v1/mempool_test.go b/mempool/v1/mempool_test.go index 80b02188e4..4b51d4a9d3 100644 --- a/mempool/v1/mempool_test.go +++ b/mempool/v1/mempool_test.go @@ -243,7 +243,7 @@ func TestTxMempool_Eviction(t *testing.T) { require.False(t, txExists(bigTx)) bigTxKey := types.Tx((bigTx)).Key() require.False(t, txmp.cache.Has(bigTxKey)) - require.True(t, txmp.GetTxEvicted(bigTxKey)) // bigTx evicted + require.True(t, txmp.IsTxEvicted(bigTxKey)) // bigTx evicted require.Equal(t, int64(len("key1=0000=25")), txmp.SizeBytes()) // Now fill up the rest of the slots with other transactions. @@ -255,15 +255,15 @@ func TestTxMempool_Eviction(t *testing.T) { // A new transaction with low priority should be discarded. mustCheckTx(t, txmp, "key6=0005=1") require.False(t, txExists("key6=0005=1")) - require.True(t, txmp.GetTxEvicted(types.Tx(("key6=0005=1")).Key())) // key6 evicted + require.True(t, txmp.IsTxEvicted(types.Tx(("key6=0005=1")).Key())) // key6 evicted // A new transaction with higher priority should evict key5, which is the // newest of the two transactions with lowest priority. mustCheckTx(t, txmp, "key7=0006=7") - require.True(t, txExists("key7=0006=7")) // new transaction added - require.False(t, txExists("key5=0004=3")) // newest low-priority tx evicted - require.True(t, txmp.GetTxEvicted(types.Tx(("key5=0004=3")).Key())) // key5 evicted - require.True(t, txExists("key4=0003=3")) // older low-priority tx retained + require.True(t, txExists("key7=0006=7")) // new transaction added + require.False(t, txExists("key5=0004=3")) // newest low-priority tx evicted + require.True(t, txmp.IsTxEvicted(types.Tx(("key5=0004=3")).Key())) // key5 evicted + require.True(t, txExists("key4=0003=3")) // older low-priority tx retained // Another new transaction evicts the other low-priority element. mustCheckTx(t, txmp, "key8=0007=20") @@ -274,7 +274,7 @@ func TestTxMempool_Eviction(t *testing.T) { mustCheckTx(t, txmp, "key9=0008=9") require.True(t, txExists("key9=0008=9")) require.False(t, txExists("key2=0001=5")) - require.True(t, txmp.GetTxEvicted(types.Tx(("key2=0001=5")).Key())) // key2 evicted + require.True(t, txmp.IsTxEvicted(types.Tx(("key2=0001=5")).Key())) // key2 evicted // Add a transaction that requires eviction of multiple lower-priority // entries, in order to fit the size of the element. @@ -283,11 +283,11 @@ func TestTxMempool_Eviction(t *testing.T) { require.True(t, txExists("key8=0007=20")) require.True(t, txExists("key10=0123456789abcdef=11")) require.False(t, txExists("key3=0002=10")) - require.True(t, txmp.GetTxEvicted(types.Tx(("key3=0002=10")).Key())) // key3 evicted + require.True(t, txmp.IsTxEvicted(types.Tx(("key3=0002=10")).Key())) // key3 evicted require.False(t, txExists("key9=0008=9")) - require.True(t, txmp.GetTxEvicted(types.Tx(("key9=0008=9")).Key())) // key9 evicted + require.True(t, txmp.IsTxEvicted(types.Tx(("key9=0008=9")).Key())) // key9 evicted require.False(t, txExists("key7=0006=7")) - require.True(t, txmp.GetTxEvicted(types.Tx(("key7=0006=7")).Key())) // key7 evicted + require.True(t, txmp.IsTxEvicted(types.Tx(("key7=0006=7")).Key())) // key7 evicted } func TestTxMempool_Flush(t *testing.T) { @@ -591,7 +591,7 @@ func TestTxMempool_ExpiredTxs_Timestamp(t *testing.T) { // All the transactions in the original set should have been purged. for _, tx := range added1 { // Check that they were adding to the evicted cache. - evicted := txmp.GetTxEvicted(tx.tx.Key()) + evicted := txmp.IsTxEvicted(tx.tx.Key()) require.True(t, evicted) if _, ok := txmp.txByKey[tx.tx.Key()]; ok { diff --git a/rpc/core/mocks/mempool.go b/rpc/core/mocks/mempool.go index dfe1818416..e9fbe4e784 100644 --- a/rpc/core/mocks/mempool.go +++ b/rpc/core/mocks/mempool.go @@ -103,18 +103,18 @@ func (mr *MockMempoolMockRecorder) GetTxByKey(key interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTxByKey", reflect.TypeOf((*MockMempool)(nil).GetTxByKey), key) } -// GetTxEvicted mocks base method. -func (m *MockMempool) GetTxEvicted(key types0.TxKey) bool { +// IsTxEvicted mocks base method. +func (m *MockMempool) IsTxEvicted(key types0.TxKey) bool { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTxEvicted", key) + ret := m.ctrl.Call(m, "IsTxEvicted", key) ret0, _ := ret[0].(bool) return ret0 } -// GetTxEvicted indicates an expected call of GetTxEvicted. -func (mr *MockMempoolMockRecorder) GetTxEvicted(key interface{}) *gomock.Call { +// IsTxEvicted indicates an expected call of IsTxEvicted. +func (mr *MockMempoolMockRecorder) IsTxEvicted(key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTxEvicted", reflect.TypeOf((*MockMempool)(nil).GetTxEvicted), key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsTxEvicted", reflect.TypeOf((*MockMempool)(nil).IsTxEvicted), key) } // Lock mocks base method. diff --git a/rpc/core/tx.go b/rpc/core/tx.go index e8024c47c9..67e9f34d96 100644 --- a/rpc/core/tx.go +++ b/rpc/core/tx.go @@ -240,7 +240,7 @@ func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error } // Check if the tx is evicted - isEvicted := env.Mempool.GetTxEvicted(txKey) + isEvicted := env.Mempool.IsTxEvicted(txKey) if isEvicted { return &ctypes.ResultTxStatus{Status: txStatusEvicted}, nil } diff --git a/rpc/core/tx_status_test.go b/rpc/core/tx_status_test.go index 6d472bcf8c..5d994ba14d 100644 --- a/rpc/core/tx_status_test.go +++ b/rpc/core/tx_status_test.go @@ -48,8 +48,8 @@ func TestTxStatus(t *testing.T) { for _, tx := range txs { // Set GetTxByKey to return nil and false for all transactions mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() - // Set GetTxEvicted to return false for all transactions - mempool.EXPECT().GetTxEvicted(tx.Key()).Return(false).AnyTimes() + // Set IsTxEvicted to return false for all transactions + mempool.EXPECT().IsTxEvicted(tx.Key()).Return(false).AnyTimes() } }, expectedStatus: "COMMITTED", @@ -64,8 +64,8 @@ func TestTxStatus(t *testing.T) { for _, tx := range txs { // Set GetTxByKey to return nil and false for all transactions mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() - // Set GetTxEvicted to return false for all transactions - mempool.EXPECT().GetTxEvicted(tx.Key()).Return(false).AnyTimes() + // Set IsTxEvicted to return false for all transactions + mempool.EXPECT().IsTxEvicted(tx.Key()).Return(false).AnyTimes() } }, @@ -103,8 +103,8 @@ func TestTxStatus(t *testing.T) { for _, tx := range txs { // Set GetTxByKey to return nil and false for all transactions mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() - // Set GetTxEvicted to return true for all transactions - mempool.EXPECT().GetTxEvicted(tx.Key()).Return(true).AnyTimes() + // Set IsTxEvicted to return true for all transactions + mempool.EXPECT().IsTxEvicted(tx.Key()).Return(true).AnyTimes() } }, expectedStatus: "EVICTED", diff --git a/test/maverick/consensus/replay_stubs.go b/test/maverick/consensus/replay_stubs.go index e300fb1641..51064a839b 100644 --- a/test/maverick/consensus/replay_stubs.go +++ b/test/maverick/consensus/replay_stubs.go @@ -41,7 +41,7 @@ func (emptyMempool) EnableTxsAvailable() {} func (emptyMempool) TxsBytes() int64 { return 0 } func (emptyMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { return nil, false } -func (emptyMempool) GetTxEvicted(txKey types.TxKey) bool { return false } +func (emptyMempool) IsTxEvicted(txKey types.TxKey) bool { return false } func (emptyMempool) TxsFront() *clist.CElement { return nil } func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } From 486888efe076bbbb57fa84f49a5007b15a68fec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Thu, 13 Jun 2024 13:35:21 +0200 Subject: [PATCH 33/47] Update mempool.go --- mempool/mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index f983fc45d7..5eb51c0bc4 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -97,7 +97,7 @@ type Mempool interface { // IsTxEvicted returns true if the tx is evicted from the mempool and exists in the // evicted cache. - // Used in the RPC endpoint - TxStatus. + // Used in the RPC endpoint: TxStatus. IsTxEvicted(key types.TxKey) bool // Size returns the number of transactions in the mempool. From 8a5bbaedf9cc4ffbd029667b601366ef94905e07 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 13 Jun 2024 16:14:09 +0200 Subject: [PATCH 34/47] refactor: revert mempool cache changes --- mempool/cache.go | 42 ++++++++++++++++++++++---------- mempool/cache_bench_test.go | 30 ++++++++--------------- mempool/cache_test.go | 4 +-- mempool/v0/clist_mempool.go | 12 ++++----- mempool/v0/clist_mempool_test.go | 2 +- mempool/v1/mempool.go | 31 ++++++++++++----------- mempool/v1/mempool_test.go | 4 +-- 7 files changed, 65 insertions(+), 60 deletions(-) diff --git a/mempool/cache.go b/mempool/cache.go index df4e7a3c00..330c65f480 100644 --- a/mempool/cache.go +++ b/mempool/cache.go @@ -16,16 +16,20 @@ type TxCache interface { // Reset resets the cache to an empty state. Reset() - // Push adds the given tx key to the cache and returns true if it was + // Push adds the given raw transaction to the cache and returns true if it was // newly added. Otherwise, it returns false. - Push(tx types.TxKey) bool + Push(tx types.Tx) bool - // Remove removes the given tx key from the cache. - Remove(tx types.TxKey) + // Remove removes the given raw transaction from the cache. + Remove(tx types.Tx) - // Has reports whether tx key is present in the cache. Checking for presence is + // Has reports whether tx is present in the cache. Checking for presence is // not treated as an access of the value. - Has(tx types.TxKey) bool + Has(tx types.Tx) bool + + // HasKey reports whether the given key is present in the cache. Checking for + // presence is not treated as an access of the value. + HasKey(key types.TxKey) bool } var _ TxCache = (*LRUTxCache)(nil) @@ -61,10 +65,12 @@ func (c *LRUTxCache) Reset() { c.list.Init() } -func (c *LRUTxCache) Push(key types.TxKey) bool { +func (c *LRUTxCache) Push(tx types.Tx) bool { c.mtx.Lock() defer c.mtx.Unlock() + key := tx.Key() + moved, ok := c.cacheMap[key] if ok { c.list.MoveToBack(moved) @@ -86,7 +92,8 @@ func (c *LRUTxCache) Push(key types.TxKey) bool { return true } -func (c *LRUTxCache) Remove(key types.TxKey) { +func (c *LRUTxCache) Remove(tx types.Tx) { + key := tx.Key() c.RemoveTxByKey(key) } @@ -102,7 +109,15 @@ func (c *LRUTxCache) RemoveTxByKey(key types.TxKey) { } } -func (c *LRUTxCache) Has(key types.TxKey) bool { +func (c *LRUTxCache) Has(tx types.Tx) bool { + c.mtx.Lock() + defer c.mtx.Unlock() + + _, ok := c.cacheMap[tx.Key()] + return ok +} + +func (c *LRUTxCache) HasKey(key types.TxKey) bool { c.mtx.Lock() defer c.mtx.Unlock() @@ -115,7 +130,8 @@ type NopTxCache struct{} var _ TxCache = (*NopTxCache)(nil) -func (NopTxCache) Reset() {} -func (NopTxCache) Push(types.TxKey) bool { return true } -func (NopTxCache) Remove(types.TxKey) {} -func (NopTxCache) Has(types.TxKey) bool { return false } +func (NopTxCache) Reset() {} +func (NopTxCache) Push(types.Tx) bool { return true } +func (NopTxCache) Remove(types.Tx) {} +func (NopTxCache) Has(types.Tx) bool { return false } +func (NopTxCache) HasKey(types.TxKey) bool { return false } diff --git a/mempool/cache_bench_test.go b/mempool/cache_bench_test.go index fd7609cf10..551f3268d5 100644 --- a/mempool/cache_bench_test.go +++ b/mempool/cache_bench_test.go @@ -1,30 +1,23 @@ package mempool import ( - "crypto/rand" "encoding/binary" "testing" - - "github.com/cometbft/cometbft/types" ) func BenchmarkCacheInsertTime(b *testing.B) { cache := NewLRUTxCache(b.N) - keys := make([][]byte, b.N) + txs := make([][]byte, b.N) for i := 0; i < b.N; i++ { - keys[i] = make([]byte, 32) - _, err := rand.Read(keys[i]) - if err != nil { - b.Fatal(err) - } - binary.BigEndian.PutUint64(keys[i], uint64(i)) + txs[i] = make([]byte, 8) + binary.BigEndian.PutUint64(txs[i], uint64(i)) } b.ResetTimer() for i := 0; i < b.N; i++ { - cache.Push(types.TxKey(keys[i])) + cache.Push(txs[i]) } } @@ -33,19 +26,16 @@ func BenchmarkCacheInsertTime(b *testing.B) { func BenchmarkCacheRemoveTime(b *testing.B) { cache := NewLRUTxCache(b.N) - keys := make([][]byte, b.N) + txs := make([][]byte, b.N) for i := 0; i < b.N; i++ { - keys[i] = make([]byte, 32) - _, err := rand.Read(keys[i]) - if err != nil { - b.Fatal(err) - } - cache.Push(types.TxKey(keys[i])) + txs[i] = make([]byte, 8) + binary.BigEndian.PutUint64(txs[i], uint64(i)) + cache.Push(txs[i]) } b.ResetTimer() for i := 0; i < b.N; i++ { - cache.Remove(types.TxKey(keys[i])) + cache.Remove(txs[i]) } -} +} \ No newline at end of file diff --git a/mempool/cache_test.go b/mempool/cache_test.go index 0cc7e09d8c..b69fb40b7c 100644 --- a/mempool/cache_test.go +++ b/mempool/cache_test.go @@ -21,7 +21,7 @@ func populate(cache TxCache, numTxs int) ([][]byte, error) { } txs[i] = txBytes - cache.Push(types.Tx(txBytes).Key()) + cache.Push(txBytes) } return txs, nil @@ -37,7 +37,7 @@ func TestCacheRemove(t *testing.T) { require.Equal(t, numTxs, cache.list.Len()) for i := 0; i < numTxs; i++ { - cache.Remove(types.Tx(txs[i]).Key()) + cache.Remove(txs[i]) // make sure its removed from both the map and the linked list require.Equal(t, numTxs-(i+1), len(cache.cacheMap)) require.Equal(t, numTxs-(i+1), cache.list.Len()) diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index 239e1628a6..d2a75a0b93 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -246,7 +246,7 @@ func (mem *CListMempool) CheckTx( return err } - if !mem.cache.Push(tx.Key()) { // if the transaction already exists in the cache + if !mem.cache.Push(tx) { // if the transaction already exists in the cache // Record a new sender for a tx we've already seen. // 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), @@ -346,7 +346,7 @@ func (mem *CListMempool) removeTx(tx types.Tx, elem *clist.CElement, removeFromC atomic.AddInt64(&mem.txsBytes, int64(-len(tx))) if removeFromCache { - mem.cache.Remove(tx.Key()) + mem.cache.Remove(tx) } } @@ -402,7 +402,7 @@ func (mem *CListMempool) resCbFirstTime( // limits. if err := mem.isFull(len(tx)); err != nil { // remove from cache (mempool might have a space later) - mem.cache.Remove(types.Tx(tx).Key()) + mem.cache.Remove(tx) mem.logger.Error(err.Error()) return } @@ -435,7 +435,7 @@ func (mem *CListMempool) resCbFirstTime( if !mem.config.KeepInvalidTxsInCache { // remove from cache (it might be good later) - mem.cache.Remove(types.Tx(tx).Key()) + mem.cache.Remove(tx) } } @@ -614,10 +614,10 @@ func (mem *CListMempool) Update( for i, tx := range txs { if deliverTxResponses[i].Code == abci.CodeTypeOK { // Add valid committed tx to the cache (if missing). - _ = mem.cache.Push(tx.Key()) + _ = mem.cache.Push(tx) } else if !mem.config.KeepInvalidTxsInCache { // Allow invalid transactions to be resubmitted. - mem.cache.Remove(tx.Key()) + mem.cache.Remove(tx) } // Remove committed tx from the mempool. diff --git a/mempool/v0/clist_mempool_test.go b/mempool/v0/clist_mempool_test.go index 58f3fc2acb..0c303714c9 100644 --- a/mempool/v0/clist_mempool_test.go +++ b/mempool/v0/clist_mempool_test.go @@ -342,7 +342,7 @@ func TestMempool_KeepInvalidTxsInCache(t *testing.T) { binary.BigEndian.PutUint64(a, 0) // remove a from the cache to test (2) - mp.cache.Remove(types.Tx(a).Key()) + mp.cache.Remove(a) err := mp.CheckTx(a, nil, mempool.TxInfo{}) require.NoError(t, err) diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index 091b7f6816..ec544115b2 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -217,7 +217,7 @@ func (txmp *TxMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo memp txKey := tx.Key() // Check for the transaction in the cache. - if !txmp.cache.Push(txKey) { + if !txmp.cache.Push(tx) { // If the cached transaction is also in the pool, record its sender. if elt, ok := txmp.txByKey[txKey]; ok { txmp.metrics.AlreadySeenTxs.Add(1) @@ -235,7 +235,7 @@ func (txmp *TxMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo memp // Invoke an ABCI CheckTx for this transaction. rsp, err := txmp.proxyAppConn.CheckTxSync(abci.RequestCheckTx{Tx: tx}) if err != nil { - txmp.cache.Remove(tx.Key()) + txmp.cache.Remove(tx) return err } wtx := &WrappedTx{ @@ -276,7 +276,7 @@ func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { // IsTxEvicted returns a bool indicating whether the transaction with // the specified key was recently evicted and is currently within the cache. func (txmp *TxMempool) IsTxEvicted(txKey types.TxKey) bool { - return txmp.evictedTxs.Has(txKey) + return txmp.evictedTxs.HasKey(txKey) } // removeTxByKey removes the specified transaction key from the mempool. @@ -441,9 +441,9 @@ func (txmp *TxMempool) Update( // already present). Transactions that failed to commit are removed from // the cache unless the operator has explicitly requested we keep them. if deliverTxResponses[i].Code == abci.CodeTypeOK { - _ = txmp.cache.Push(tx.Key()) + _ = txmp.cache.Push(tx) } else if !txmp.config.KeepInvalidTxsInCache { - txmp.cache.Remove(tx.Key()) + txmp.cache.Remove(tx) } // Regardless of success, remove the transaction from the mempool. @@ -505,7 +505,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon // Remove the invalid transaction from the cache, unless the operator has // instructed us to keep invalid transactions. if !txmp.config.KeepInvalidTxsInCache { - txmp.cache.Remove(wtx.tx.Key()) + txmp.cache.Remove(wtx.tx) } // If there was a post-check error, record its text in the result for @@ -559,8 +559,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon // those candidates is not enough to make room for the new transaction, // drop the new one. if len(victims) == 0 || victimBytes < wtx.Size() { - wtxKey := wtx.tx.Key() - txmp.cache.Remove(wtxKey) + txmp.cache.Remove(wtx.tx) txmp.logger.Error( "rejected valid incoming transaction; mempool is full", "tx", fmt.Sprintf("%X", wtx.tx.Hash()), @@ -571,7 +570,7 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon wtx.tx.Hash()) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedNewTxFullMempool).Add(1) // Add it to evicted transactions cache - txmp.evictedTxs.Push(wtxKey) + txmp.evictedTxs.Push(wtx.tx) return } @@ -602,10 +601,10 @@ func (txmp *TxMempool) addNewTransaction(wtx *WrappedTx, checkTxRes *abci.Respon "old_priority", w.priority, ) txmp.removeTxByElement(vic) - txmp.cache.Remove(w.tx.Key()) + txmp.cache.Remove(w.tx) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedExistingTxFullMempool).Add(1) // Add it to evicted transactions cache - txmp.evictedTxs.Push(w.tx.Key()) + txmp.evictedTxs.Push(w.tx) // We may not need to evict all the eligible transactions. Bail out // early if we have made enough room. evictedBytes += w.Size() @@ -684,7 +683,7 @@ func (txmp *TxMempool) handleRecheckResult(tx types.Tx, checkTxRes *abci.Respons txmp.removeTxByElement(elt) txmp.metrics.FailedTxs.With(mempool.TypeLabel, mempool.FailedRecheck).Add(1) if !txmp.config.KeepInvalidTxsInCache { - txmp.cache.Remove(wtx.tx.Key()) + txmp.cache.Remove(wtx.tx) } txmp.metrics.Size.Set(float64(txmp.Size())) txmp.metrics.SizeBytes.Set(float64(txmp.SizeBytes())) @@ -794,13 +793,13 @@ func (txmp *TxMempool) purgeExpiredTxs(blockHeight int64) { w := cur.Value.(*WrappedTx) if txmp.config.TTLNumBlocks > 0 && (blockHeight-w.height) > txmp.config.TTLNumBlocks { txmp.removeTxByElement(cur) - txmp.cache.Remove(w.tx.Key()) + txmp.cache.Remove(w.tx) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedTxExpiredBlocks).Add(1) - txmp.evictedTxs.Push(w.tx.Key()) + txmp.evictedTxs.Push(w.tx) } else if txmp.config.TTLDuration > 0 && now.Sub(w.timestamp) > txmp.config.TTLDuration { txmp.removeTxByElement(cur) - txmp.cache.Remove(w.tx.Key()) - txmp.evictedTxs.Push(w.tx.Key()) + txmp.cache.Remove(w.tx) + txmp.evictedTxs.Push(w.tx) txmp.metrics.EvictedTxs.With(mempool.TypeLabel, mempool.EvictedTxExpiredTime).Add(1) } cur = next diff --git a/mempool/v1/mempool_test.go b/mempool/v1/mempool_test.go index 4b51d4a9d3..c52107169f 100644 --- a/mempool/v1/mempool_test.go +++ b/mempool/v1/mempool_test.go @@ -242,7 +242,7 @@ func TestTxMempool_Eviction(t *testing.T) { require.True(t, txExists("key1=0000=25")) require.False(t, txExists(bigTx)) bigTxKey := types.Tx((bigTx)).Key() - require.False(t, txmp.cache.Has(bigTxKey)) + require.False(t, txmp.cache.HasKey(bigTxKey)) require.True(t, txmp.IsTxEvicted(bigTxKey)) // bigTx evicted require.Equal(t, int64(len("key1=0000=25")), txmp.SizeBytes()) @@ -597,7 +597,7 @@ func TestTxMempool_ExpiredTxs_Timestamp(t *testing.T) { if _, ok := txmp.txByKey[tx.tx.Key()]; ok { t.Errorf("Transaction %X should have been purged for TTL", tx.tx.Key()) } - if txmp.cache.Has(tx.tx.Key()) { + if txmp.cache.Has(tx.tx) { t.Errorf("Transaction %X should have been removed from the cache", tx.tx.Key()) } } From e4c98399e971580dc0939e3caea56a89f5ab38cb Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 13 Jun 2024 16:28:20 +0200 Subject: [PATCH 35/47] style: lint --- mempool/cache_bench_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/cache_bench_test.go b/mempool/cache_bench_test.go index 551f3268d5..1c26999d10 100644 --- a/mempool/cache_bench_test.go +++ b/mempool/cache_bench_test.go @@ -38,4 +38,4 @@ func BenchmarkCacheRemoveTime(b *testing.B) { for i := 0; i < b.N; i++ { cache.Remove(txs[i]) } -} \ No newline at end of file +} From 5ae87e90488315a9f2587ab39073c63c947186d6 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 13 Jun 2024 16:53:58 +0200 Subject: [PATCH 36/47] refactor: comments --- mempool/cache.go | 3 +-- mempool/v1/mempool_test.go | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mempool/cache.go b/mempool/cache.go index 330c65f480..429f4e1ab7 100644 --- a/mempool/cache.go +++ b/mempool/cache.go @@ -23,8 +23,7 @@ type TxCache interface { // Remove removes the given raw transaction from the cache. Remove(tx types.Tx) - // Has reports whether tx is present in the cache. Checking for presence is - // not treated as an access of the value. + // Has reports whether tx is present in the cache. Has(tx types.Tx) bool // HasKey reports whether the given key is present in the cache. Checking for diff --git a/mempool/v1/mempool_test.go b/mempool/v1/mempool_test.go index c52107169f..8395fa894f 100644 --- a/mempool/v1/mempool_test.go +++ b/mempool/v1/mempool_test.go @@ -590,7 +590,7 @@ func TestTxMempool_ExpiredTxs_Timestamp(t *testing.T) { // All the transactions in the original set should have been purged. for _, tx := range added1 { - // Check that they were adding to the evicted cache. + // Check that they were added to the evicted cache. evicted := txmp.IsTxEvicted(tx.tx.Key()) require.True(t, evicted) @@ -614,7 +614,7 @@ func TestGetTxByKey_GetsTx(t *testing.T) { txmp := setup(t, 500) txs := checkTxs(t, txmp, 100, 0) - // Test that it gets all valid txs + // Should get all valid txs for _, tx := range txs { txKey := tx.tx.Key() txFromMempool, exists := txmp.GetTxByKey(txKey) @@ -622,7 +622,7 @@ func TestGetTxByKey_GetsTx(t *testing.T) { require.True(t, exists) } - // Test that a non-existent tx returns false + // Non-existent tx should return false _, exists := txmp.GetTxByKey(types.Tx("non-existent-tx").Key()) require.False(t, exists) } From 6ac1205a76b0cdba214f6bf094e35bf098af6778 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 13 Jun 2024 16:58:52 +0200 Subject: [PATCH 37/47] refactor: revert accidentally removed comment --- mempool/cache.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mempool/cache.go b/mempool/cache.go index 429f4e1ab7..8141f2ae23 100644 --- a/mempool/cache.go +++ b/mempool/cache.go @@ -23,11 +23,11 @@ type TxCache interface { // Remove removes the given raw transaction from the cache. Remove(tx types.Tx) - // Has reports whether tx is present in the cache. + // Has reports whether tx is present in the cache. Checking for presence is + // not treated as an access of the value. Has(tx types.Tx) bool - // HasKey reports whether the given key is present in the cache. Checking for - // presence is not treated as an access of the value. + // HasKey reports whether the given key is present in the cache. HasKey(key types.TxKey) bool } From 4e09a6c6cee590aa1cef057e4aec1098a45b6380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Thu, 13 Jun 2024 18:55:14 +0200 Subject: [PATCH 38/47] Update mempool/v1/mempool.go Co-authored-by: Rootul P --- mempool/v1/mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index ec544115b2..961d27e225 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -274,7 +274,7 @@ func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { } // IsTxEvicted returns a bool indicating whether the transaction with -// the specified key was recently evicted and is currently within the cache. +// the specified key was recently evicted and is currently within the evicted cache. func (txmp *TxMempool) IsTxEvicted(txKey types.TxKey) bool { return txmp.evictedTxs.HasKey(txKey) } From cc8c178a0dcaf6f81dd90519bd2c031e20fee008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Thu, 13 Jun 2024 18:58:50 +0200 Subject: [PATCH 39/47] Update mempool/mempool.go Co-authored-by: Rootul P --- mempool/mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index 5eb51c0bc4..ec3fef31e3 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -91,7 +91,7 @@ type Mempool interface { // trigger once every height when transactions are available. EnableTxsAvailable() - // GetTxByKey gets a tx by its key from the mempool cache. Returns the tx and a bool indicating its presence in the tx cache. + // GetTxByKey gets a tx by its key from the mempool. Returns the tx and a bool indicating its presence in the tx cache. // Used in the RPC endpoint: TxStatus. GetTxByKey(key types.TxKey) (types.Tx, bool) From 7437fd9e8b9ab91525d0baf3bcccc6f2fb550ead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Thu, 13 Jun 2024 18:59:03 +0200 Subject: [PATCH 40/47] Update mempool/mempool.go Co-authored-by: Rootul P --- mempool/mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index ec3fef31e3..8ccf0a35bd 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -95,7 +95,7 @@ type Mempool interface { // Used in the RPC endpoint: TxStatus. GetTxByKey(key types.TxKey) (types.Tx, bool) - // IsTxEvicted returns true if the tx is evicted from the mempool and exists in the + // IsTxEvicted returns true if the tx was evicted from the mempool and exists in the // evicted cache. // Used in the RPC endpoint: TxStatus. IsTxEvicted(key types.TxKey) bool From c6f3e9a14bf3995fbfc038162f4589e060d6ef85 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Thu, 13 Jun 2024 19:15:07 +0200 Subject: [PATCH 41/47] test: update test --- rpc/core/tx.go | 12 ++++++------ rpc/core/tx_status_test.go | 6 ------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/rpc/core/tx.go b/rpc/core/tx.go index 67e9f34d96..7de85d81c8 100644 --- a/rpc/core/tx.go +++ b/rpc/core/tx.go @@ -227,6 +227,12 @@ func ProveShares( func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error) { env := GetEnvironment() + // Check if the tx has been committed + txInfo := env.BlockStore.LoadTxInfo(hash) + if txInfo != nil { + return &ctypes.ResultTxStatus{Height: txInfo.Height, Index: txInfo.Index, Status: txStatusCommitted}, nil + } + // Get the tx key from the hash txKey, err := types.TxKeyFromBytes(hash) if err != nil { @@ -245,12 +251,6 @@ func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error return &ctypes.ResultTxStatus{Status: txStatusEvicted}, nil } - // Check if the tx has been committed - txInfo := env.BlockStore.LoadTxInfo(hash) - if txInfo != nil { - return &ctypes.ResultTxStatus{Height: txInfo.Height, Index: txInfo.Index, Status: txStatusCommitted}, nil - } - // If the tx is not in the mempool, evicted, or committed, return unknown return &ctypes.ResultTxStatus{Status: txStatusUnknown}, nil } diff --git a/rpc/core/tx_status_test.go b/rpc/core/tx_status_test.go index 5d994ba14d..604cc14f26 100644 --- a/rpc/core/tx_status_test.go +++ b/rpc/core/tx_status_test.go @@ -45,12 +45,6 @@ func TestTxStatus(t *testing.T) { blocks: blocks, } env.BlockStore = blockStore - for _, tx := range txs { - // Set GetTxByKey to return nil and false for all transactions - mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() - // Set IsTxEvicted to return false for all transactions - mempool.EXPECT().IsTxEvicted(tx.Key()).Return(false).AnyTimes() - } }, expectedStatus: "COMMITTED", }, From bc74ef37f51fd7f4dbe72fea63979ffdd89b2ce7 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Mon, 17 Jun 2024 16:16:03 +0200 Subject: [PATCH 42/47] refactor: no longer pass the cache in purgeExpiredTxs and reduce evictedTxCache size --- mempool/cat/pool.go | 16 ++++++++++++---- mempool/cat/store.go | 11 ++++++----- mempool/cat/store_test.go | 4 ++-- mempool/v1/mempool.go | 2 +- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/mempool/cat/pool.go b/mempool/cat/pool.go index 9584720036..050a94589d 100644 --- a/mempool/cat/pool.go +++ b/mempool/cat/pool.go @@ -94,7 +94,7 @@ func NewTxPool( proxyAppConn: proxyAppConn, metrics: mempool.NopMetrics(), rejectedTxCache: NewLRUTxCache(cfg.CacheSize), - evictedTxCache: NewLRUTxCache(cfg.CacheSize), + evictedTxCache: NewLRUTxCache(cfg.CacheSize / 5), seenByPeersSet: NewSeenTxSet(), height: height, preCheckFn: func(_ types.Tx) error { return nil }, @@ -210,9 +210,13 @@ func (txmp *TxPool) CheckToPurgeExpiredTxs() { defer txmp.updateMtx.Unlock() if txmp.config.TTLDuration > 0 && time.Since(txmp.lastPurgeTime) > txmp.config.TTLDuration { expirationAge := time.Now().Add(-txmp.config.TTLDuration) - // a height of 0 means no transactions will be removed because of height + // A height of 0 means no transactions will be removed because of height // (in other words, no transaction has a height less than 0) - numExpired := txmp.store.purgeExpiredTxs(0, expirationAge, txmp.evictedTxCache) + purgedTxs, numExpired := txmp.store.purgeExpiredTxs(0, expirationAge) + // Add the purged transactions to the evicted cache + for _, tx := range purgedTxs { + txmp.evictedTxCache.Push(tx.key) + } txmp.metrics.EvictedTxs.Add(float64(numExpired)) txmp.lastPurgeTime = time.Now() } @@ -738,7 +742,11 @@ func (txmp *TxPool) purgeExpiredTxs(blockHeight int64) { expirationAge = time.Time{} } - numExpired := txmp.store.purgeExpiredTxs(expirationHeight, expirationAge, txmp.evictedTxCache) + purgedTxs, numExpired := txmp.store.purgeExpiredTxs(expirationHeight, expirationAge) + // Add the purged transactions to the evicted cache + for _, tx := range purgedTxs { + txmp.evictedTxCache.Push(tx.key) + } txmp.metrics.EvictedTxs.Add(float64(numExpired)) // purge old evicted and seen transactions diff --git a/mempool/cat/store.go b/mempool/cat/store.go index 5638f5ce9d..92e468d616 100644 --- a/mempool/cat/store.go +++ b/mempool/cat/store.go @@ -142,21 +142,22 @@ func (s *store) getTxsBelowPriority(priority int64) ([]*wrappedTx, int64) { // purgeExpiredTxs removes all transactions that are older than the given height // and time. Returns the amount of transactions that were removed -func (s *store) purgeExpiredTxs(expirationHeight int64, expirationAge time.Time, evictedTxCache *LRUTxCache) int { +func (s *store) purgeExpiredTxs(expirationHeight int64, expirationAge time.Time) ([]*wrappedTx, int) { s.mtx.Lock() defer s.mtx.Unlock() + + var purgedTxs []*wrappedTx counter := 0 + for key, tx := range s.txs { if tx.height < expirationHeight || tx.timestamp.Before(expirationAge) { s.bytes -= tx.size() delete(s.txs, key) - if evictedTxCache != nil { - evictedTxCache.Push(key) - } + purgedTxs = append(purgedTxs, tx) counter++ } } - return counter + return purgedTxs, counter } func (s *store) reset() { diff --git a/mempool/cat/store_test.go b/mempool/cat/store_test.go index 75ea3f9c45..7813eddba6 100644 --- a/mempool/cat/store_test.go +++ b/mempool/cat/store_test.go @@ -173,7 +173,7 @@ func TestStoreExpiredTxs(t *testing.T) { } // half of them should get purged - store.purgeExpiredTxs(int64(numTxs/2), time.Time{}, nil) + store.purgeExpiredTxs(int64(numTxs/2), time.Time{}) remainingTxs := store.getAllTxs() require.Equal(t, numTxs/2, len(remainingTxs)) @@ -181,6 +181,6 @@ func TestStoreExpiredTxs(t *testing.T) { require.GreaterOrEqual(t, tx.height, int64(numTxs/2)) } - store.purgeExpiredTxs(int64(0), time.Now().Add(time.Second), nil) + store.purgeExpiredTxs(int64(0), time.Now().Add(time.Second)) require.Empty(t, store.getAllTxs()) } diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index 961d27e225..3d85daf473 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -87,7 +87,7 @@ func NewTxMempool( } if cfg.CacheSize > 0 { txmp.cache = mempool.NewLRUTxCache(cfg.CacheSize) - txmp.evictedTxs = mempool.NewLRUTxCache(cfg.CacheSize) + txmp.evictedTxs = mempool.NewLRUTxCache(cfg.CacheSize / 5) } for _, opt := range options { From 64eb49839d9d76d1ce00be153c4c2c7d14f1944a Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Mon, 17 Jun 2024 17:44:56 +0200 Subject: [PATCH 43/47] feat: add txstatus in mempool and test it --- mempool/v0/clist_mempool.go | 11 ++++++++--- mempool/v0/clist_mempool_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index d2a75a0b93..2bb39347d9 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -183,12 +183,17 @@ func (mem *CListMempool) TxsFront() *clist.CElement { return mem.txs.Front() } -// GetTxByKey is not supported by the v0 mempool but it is required to satisfy the mempool interface. +// GetTxByKey retrieves a transaction from the mempool using its key. func (mem *CListMempool) GetTxByKey(key types.TxKey) (types.Tx, bool) { - return nil, false + e, ok := mem.txsMap.Load(key) + if !ok { + return nil, false + } + memTx, ok := e.(*clist.CElement).Value.(*mempoolTx) + return memTx.tx, ok } -// IsTxEvicted is not supported by the v0 mempool but it is required to satisfy the mempool interface. +// IsTxEvicted returns false consistently as this implementation does not support transaction eviction. func (mem *CListMempool) IsTxEvicted(key types.TxKey) bool { return false } diff --git a/mempool/v0/clist_mempool_test.go b/mempool/v0/clist_mempool_test.go index 0c303714c9..8c8fba6725 100644 --- a/mempool/v0/clist_mempool_test.go +++ b/mempool/v0/clist_mempool_test.go @@ -549,6 +549,33 @@ func TestMempool_CheckTxChecksTxSize(t *testing.T) { } } +func TestGetTxByKey(t *testing.T) { + app := kvstore.NewApplication() + cc := proxy.NewLocalClientCreator(app) + + mp, cleanup := newMempoolWithApp(cc) + defer cleanup() + + // Create a tx + tx := types.Tx([]byte{0x01}) + // Add it to the mempool + err := mp.CheckTx(tx, nil, mempool.TxInfo{}) + require.NoError(t, err) + + txKey := types.Tx(tx).Key() + // Query the tx from the mempool + got, ok := mp.GetTxByKey(txKey) + require.True(t, ok) + // Ensure the returned tx is the same as the one we added + require.Equal(t, tx, got) + + // Query a random tx from the mempool + randomTx, ok := mp.GetTxByKey(types.Tx([]byte{0x02}).Key()) + // Ensure the returned tx is nil + require.False(t, ok) + require.Nil(t, randomTx) +} + func TestMempoolTxsBytes(t *testing.T) { app := kvstore.NewApplication() cc := proxy.NewLocalClientCreator(app) From bbcb66a38f9135c24046b2805a0f8868d23f2442 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Mon, 17 Jun 2024 18:44:43 +0200 Subject: [PATCH 44/47] style: lint --- mempool/v0/clist_mempool.go | 2 +- mempool/v0/clist_mempool_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index 2bb39347d9..304cde13c5 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -183,7 +183,7 @@ func (mem *CListMempool) TxsFront() *clist.CElement { return mem.txs.Front() } -// GetTxByKey retrieves a transaction from the mempool using its key. +// GetTxByKey retrieves a transaction from the mempool using its key. func (mem *CListMempool) GetTxByKey(key types.TxKey) (types.Tx, bool) { e, ok := mem.txsMap.Load(key) if !ok { diff --git a/mempool/v0/clist_mempool_test.go b/mempool/v0/clist_mempool_test.go index 8c8fba6725..b3d0f523b3 100644 --- a/mempool/v0/clist_mempool_test.go +++ b/mempool/v0/clist_mempool_test.go @@ -555,7 +555,7 @@ func TestGetTxByKey(t *testing.T) { mp, cleanup := newMempoolWithApp(cc) defer cleanup() - + // Create a tx tx := types.Tx([]byte{0x01}) // Add it to the mempool From a75c6d5f3f95ceb620c31cc58bb6bd79b3dbb547 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Mon, 17 Jun 2024 18:50:06 +0200 Subject: [PATCH 45/47] lint: remove lint error --- mempool/v0/clist_mempool_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mempool/v0/clist_mempool_test.go b/mempool/v0/clist_mempool_test.go index b3d0f523b3..f2e01e5aad 100644 --- a/mempool/v0/clist_mempool_test.go +++ b/mempool/v0/clist_mempool_test.go @@ -562,9 +562,8 @@ func TestGetTxByKey(t *testing.T) { err := mp.CheckTx(tx, nil, mempool.TxInfo{}) require.NoError(t, err) - txKey := types.Tx(tx).Key() // Query the tx from the mempool - got, ok := mp.GetTxByKey(txKey) + got, ok := mp.GetTxByKey(tx.Key()) require.True(t, ok) // Ensure the returned tx is the same as the one we added require.Equal(t, tx, got) From 14d09b0d644abdd1b0d61b4caf46ce76e8da6ed6 Mon Sep 17 00:00:00 2001 From: Nina Barbakadze Date: Mon, 17 Jun 2024 19:04:33 +0200 Subject: [PATCH 46/47] refactor: rename IsTxEvicted to WasRecentlyEvicted --- consensus/replay_stubs.go | 2 +- mempool/cat/pool.go | 4 ++-- mempool/cat/pool_test.go | 20 ++++++++++---------- mempool/mempool.go | 4 ++-- mempool/mock/mempool.go | 2 +- mempool/v0/clist_mempool.go | 4 ++-- mempool/v1/mempool.go | 4 ++-- mempool/v1/mempool_test.go | 22 +++++++++++----------- rpc/core/mocks/mempool.go | 12 ++++++------ rpc/core/tx.go | 2 +- rpc/core/tx_status_test.go | 8 ++++---- test/maverick/consensus/replay_stubs.go | 2 +- 12 files changed, 43 insertions(+), 43 deletions(-) diff --git a/consensus/replay_stubs.go b/consensus/replay_stubs.go index 6e3d80f488..60d587edd4 100644 --- a/consensus/replay_stubs.go +++ b/consensus/replay_stubs.go @@ -50,7 +50,7 @@ func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } func (emptyMempool) InitWAL() error { return nil } func (emptyMempool) CloseWAL() {} func (emptyMempool) GetTxByKey(types.TxKey) (types.Tx, bool) { return nil, false } -func (emptyMempool) IsTxEvicted(types.TxKey) bool { return false } +func (emptyMempool) WasRecentlyEvicted(types.TxKey) bool { return false } //----------------------------------------------------------------------------- // mockProxyApp uses ABCIResponses to give the right results. diff --git a/mempool/cat/pool.go b/mempool/cat/pool.go index 050a94589d..91caa1d86e 100644 --- a/mempool/cat/pool.go +++ b/mempool/cat/pool.go @@ -190,9 +190,9 @@ func (txmp *TxPool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { return types.Tx{}, false } -// IsTxEvicted returns a bool indicating whether the transaction with +// WasRecentlyEvicted returns a bool indicating whether the transaction with // the specified key was recently evicted and is currently within the cache. -func (txmp *TxPool) IsTxEvicted(txKey types.TxKey) bool { +func (txmp *TxPool) WasRecentlyEvicted(txKey types.TxKey) bool { return txmp.evictedTxCache.Has(txKey) } diff --git a/mempool/cat/pool_test.go b/mempool/cat/pool_test.go index 973f7e473d..5f27448420 100644 --- a/mempool/cat/pool_test.go +++ b/mempool/cat/pool_test.go @@ -244,7 +244,7 @@ func TestTxPool_Eviction(t *testing.T) { mustCheckTx(t, txmp, "key1=0000=25") require.True(t, txExists("key1=0000=25")) require.False(t, txExists(bigTx)) - require.True(t, txmp.IsTxEvicted(types.Tx(bigTx).Key())) + require.True(t, txmp.WasRecentlyEvicted(types.Tx(bigTx).Key())) require.Equal(t, int64(len("key1=0000=25")), txmp.SizeBytes()) // Now fill up the rest of the slots with other transactions. @@ -258,27 +258,27 @@ func TestTxPool_Eviction(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "mempool is full") require.False(t, txExists("key6=0005=1")) - require.True(t, txmp.IsTxEvicted(types.Tx("key6=0005=1").Key())) + require.True(t, txmp.WasRecentlyEvicted(types.Tx("key6=0005=1").Key())) // A new transaction with higher priority should evict key5, which is the // newest of the two transactions with lowest priority. mustCheckTx(t, txmp, "key7=0006=7") require.True(t, txExists("key7=0006=7")) // new transaction added require.False(t, txExists("key5=0004=3")) // newest low-priority tx evicted - require.True(t, txmp.IsTxEvicted(types.Tx("key5=0004=3").Key())) + require.True(t, txmp.WasRecentlyEvicted(types.Tx("key5=0004=3").Key())) require.True(t, txExists("key4=0003=3")) // older low-priority tx retained // Another new transaction evicts the other low-priority element. mustCheckTx(t, txmp, "key8=0007=20") require.True(t, txExists("key8=0007=20")) require.False(t, txExists("key4=0003=3")) - require.True(t, txmp.IsTxEvicted(types.Tx("key4=0003=3").Key())) + require.True(t, txmp.WasRecentlyEvicted(types.Tx("key4=0003=3").Key())) // Now the lowest-priority tx is 5, so that should be the next to go. mustCheckTx(t, txmp, "key9=0008=9") require.True(t, txExists("key9=0008=9")) require.False(t, txExists("key2=0001=5")) - require.True(t, txmp.IsTxEvicted(types.Tx("key2=0001=5").Key())) + require.True(t, txmp.WasRecentlyEvicted(types.Tx("key2=0001=5").Key())) // Add a transaction that requires eviction of multiple lower-priority // entries, in order to fit the size of the element. @@ -287,11 +287,11 @@ func TestTxPool_Eviction(t *testing.T) { require.True(t, txExists("key8=0007=20")) require.True(t, txExists("key10=0123456789abcdef=11")) require.False(t, txExists("key3=0002=10")) - require.True(t, txmp.IsTxEvicted(types.Tx("key3=0002=10").Key())) + require.True(t, txmp.WasRecentlyEvicted(types.Tx("key3=0002=10").Key())) require.False(t, txExists("key9=0008=9")) - require.True(t, txmp.IsTxEvicted(types.Tx("key9=0008=9").Key())) + require.True(t, txmp.WasRecentlyEvicted(types.Tx("key9=0008=9").Key())) require.False(t, txExists("key7=0006=7")) - require.True(t, txmp.IsTxEvicted(types.Tx("key7=0006=7").Key())) + require.True(t, txmp.WasRecentlyEvicted(types.Tx("key7=0006=7").Key())) // Free up some space so we can add back previously evicted txs err = txmp.Update(1, types.Txs{types.Tx("key10=0123456789abcdef=11")}, []*abci.ResponseDeliverTx{{Code: abci.CodeTypeOK}}, nil, nil) @@ -304,7 +304,7 @@ func TestTxPool_Eviction(t *testing.T) { // space for the previously evicted tx require.NoError(t, txmp.RemoveTxByKey(types.Tx("key8=0007=20").Key())) require.False(t, txExists("key8=0007=20")) - require.False(t, txmp.IsTxEvicted(types.Tx("key8=0007=20").Key())) + require.False(t, txmp.WasRecentlyEvicted(types.Tx("key8=0007=20").Key())) } func TestTxPool_Flush(t *testing.T) { @@ -577,7 +577,7 @@ func TestTxPool_ExpiredTxs_Timestamp(t *testing.T) { // All the transactions in the original set should have been purged. for _, tx := range added1 { // Check that it was added to the evictedTxCache - evicted := txmp.IsTxEvicted(tx.tx.Key()) + evicted := txmp.WasRecentlyEvicted(tx.tx.Key()) require.True(t, evicted) if txmp.store.has(tx.tx.Key()) { diff --git a/mempool/mempool.go b/mempool/mempool.go index 8ccf0a35bd..3d7d83d695 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -95,10 +95,10 @@ type Mempool interface { // Used in the RPC endpoint: TxStatus. GetTxByKey(key types.TxKey) (types.Tx, bool) - // IsTxEvicted returns true if the tx was evicted from the mempool and exists in the + // WasRecentlyEvicted returns true if the tx was evicted from the mempool and exists in the // evicted cache. // Used in the RPC endpoint: TxStatus. - IsTxEvicted(key types.TxKey) bool + WasRecentlyEvicted(key types.TxKey) bool // Size returns the number of transactions in the mempool. Size() int diff --git a/mempool/mock/mempool.go b/mempool/mock/mempool.go index 3f5711a5c1..d1adfab008 100644 --- a/mempool/mock/mempool.go +++ b/mempool/mock/mempool.go @@ -36,7 +36,7 @@ func (Mempool) TxsAvailable() <-chan struct{} { return make(chan str func (Mempool) EnableTxsAvailable() {} func (Mempool) SizeBytes() int64 { return 0 } func (m Mempool) GetTxByKey(types.TxKey) (types.Tx, bool) { return nil, false } -func (m Mempool) IsTxEvicted(types.TxKey) bool { return false } +func (m Mempool) WasRecentlyEvicted(types.TxKey) bool { return false } func (Mempool) TxsFront() *clist.CElement { return nil } func (Mempool) TxsWaitChan() <-chan struct{} { return nil } diff --git a/mempool/v0/clist_mempool.go b/mempool/v0/clist_mempool.go index 304cde13c5..e783113b0f 100644 --- a/mempool/v0/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -193,8 +193,8 @@ func (mem *CListMempool) GetTxByKey(key types.TxKey) (types.Tx, bool) { return memTx.tx, ok } -// IsTxEvicted returns false consistently as this implementation does not support transaction eviction. -func (mem *CListMempool) IsTxEvicted(key types.TxKey) bool { +// WasRecentlyEvicted returns false consistently as this implementation does not support transaction eviction. +func (mem *CListMempool) WasRecentlyEvicted(key types.TxKey) bool { return false } diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go index 3d85daf473..5a22ab4e24 100644 --- a/mempool/v1/mempool.go +++ b/mempool/v1/mempool.go @@ -273,9 +273,9 @@ func (txmp *TxMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { return nil, false } -// IsTxEvicted returns a bool indicating whether the transaction with +// WasRecentlyEvicted returns a bool indicating whether the transaction with // the specified key was recently evicted and is currently within the evicted cache. -func (txmp *TxMempool) IsTxEvicted(txKey types.TxKey) bool { +func (txmp *TxMempool) WasRecentlyEvicted(txKey types.TxKey) bool { return txmp.evictedTxs.HasKey(txKey) } diff --git a/mempool/v1/mempool_test.go b/mempool/v1/mempool_test.go index 8395fa894f..88f9de3d0b 100644 --- a/mempool/v1/mempool_test.go +++ b/mempool/v1/mempool_test.go @@ -243,7 +243,7 @@ func TestTxMempool_Eviction(t *testing.T) { require.False(t, txExists(bigTx)) bigTxKey := types.Tx((bigTx)).Key() require.False(t, txmp.cache.HasKey(bigTxKey)) - require.True(t, txmp.IsTxEvicted(bigTxKey)) // bigTx evicted + require.True(t, txmp.WasRecentlyEvicted(bigTxKey)) // bigTx evicted require.Equal(t, int64(len("key1=0000=25")), txmp.SizeBytes()) // Now fill up the rest of the slots with other transactions. @@ -255,15 +255,15 @@ func TestTxMempool_Eviction(t *testing.T) { // A new transaction with low priority should be discarded. mustCheckTx(t, txmp, "key6=0005=1") require.False(t, txExists("key6=0005=1")) - require.True(t, txmp.IsTxEvicted(types.Tx(("key6=0005=1")).Key())) // key6 evicted + require.True(t, txmp.WasRecentlyEvicted(types.Tx(("key6=0005=1")).Key())) // key6 evicted // A new transaction with higher priority should evict key5, which is the // newest of the two transactions with lowest priority. mustCheckTx(t, txmp, "key7=0006=7") - require.True(t, txExists("key7=0006=7")) // new transaction added - require.False(t, txExists("key5=0004=3")) // newest low-priority tx evicted - require.True(t, txmp.IsTxEvicted(types.Tx(("key5=0004=3")).Key())) // key5 evicted - require.True(t, txExists("key4=0003=3")) // older low-priority tx retained + require.True(t, txExists("key7=0006=7")) // new transaction added + require.False(t, txExists("key5=0004=3")) // newest low-priority tx evicted + require.True(t, txmp.WasRecentlyEvicted(types.Tx(("key5=0004=3")).Key())) // key5 evicted + require.True(t, txExists("key4=0003=3")) // older low-priority tx retained // Another new transaction evicts the other low-priority element. mustCheckTx(t, txmp, "key8=0007=20") @@ -274,7 +274,7 @@ func TestTxMempool_Eviction(t *testing.T) { mustCheckTx(t, txmp, "key9=0008=9") require.True(t, txExists("key9=0008=9")) require.False(t, txExists("key2=0001=5")) - require.True(t, txmp.IsTxEvicted(types.Tx(("key2=0001=5")).Key())) // key2 evicted + require.True(t, txmp.WasRecentlyEvicted(types.Tx(("key2=0001=5")).Key())) // key2 evicted // Add a transaction that requires eviction of multiple lower-priority // entries, in order to fit the size of the element. @@ -283,11 +283,11 @@ func TestTxMempool_Eviction(t *testing.T) { require.True(t, txExists("key8=0007=20")) require.True(t, txExists("key10=0123456789abcdef=11")) require.False(t, txExists("key3=0002=10")) - require.True(t, txmp.IsTxEvicted(types.Tx(("key3=0002=10")).Key())) // key3 evicted + require.True(t, txmp.WasRecentlyEvicted(types.Tx(("key3=0002=10")).Key())) // key3 evicted require.False(t, txExists("key9=0008=9")) - require.True(t, txmp.IsTxEvicted(types.Tx(("key9=0008=9")).Key())) // key9 evicted + require.True(t, txmp.WasRecentlyEvicted(types.Tx(("key9=0008=9")).Key())) // key9 evicted require.False(t, txExists("key7=0006=7")) - require.True(t, txmp.IsTxEvicted(types.Tx(("key7=0006=7")).Key())) // key7 evicted + require.True(t, txmp.WasRecentlyEvicted(types.Tx(("key7=0006=7")).Key())) // key7 evicted } func TestTxMempool_Flush(t *testing.T) { @@ -591,7 +591,7 @@ func TestTxMempool_ExpiredTxs_Timestamp(t *testing.T) { // All the transactions in the original set should have been purged. for _, tx := range added1 { // Check that they were added to the evicted cache. - evicted := txmp.IsTxEvicted(tx.tx.Key()) + evicted := txmp.WasRecentlyEvicted(tx.tx.Key()) require.True(t, evicted) if _, ok := txmp.txByKey[tx.tx.Key()]; ok { diff --git a/rpc/core/mocks/mempool.go b/rpc/core/mocks/mempool.go index e9fbe4e784..57d750dad8 100644 --- a/rpc/core/mocks/mempool.go +++ b/rpc/core/mocks/mempool.go @@ -103,18 +103,18 @@ func (mr *MockMempoolMockRecorder) GetTxByKey(key interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTxByKey", reflect.TypeOf((*MockMempool)(nil).GetTxByKey), key) } -// IsTxEvicted mocks base method. -func (m *MockMempool) IsTxEvicted(key types0.TxKey) bool { +// WasRecentlyEvicted mocks base method. +func (m *MockMempool) WasRecentlyEvicted(key types0.TxKey) bool { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsTxEvicted", key) + ret := m.ctrl.Call(m, "WasRecentlyEvicted", key) ret0, _ := ret[0].(bool) return ret0 } -// IsTxEvicted indicates an expected call of IsTxEvicted. -func (mr *MockMempoolMockRecorder) IsTxEvicted(key interface{}) *gomock.Call { +// WasRecentlyEvicted indicates an expected call of WasRecentlyEvicted. +func (mr *MockMempoolMockRecorder) WasRecentlyEvicted(key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsTxEvicted", reflect.TypeOf((*MockMempool)(nil).IsTxEvicted), key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WasRecentlyEvicted", reflect.TypeOf((*MockMempool)(nil).WasRecentlyEvicted), key) } // Lock mocks base method. diff --git a/rpc/core/tx.go b/rpc/core/tx.go index 7de85d81c8..a25cd477cb 100644 --- a/rpc/core/tx.go +++ b/rpc/core/tx.go @@ -246,7 +246,7 @@ func TxStatus(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultTxStatus, error } // Check if the tx is evicted - isEvicted := env.Mempool.IsTxEvicted(txKey) + isEvicted := env.Mempool.WasRecentlyEvicted(txKey) if isEvicted { return &ctypes.ResultTxStatus{Status: txStatusEvicted}, nil } diff --git a/rpc/core/tx_status_test.go b/rpc/core/tx_status_test.go index 604cc14f26..d91afd468c 100644 --- a/rpc/core/tx_status_test.go +++ b/rpc/core/tx_status_test.go @@ -58,8 +58,8 @@ func TestTxStatus(t *testing.T) { for _, tx := range txs { // Set GetTxByKey to return nil and false for all transactions mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() - // Set IsTxEvicted to return false for all transactions - mempool.EXPECT().IsTxEvicted(tx.Key()).Return(false).AnyTimes() + // Set WasRecentlyEvicted to return false for all transactions + mempool.EXPECT().WasRecentlyEvicted(tx.Key()).Return(false).AnyTimes() } }, @@ -97,8 +97,8 @@ func TestTxStatus(t *testing.T) { for _, tx := range txs { // Set GetTxByKey to return nil and false for all transactions mempool.EXPECT().GetTxByKey(tx.Key()).Return(nil, false).AnyTimes() - // Set IsTxEvicted to return true for all transactions - mempool.EXPECT().IsTxEvicted(tx.Key()).Return(true).AnyTimes() + // Set WasRecentlyEvicted to return true for all transactions + mempool.EXPECT().WasRecentlyEvicted(tx.Key()).Return(true).AnyTimes() } }, expectedStatus: "EVICTED", diff --git a/test/maverick/consensus/replay_stubs.go b/test/maverick/consensus/replay_stubs.go index 51064a839b..9fc3b45013 100644 --- a/test/maverick/consensus/replay_stubs.go +++ b/test/maverick/consensus/replay_stubs.go @@ -41,7 +41,7 @@ func (emptyMempool) EnableTxsAvailable() {} func (emptyMempool) TxsBytes() int64 { return 0 } func (emptyMempool) GetTxByKey(txKey types.TxKey) (types.Tx, bool) { return nil, false } -func (emptyMempool) IsTxEvicted(txKey types.TxKey) bool { return false } +func (emptyMempool) WasRecentlyEvicted(txKey types.TxKey) bool { return false } func (emptyMempool) TxsFront() *clist.CElement { return nil } func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } From 8e3c51dcd1c5ac51d1515f9630864feff4efe1a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nina=20/=20=E1=83=9C=E1=83=98=E1=83=9C=E1=83=90?= Date: Tue, 18 Jun 2024 08:50:37 +0200 Subject: [PATCH 47/47] Update mempool/cat/store.go Co-authored-by: Rootul P --- mempool/cat/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/cat/store.go b/mempool/cat/store.go index 92e468d616..33ecf1a851 100644 --- a/mempool/cat/store.go +++ b/mempool/cat/store.go @@ -141,7 +141,7 @@ func (s *store) getTxsBelowPriority(priority int64) ([]*wrappedTx, int64) { } // purgeExpiredTxs removes all transactions that are older than the given height -// and time. Returns the amount of transactions that were removed +// and time. Returns the purged txs and amount of transactions that were purged. func (s *store) purgeExpiredTxs(expirationHeight int64, expirationAge time.Time) ([]*wrappedTx, int) { s.mtx.Lock() defer s.mtx.Unlock()