From 0d0ac62e65f09292793026e11e947306ff515238 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 20 Dec 2023 10:21:28 -0500 Subject: [PATCH] Make X-chain mempool safe for concurrent use (#2520) --- vms/avm/block/builder/builder_test.go | 4 +- vms/avm/network/network.go | 2 +- vms/avm/network/network_test.go | 22 +- vms/avm/txs/mempool/mempool.go | 116 +++++---- vms/avm/txs/mempool/mempool_test.go | 343 ++++++++++++++++---------- vms/avm/txs/mempool/mock_mempool.go | 19 +- 6 files changed, 298 insertions(+), 208 deletions(-) diff --git a/vms/avm/block/builder/builder_test.go b/vms/avm/block/builder/builder_test.go index d15a5f8d08f7..e034db41cf91 100644 --- a/vms/avm/block/builder/builder_test.go +++ b/vms/avm/block/builder/builder_test.go @@ -510,7 +510,9 @@ func TestBlockBuilderAddLocalTx(t *testing.T) { tx := transactions[0] txID := tx.ID() require.NoError(mempool.Add(tx)) - require.True(mempool.Has(txID)) + + _, ok := mempool.Get(txID) + require.True(ok) parser, err := block.NewParser([]fxs.Fx{ &secp256k1fx.Fx{}, diff --git a/vms/avm/network/network.go b/vms/avm/network/network.go index a1d3337ddb23..0f4fc6b52de2 100644 --- a/vms/avm/network/network.go +++ b/vms/avm/network/network.go @@ -141,7 +141,7 @@ func (n *network) IssueTx(ctx context.Context, tx *txs.Tx) error { // returns nil if the tx is in the mempool func (n *network) issueTx(tx *txs.Tx) error { txID := tx.ID() - if n.mempool.Has(txID) { + if _, ok := n.mempool.Get(txID); ok { // The tx is already in the mempool return nil } diff --git a/vms/avm/network/network_test.go b/vms/avm/network/network_test.go index 6d779eadcc28..0217430a2d22 100644 --- a/vms/avm/network/network_test.go +++ b/vms/avm/network/network_test.go @@ -91,7 +91,8 @@ func TestNetworkAppGossip(t *testing.T) { }, }, { - // Issue returns nil because mempool has tx. We should gossip the tx. + // Issue returns nil because mempool has tx. We haven't gossipped + // the tx recently, so we should gossip it. name: "issuance succeeds", msgBytesFunc: func() []byte { msg := message.Tx{ @@ -103,17 +104,18 @@ func TestNetworkAppGossip(t *testing.T) { }, mempoolFunc: func(ctrl *gomock.Controller) mempool.Mempool { mempool := mempool.NewMockMempool(ctrl) - mempool.EXPECT().Has(gomock.Any()).Return(true) + mempool.EXPECT().Get(gomock.Any()).Return(testTx, true) return mempool }, appSenderFunc: func(ctrl *gomock.Controller) common.AppSender { appSender := common.NewMockSender(ctrl) - appSender.EXPECT().SendAppGossip(gomock.Any(), gomock.Any()) + appSender.EXPECT().SendAppGossip(gomock.Any(), gomock.Any()).Times(1) return appSender }, }, { - // Issue returns error because tx was dropped. We shouldn't gossip the tx. + // Issue returns error because tx was dropped. We shouldn't gossip + // the tx. name: "issuance fails", msgBytesFunc: func() []byte { msg := message.Tx{ @@ -125,7 +127,7 @@ func TestNetworkAppGossip(t *testing.T) { }, mempoolFunc: func(ctrl *gomock.Controller) mempool.Mempool { mempool := mempool.NewMockMempool(ctrl) - mempool.EXPECT().Has(gomock.Any()).Return(false) + mempool.EXPECT().Get(gomock.Any()).Return(nil, false) mempool.EXPECT().GetDropReason(gomock.Any()).Return(errTest) return mempool }, @@ -176,7 +178,7 @@ func TestNetworkIssueTx(t *testing.T) { name: "mempool has transaction", mempoolFunc: func(ctrl *gomock.Controller) mempool.Mempool { mempool := mempool.NewMockMempool(ctrl) - mempool.EXPECT().Has(gomock.Any()).Return(true) + mempool.EXPECT().Get(gomock.Any()).Return(nil, true) return mempool }, managerFunc: func(ctrl *gomock.Controller) executor.Manager { @@ -195,7 +197,7 @@ func TestNetworkIssueTx(t *testing.T) { name: "transaction marked as dropped in mempool", mempoolFunc: func(ctrl *gomock.Controller) mempool.Mempool { mempool := mempool.NewMockMempool(ctrl) - mempool.EXPECT().Has(gomock.Any()).Return(false) + mempool.EXPECT().Get(gomock.Any()).Return(nil, false) mempool.EXPECT().GetDropReason(gomock.Any()).Return(errTest) return mempool }, @@ -213,7 +215,7 @@ func TestNetworkIssueTx(t *testing.T) { name: "transaction invalid", mempoolFunc: func(ctrl *gomock.Controller) mempool.Mempool { mempool := mempool.NewMockMempool(ctrl) - mempool.EXPECT().Has(gomock.Any()).Return(false) + mempool.EXPECT().Get(gomock.Any()).Return(nil, false) mempool.EXPECT().GetDropReason(gomock.Any()).Return(nil) mempool.EXPECT().MarkDropped(gomock.Any(), gomock.Any()) return mempool @@ -233,7 +235,7 @@ func TestNetworkIssueTx(t *testing.T) { name: "can't add transaction to mempool", mempoolFunc: func(ctrl *gomock.Controller) mempool.Mempool { mempool := mempool.NewMockMempool(ctrl) - mempool.EXPECT().Has(gomock.Any()).Return(false) + mempool.EXPECT().Get(gomock.Any()).Return(nil, false) mempool.EXPECT().GetDropReason(gomock.Any()).Return(nil) mempool.EXPECT().Add(gomock.Any()).Return(errTest) mempool.EXPECT().MarkDropped(gomock.Any(), gomock.Any()) @@ -254,7 +256,7 @@ func TestNetworkIssueTx(t *testing.T) { name: "happy path", mempoolFunc: func(ctrl *gomock.Controller) mempool.Mempool { mempool := mempool.NewMockMempool(ctrl) - mempool.EXPECT().Has(gomock.Any()).Return(false) + mempool.EXPECT().Get(gomock.Any()).Return(nil, false) mempool.EXPECT().GetDropReason(gomock.Any()).Return(nil) mempool.EXPECT().Add(gomock.Any()).Return(nil) mempool.EXPECT().RequestBuildBlock() diff --git a/vms/avm/txs/mempool/mempool.go b/vms/avm/txs/mempool/mempool.go index 6e22ee61407a..db42c9cca418 100644 --- a/vms/avm/txs/mempool/mempool.go +++ b/vms/avm/txs/mempool/mempool.go @@ -6,12 +6,14 @@ package mempool import ( "errors" "fmt" + "sync" "github.com/prometheus/client_golang/prometheus" "github.com/ava-labs/avalanchego/cache" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/engine/common" + "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/linkedhashmap" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/units" @@ -26,8 +28,6 @@ const ( // droppedTxIDsCacheSize is the maximum number of dropped txIDs to cache droppedTxIDsCacheSize = 64 - initialConsumedUTXOsSize = 512 - // maxMempoolSize is the maximum number of bytes allowed in the mempool maxMempoolSize = 64 * units.MiB ) @@ -44,13 +44,16 @@ var ( // Mempool contains transactions that have not yet been put into a block. type Mempool interface { Add(tx *txs.Tx) error - Has(txID ids.ID) bool - Get(txID ids.ID) *txs.Tx + Get(txID ids.ID) (*txs.Tx, bool) Remove(txs []*txs.Tx) // Peek returns the oldest tx in the mempool. Peek() (tx *txs.Tx, exists bool) + // Iterate over transactions from oldest to newest until the function + // returns false or there are no more transactions. + Iterate(f func(tx *txs.Tx) bool) + // RequestBuildBlock notifies the consensus engine that a block should be // built if there is at least one transaction in the mempool. RequestBuildBlock() @@ -62,19 +65,16 @@ type Mempool interface { } type mempool struct { - bytesAvailableMetric prometheus.Gauge - bytesAvailable int - - unissuedTxs linkedhashmap.LinkedHashmap[ids.ID, *txs.Tx] - numTxs prometheus.Gauge + lock sync.RWMutex + unissuedTxs linkedhashmap.LinkedHashmap[ids.ID, *txs.Tx] + consumedUTXOs set.Set[ids.ID] + bytesAvailable int + droppedTxIDs *cache.LRU[ids.ID, error] // TxID -> Verification error toEngine chan<- common.Message - // Key: Tx ID - // Value: Verification error - droppedTxIDs *cache.LRU[ids.ID, error] - - consumedUTXOs set.Set[ids.ID] + numTxs prometheus.Gauge + bytesAvailableMetric prometheus.Gauge } func New( @@ -82,40 +82,38 @@ func New( registerer prometheus.Registerer, toEngine chan<- common.Message, ) (Mempool, error) { - bytesAvailableMetric := prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: namespace, - Name: "bytes_available", - Help: "Number of bytes of space currently available in the mempool", - }) - if err := registerer.Register(bytesAvailableMetric); err != nil { - return nil, err + m := &mempool{ + unissuedTxs: linkedhashmap.New[ids.ID, *txs.Tx](), + bytesAvailable: maxMempoolSize, + droppedTxIDs: &cache.LRU[ids.ID, error]{Size: droppedTxIDsCacheSize}, + toEngine: toEngine, + numTxs: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: namespace, + Name: "count", + Help: "Number of transactions in the mempool", + }), + bytesAvailableMetric: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: namespace, + Name: "bytes_available", + Help: "Number of bytes of space currently available in the mempool", + }), } + m.bytesAvailableMetric.Set(maxMempoolSize) - numTxsMetric := prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: namespace, - Name: "count", - Help: "Number of transactions in the mempool", - }) - if err := registerer.Register(numTxsMetric); err != nil { - return nil, err - } - - bytesAvailableMetric.Set(maxMempoolSize) - return &mempool{ - bytesAvailableMetric: bytesAvailableMetric, - bytesAvailable: maxMempoolSize, - unissuedTxs: linkedhashmap.New[ids.ID, *txs.Tx](), - numTxs: numTxsMetric, - toEngine: toEngine, - droppedTxIDs: &cache.LRU[ids.ID, error]{Size: droppedTxIDsCacheSize}, - consumedUTXOs: set.NewSet[ids.ID](initialConsumedUTXOsSize), - }, nil + err := utils.Err( + registerer.Register(m.numTxs), + registerer.Register(m.bytesAvailableMetric), + ) + return m, err } func (m *mempool) Add(tx *txs.Tx) error { - // Note: a previously dropped tx can be re-added txID := tx.ID() - if m.Has(txID) { + + m.lock.Lock() + defer m.lock.Unlock() + + if _, ok := m.unissuedTxs.Get(txID); ok { return fmt.Errorf("%w: %s", errDuplicateTx, txID) } @@ -151,21 +149,20 @@ func (m *mempool) Add(tx *txs.Tx) error { // Mark these UTXOs as consumed in the mempool m.consumedUTXOs.Union(inputs) - // An explicitly added tx must not be marked as dropped. + // An added tx must not be marked as dropped. m.droppedTxIDs.Evict(txID) return nil } -func (m *mempool) Has(txID ids.ID) bool { - return m.Get(txID) != nil -} - -func (m *mempool) Get(txID ids.ID) *txs.Tx { - tx, _ := m.unissuedTxs.Get(txID) - return tx +func (m *mempool) Get(txID ids.ID) (*txs.Tx, bool) { + tx, ok := m.unissuedTxs.Get(txID) + return tx, ok } func (m *mempool) Remove(txsToRemove []*txs.Tx) { + m.lock.Lock() + defer m.lock.Unlock() + for _, tx := range txsToRemove { txID := tx.ID() if !m.unissuedTxs.Delete(txID) { @@ -187,6 +184,18 @@ func (m *mempool) Peek() (*txs.Tx, bool) { return tx, exists } +func (m *mempool) Iterate(f func(*txs.Tx) bool) { + m.lock.RLock() + defer m.lock.RUnlock() + + it := m.unissuedTxs.NewIterator() + for it.Next() { + if !f(it.Value()) { + return + } + } +} + func (m *mempool) RequestBuildBlock() { if m.unissuedTxs.Len() == 0 { return @@ -199,6 +208,13 @@ func (m *mempool) RequestBuildBlock() { } func (m *mempool) MarkDropped(txID ids.ID, reason error) { + m.lock.RLock() + defer m.lock.RUnlock() + + if _, ok := m.unissuedTxs.Get(txID); ok { + return + } + m.droppedTxIDs.Put(txID, reason) } diff --git a/vms/avm/txs/mempool/mempool_test.go b/vms/avm/txs/mempool/mempool_test.go index 2e009fc44520..a4760ceba792 100644 --- a/vms/avm/txs/mempool/mempool_test.go +++ b/vms/avm/txs/mempool/mempool_test.go @@ -4,6 +4,7 @@ package mempool import ( + "errors" "testing" "github.com/prometheus/client_golang/prometheus" @@ -13,196 +14,266 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/components/verify" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" ) -var ( - keys = secp256k1.TestKeys() - chainID = ids.ID{5, 4, 3, 2, 1} - assetID = ids.ID{1, 2, 3} -) +func TestAdd(t *testing.T) { + tx0 := newTx(0, 32) + + tests := []struct { + name string + initialTxs []*txs.Tx + tx *txs.Tx + err error + }{ + { + name: "successfully add tx", + initialTxs: nil, + tx: tx0, + err: nil, + }, + { + name: "attempt adding duplicate tx", + initialTxs: []*txs.Tx{tx0}, + tx: tx0, + err: errDuplicateTx, + }, + { + name: "attempt adding too large tx", + initialTxs: nil, + tx: newTx(0, MaxTxSize+1), + err: errTxTooLarge, + }, + { + name: "attempt adding tx when full", + initialTxs: newTxs(maxMempoolSize/MaxTxSize, MaxTxSize), + tx: newTx(maxMempoolSize/MaxTxSize, MaxTxSize), + err: errMempoolFull, + }, + { + name: "attempt adding conflicting tx", + initialTxs: []*txs.Tx{tx0}, + tx: newTx(0, 32), + err: errConflictsWithOtherTx, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require := require.New(t) + + mempool, err := New( + "mempool", + prometheus.NewRegistry(), + nil, + ) + require.NoError(err) + + for _, tx := range test.initialTxs { + require.NoError(mempool.Add(tx)) + } + + err = mempool.Add(test.tx) + require.ErrorIs(err, test.err) + }) + } +} -// shows that valid tx is not added to mempool if this would exceed its maximum -// size -func TestBlockBuilderMaxMempoolSizeHandling(t *testing.T) { +func TestGet(t *testing.T) { require := require.New(t) - registerer := prometheus.NewRegistry() - mempoolIntf, err := New("mempool", registerer, nil) + mempool, err := New( + "mempool", + prometheus.NewRegistry(), + nil, + ) require.NoError(err) - mempool := mempoolIntf.(*mempool) + tx := newTx(0, 32) + txID := tx.ID() - testTxs := createTestTxs(2) - tx := testTxs[0] + _, exists := mempool.Get(txID) + require.False(exists) - // shortcut to simulated almost filled mempool - mempool.bytesAvailable = len(tx.Bytes()) - 1 + require.NoError(mempool.Add(tx)) - err = mempool.Add(tx) - require.ErrorIs(err, errMempoolFull) + returned, exists := mempool.Get(txID) + require.True(exists) + require.Equal(tx, returned) - // shortcut to simulated almost filled mempool - mempool.bytesAvailable = len(tx.Bytes()) + mempool.Remove([]*txs.Tx{tx}) - require.NoError(mempool.Add(tx)) + _, exists = mempool.Get(txID) + require.False(exists) } -func TestTxsInMempool(t *testing.T) { +func TestPeek(t *testing.T) { require := require.New(t) - registerer := prometheus.NewRegistry() - toEngine := make(chan common.Message, 100) - mempool, err := New("mempool", registerer, toEngine) + mempool, err := New( + "mempool", + prometheus.NewRegistry(), + nil, + ) require.NoError(err) - testTxs := createTestTxs(2) + _, exists := mempool.Peek() + require.False(exists) - mempool.RequestBuildBlock() - select { - case <-toEngine: - require.FailNow("should not have sent message to engine") - default: - } + tx0 := newTx(0, 32) + tx1 := newTx(1, 32) + + require.NoError(mempool.Add(tx0)) + require.NoError(mempool.Add(tx1)) - for _, tx := range testTxs { - txID := tx.ID() - // tx not already there - require.False(mempool.Has(txID)) + tx, exists := mempool.Peek() + require.True(exists) + require.Equal(tx, tx0) - // we can insert - require.NoError(mempool.Add(tx)) + mempool.Remove([]*txs.Tx{tx0}) - // we can get it - require.True(mempool.Has(txID)) + tx, exists = mempool.Peek() + require.True(exists) + require.Equal(tx, tx1) - retrieved := mempool.Get(txID) - require.NotNil(retrieved) - require.Equal(tx, retrieved) + mempool.Remove([]*txs.Tx{tx0}) - // tx exists in mempool - require.True(mempool.Has(txID)) + tx, exists = mempool.Peek() + require.True(exists) + require.Equal(tx, tx1) - // once removed it cannot be there - mempool.Remove([]*txs.Tx{tx}) + mempool.Remove([]*txs.Tx{tx1}) - require.False(mempool.Has(txID)) - require.Nil(mempool.Get(txID)) + _, exists = mempool.Peek() + require.False(exists) +} - // we can reinsert it again to grow the mempool - require.NoError(mempool.Add(tx)) +func TestIterate(t *testing.T) { + require := require.New(t) + + mempool, err := New( + "mempool", + prometheus.NewRegistry(), + nil, + ) + require.NoError(err) + + var ( + iteratedTxs []*txs.Tx + maxLen = 2 + ) + addTxs := func(tx *txs.Tx) bool { + iteratedTxs = append(iteratedTxs, tx) + return len(iteratedTxs) < maxLen } + mempool.Iterate(addTxs) + require.Empty(iteratedTxs) + + tx0 := newTx(0, 32) + require.NoError(mempool.Add(tx0)) + + mempool.Iterate(addTxs) + require.Equal([]*txs.Tx{tx0}, iteratedTxs) + + tx1 := newTx(1, 32) + require.NoError(mempool.Add(tx1)) + + iteratedTxs = nil + mempool.Iterate(addTxs) + require.Equal([]*txs.Tx{tx0, tx1}, iteratedTxs) + + tx2 := newTx(2, 32) + require.NoError(mempool.Add(tx2)) + + iteratedTxs = nil + mempool.Iterate(addTxs) + require.Equal([]*txs.Tx{tx0, tx1}, iteratedTxs) + + mempool.Remove([]*txs.Tx{tx0, tx2}) + + iteratedTxs = nil + mempool.Iterate(addTxs) + require.Equal([]*txs.Tx{tx1}, iteratedTxs) +} + +func TestRequestBuildBlock(t *testing.T) { + require := require.New(t) + + toEngine := make(chan common.Message, 1) + mempool, err := New( + "mempool", + prometheus.NewRegistry(), + toEngine, + ) + require.NoError(err) mempool.RequestBuildBlock() select { case <-toEngine: + require.FailNow("should not have sent message to engine") default: - require.FailNow("should have sent message to engine") } - mempool.Remove(testTxs) + tx := newTx(0, 32) + require.NoError(mempool.Add(tx)) mempool.RequestBuildBlock() + mempool.RequestBuildBlock() // Must not deadlock select { case <-toEngine: - require.FailNow("should not have sent message to engine") default: + require.FailNow("should have sent message to engine") } -} - -func createTestTxs(count int) []*txs.Tx { - testTxs := make([]*txs.Tx, 0, count) - addr := keys[0].PublicKey().Address() - for i := uint32(0); i < uint32(count); i++ { - tx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: chainID, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: ids.ID{'t', 'x', 'I', 'D'}, - OutputIndex: i, - }, - Asset: avax.Asset{ID: assetID}, - In: &secp256k1fx.TransferInput{ - Amt: 54321, - Input: secp256k1fx.Input{ - SigIndices: []uint32{i}, - }, - }, - }}, - Outs: []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: assetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: 12345, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{addr}, - }, - }, - }}, - }}, - Name: "NormalName", - Symbol: "TICK", - Denomination: byte(2), - States: []*txs.InitialState{ - { - FxIndex: 0, - Outs: []verify.State{ - &secp256k1fx.TransferOutput{ - Amt: 12345, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{addr}, - }, - }, - }, - }, - }, - }} - tx.SetBytes(utils.RandomBytes(16), utils.RandomBytes(16)) - testTxs = append(testTxs, tx) + select { + case <-toEngine: + require.FailNow("should have only sent one message to engine") + default: } - return testTxs } -func TestPeekTxs(t *testing.T) { +func TestDropped(t *testing.T) { require := require.New(t) - registerer := prometheus.NewRegistry() - toEngine := make(chan common.Message, 100) - mempool, err := New("mempool", registerer, toEngine) + mempool, err := New( + "mempool", + prometheus.NewRegistry(), + nil, + ) require.NoError(err) - testTxs := createTestTxs(2) - - tx, exists := mempool.Peek() - require.False(exists) - require.Nil(tx) + tx := newTx(0, 32) + txID := tx.ID() + testErr := errors.New("test") - require.NoError(mempool.Add(testTxs[0])) - require.NoError(mempool.Add(testTxs[1])) + mempool.MarkDropped(txID, testErr) - tx, exists = mempool.Peek() - require.True(exists) - require.Equal(tx, testTxs[0]) - require.NotEqual(tx, testTxs[1]) + err = mempool.GetDropReason(txID) + require.ErrorIs(err, testErr) - mempool.Remove([]*txs.Tx{testTxs[0]}) + require.NoError(mempool.Add(tx)) + require.NoError(mempool.GetDropReason(txID)) - tx, exists = mempool.Peek() - require.True(exists) - require.NotEqual(tx, testTxs[0]) - require.Equal(tx, testTxs[1]) + mempool.MarkDropped(txID, testErr) + require.NoError(mempool.GetDropReason(txID)) +} - mempool.Remove([]*txs.Tx{testTxs[1]}) +func newTxs(num int, size int) []*txs.Tx { + txs := make([]*txs.Tx, num) + for i := range txs { + txs[i] = newTx(uint32(i), size) + } + return txs +} - tx, exists = mempool.Peek() - require.False(exists) - require.Nil(tx) +func newTx(index uint32, size int) *txs.Tx { + tx := &txs.Tx{Unsigned: &txs.BaseTx{BaseTx: avax.BaseTx{ + Ins: []*avax.TransferableInput{{ + UTXOID: avax.UTXOID{ + TxID: ids.ID{'t', 'x', 'I', 'D'}, + OutputIndex: index, + }, + }}, + }}} + tx.SetBytes(utils.RandomBytes(size), utils.RandomBytes(size)) + return tx } diff --git a/vms/avm/txs/mempool/mock_mempool.go b/vms/avm/txs/mempool/mock_mempool.go index 8660976dde0d..9c85b8f4590a 100644 --- a/vms/avm/txs/mempool/mock_mempool.go +++ b/vms/avm/txs/mempool/mock_mempool.go @@ -53,11 +53,12 @@ func (mr *MockMempoolMockRecorder) Add(arg0 interface{}) *gomock.Call { } // Get mocks base method. -func (m *MockMempool) Get(arg0 ids.ID) *txs.Tx { +func (m *MockMempool) Get(arg0 ids.ID) (*txs.Tx, bool) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0) ret0, _ := ret[0].(*txs.Tx) - return ret0 + ret1, _ := ret[1].(bool) + return ret0, ret1 } // Get indicates an expected call of Get. @@ -80,18 +81,16 @@ func (mr *MockMempoolMockRecorder) GetDropReason(arg0 interface{}) *gomock.Call return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDropReason", reflect.TypeOf((*MockMempool)(nil).GetDropReason), arg0) } -// Has mocks base method. -func (m *MockMempool) Has(arg0 ids.ID) bool { +// Iterate mocks base method. +func (m *MockMempool) Iterate(arg0 func(*txs.Tx) bool) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Has", arg0) - ret0, _ := ret[0].(bool) - return ret0 + m.ctrl.Call(m, "Iterate", arg0) } -// Has indicates an expected call of Has. -func (mr *MockMempoolMockRecorder) Has(arg0 interface{}) *gomock.Call { +// Iterate indicates an expected call of Iterate. +func (mr *MockMempoolMockRecorder) Iterate(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Has", reflect.TypeOf((*MockMempool)(nil).Has), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Iterate", reflect.TypeOf((*MockMempool)(nil).Iterate), arg0) } // MarkDropped mocks base method.