github.com/okex/exchain@v1.8.0/libs/tendermint/mempool/clist_mempool_test.go (about)

     1  package mempool
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"math/big"
     8  	mrand "math/rand"
     9  	"os"
    10  	"strconv"
    11  	"sync"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/okex/exchain/libs/tendermint/libs/clist"
    16  
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/stretchr/testify/require"
    19  
    20  	amino "github.com/tendermint/go-amino"
    21  
    22  	"github.com/okex/exchain/libs/tendermint/abci/example/counter"
    23  	"github.com/okex/exchain/libs/tendermint/abci/example/kvstore"
    24  	abci "github.com/okex/exchain/libs/tendermint/abci/types"
    25  	cfg "github.com/okex/exchain/libs/tendermint/config"
    26  	"github.com/okex/exchain/libs/tendermint/libs/log"
    27  	tmrand "github.com/okex/exchain/libs/tendermint/libs/rand"
    28  	"github.com/okex/exchain/libs/tendermint/proxy"
    29  	"github.com/okex/exchain/libs/tendermint/types"
    30  )
    31  
    32  const (
    33  	BlockMaxTxNum = 300
    34  )
    35  
    36  // A cleanupFunc cleans up any config / test files created for a particular
    37  // test.
    38  type cleanupFunc func()
    39  
    40  func newMempoolWithApp(cc proxy.ClientCreator) (*CListMempool, cleanupFunc) {
    41  	return newMempoolWithAppAndConfig(cc, cfg.ResetTestRoot("mempool_test"))
    42  }
    43  
    44  func newMempoolWithAppAndConfig(cc proxy.ClientCreator, config *cfg.Config) (*CListMempool, cleanupFunc) {
    45  	appConnMem, _ := cc.NewABCIClient()
    46  	appConnMem.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "mempool"))
    47  	err := appConnMem.Start()
    48  	if err != nil {
    49  		panic(err)
    50  	}
    51  	mempool := NewCListMempool(config.Mempool, appConnMem, 0)
    52  	mempool.SetLogger(log.TestingLogger())
    53  	return mempool, func() { os.RemoveAll(config.RootDir) }
    54  }
    55  
    56  func ensureNoFire(t *testing.T, ch <-chan struct{}, timeoutMS int) {
    57  	timer := time.NewTimer(time.Duration(timeoutMS) * time.Millisecond)
    58  	select {
    59  	case <-ch:
    60  		t.Fatal("Expected not to fire")
    61  	case <-timer.C:
    62  	}
    63  }
    64  
    65  func ensureFire(t *testing.T, ch <-chan struct{}, timeoutMS int) {
    66  	timer := time.NewTimer(time.Duration(timeoutMS) * time.Millisecond)
    67  	select {
    68  	case <-ch:
    69  	case <-timer.C:
    70  		t.Fatal("Expected to fire")
    71  	}
    72  }
    73  
    74  func checkTxs(t *testing.T, mempool Mempool, count int, peerID uint16) types.Txs {
    75  	txs := make(types.Txs, count)
    76  	txInfo := TxInfo{SenderID: peerID}
    77  	for i := 0; i < count; i++ {
    78  		txBytes := make([]byte, 20)
    79  		txs[i] = txBytes
    80  		_, err := rand.Read(txBytes)
    81  		if err != nil {
    82  			t.Error(err)
    83  		}
    84  		if err := mempool.CheckTx(txBytes, nil, txInfo); err != nil {
    85  			// Skip invalid txs.
    86  			// TestMempoolFilters will fail otherwise. It asserts a number of txs
    87  			// returned.
    88  			if IsPreCheckError(err) {
    89  				continue
    90  			}
    91  			t.Fatalf("CheckTx failed: %v while checking #%d tx", err, i)
    92  		}
    93  	}
    94  	return txs
    95  }
    96  
    97  func TestReapMaxBytesMaxGas(t *testing.T) {
    98  	app := kvstore.NewApplication()
    99  	cc := proxy.NewLocalClientCreator(app)
   100  	mempool, cleanup := newMempoolWithApp(cc)
   101  	defer cleanup()
   102  
   103  	// Ensure gas calculation behaves as expected
   104  	checkTxs(t, mempool, 1, UnknownPeerID)
   105  	tx0 := mempool.TxsFront().Value.(*mempoolTx)
   106  	// assert that kv store has gas wanted = 1.
   107  	require.Equal(t, app.CheckTx(abci.RequestCheckTx{Tx: tx0.tx}).GasWanted, int64(1), "KVStore had a gas value neq to 1")
   108  	require.Equal(t, tx0.gasLimit, int64(1), "transactions gas was set incorrectly")
   109  	// ensure each tx is 20 bytes long
   110  	require.Equal(t, len(tx0.tx), 20, "Tx is longer than 20 bytes")
   111  	mempool.Flush()
   112  	assert.Zero(t, mempool.Size())
   113  
   114  	// each table driven test creates numTxsToCreate txs with checkTx, and at the end clears all remaining txs.
   115  	// each tx has 20 bytes + amino overhead = 21 bytes, 1 gas
   116  	tests := []struct {
   117  		numTxsToCreate int
   118  		maxBytes       int64
   119  		maxGas         int64
   120  		expectedNumTxs int
   121  	}{
   122  		{20, -1, -1, 20},
   123  		{20, -1, 0, 1},
   124  		{20, -1, 10, 10},
   125  		{20, -1, 30, 20},
   126  		{20, 0, -1, 0},
   127  		{20, 0, 10, 0},
   128  		{20, 10, 10, 0},
   129  		{20, 22, 10, 1},
   130  		{20, 220, -1, 10},
   131  		{20, 220, 5, 5},
   132  		{20, 220, 10, 10},
   133  		{20, 220, 15, 10},
   134  		{20, 20000, -1, 20},
   135  		{20, 20000, 5, 5},
   136  		{20, 20000, 30, 20},
   137  		{2000, -1, -1, 300},
   138  	}
   139  	for tcIndex, tt := range tests {
   140  		checkTxs(t, mempool, tt.numTxsToCreate, UnknownPeerID)
   141  		got := mempool.ReapMaxBytesMaxGas(tt.maxBytes, tt.maxGas)
   142  		assert.Equal(t, tt.expectedNumTxs, len(got), "Got %d txs, expected %d, tc #%d",
   143  			len(got), tt.expectedNumTxs, tcIndex)
   144  		mempool.Flush()
   145  		assert.Zero(t, mempool.Size())
   146  	}
   147  }
   148  
   149  func TestMempoolFilters(t *testing.T) {
   150  	app := kvstore.NewApplication()
   151  	cc := proxy.NewLocalClientCreator(app)
   152  	mempool, cleanup := newMempoolWithApp(cc)
   153  	defer cleanup()
   154  	emptyTxArr := []types.Tx{[]byte{}}
   155  
   156  	nopPreFilter := func(tx types.Tx) error { return nil }
   157  	nopPostFilter := func(tx types.Tx, res *abci.ResponseCheckTx) error { return nil }
   158  
   159  	// each table driven test creates numTxsToCreate txs with checkTx, and at the end clears all remaining txs.
   160  	// each tx has 20 bytes + amino overhead = 21 bytes, 1 gas
   161  	tests := []struct {
   162  		numTxsToCreate int
   163  		preFilter      PreCheckFunc
   164  		postFilter     PostCheckFunc
   165  		expectedNumTxs int
   166  	}{
   167  		{10, nopPreFilter, nopPostFilter, 10},
   168  		{10, PreCheckAminoMaxBytes(10), nopPostFilter, 0},
   169  		{10, PreCheckAminoMaxBytes(20), nopPostFilter, 0},
   170  		{10, PreCheckAminoMaxBytes(22), nopPostFilter, 10},
   171  		{10, nopPreFilter, PostCheckMaxGas(-1), 10},
   172  		{10, nopPreFilter, PostCheckMaxGas(0), 0},
   173  		{10, nopPreFilter, PostCheckMaxGas(1), 10},
   174  		{10, nopPreFilter, PostCheckMaxGas(3000), 10},
   175  		{10, PreCheckAminoMaxBytes(10), PostCheckMaxGas(20), 0},
   176  		{10, PreCheckAminoMaxBytes(30), PostCheckMaxGas(20), 10},
   177  		{10, PreCheckAminoMaxBytes(22), PostCheckMaxGas(1), 10},
   178  		{10, PreCheckAminoMaxBytes(22), PostCheckMaxGas(0), 0},
   179  	}
   180  	for tcIndex, tt := range tests {
   181  		mempool.Update(1, emptyTxArr, abciResponses(len(emptyTxArr), abci.CodeTypeOK), tt.preFilter, tt.postFilter)
   182  		checkTxs(t, mempool, tt.numTxsToCreate, UnknownPeerID)
   183  		require.Equal(t, tt.expectedNumTxs, mempool.Size(), "mempool had the incorrect size, on test case %d", tcIndex)
   184  		mempool.Flush()
   185  	}
   186  }
   187  
   188  func TestMempoolUpdate(t *testing.T) {
   189  	app := kvstore.NewApplication()
   190  	cc := proxy.NewLocalClientCreator(app)
   191  	mempool, cleanup := newMempoolWithApp(cc)
   192  	defer cleanup()
   193  
   194  	// 1. Adds valid txs to the cache
   195  	{
   196  		mempool.Update(1, []types.Tx{[]byte{0x01}}, abciResponses(1, abci.CodeTypeOK), nil, nil)
   197  		err := mempool.CheckTx([]byte{0x01}, nil, TxInfo{})
   198  		if assert.Error(t, err) {
   199  			assert.Equal(t, ErrTxInCache, err)
   200  		}
   201  	}
   202  
   203  	// 2. Removes valid txs from the mempool
   204  	{
   205  		err := mempool.CheckTx([]byte{0x02}, nil, TxInfo{})
   206  		require.NoError(t, err)
   207  		mempool.Update(1, []types.Tx{[]byte{0x02}}, abciResponses(1, abci.CodeTypeOK), nil, nil)
   208  		assert.Zero(t, mempool.Size())
   209  	}
   210  
   211  	// 3. Removes invalid transactions from the cache and the mempool (if present)
   212  	{
   213  		err := mempool.CheckTx([]byte{0x03}, nil, TxInfo{})
   214  		require.NoError(t, err)
   215  		mempool.Update(1, []types.Tx{[]byte{0x03}}, abciResponses(1, 1), nil, nil)
   216  		assert.Zero(t, mempool.Size())
   217  
   218  		err = mempool.CheckTx([]byte{0x03}, nil, TxInfo{})
   219  		assert.NoError(t, err)
   220  	}
   221  }
   222  
   223  func TestTxsAvailable(t *testing.T) {
   224  	app := kvstore.NewApplication()
   225  	cc := proxy.NewLocalClientCreator(app)
   226  	mempool, cleanup := newMempoolWithApp(cc)
   227  	defer cleanup()
   228  	mempool.EnableTxsAvailable()
   229  
   230  	timeoutMS := 500
   231  
   232  	// with no txs, it shouldnt fire
   233  	ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
   234  
   235  	// send a bunch of txs, it should only fire once
   236  	txs := checkTxs(t, mempool, 100, UnknownPeerID)
   237  	ensureFire(t, mempool.TxsAvailable(), timeoutMS)
   238  	ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
   239  
   240  	// call update with half the txs.
   241  	// it should fire once now for the new height
   242  	// since there are still txs left
   243  	committedTxs, txs := txs[:50], txs[50:]
   244  	if err := mempool.Update(1, committedTxs, abciResponses(len(committedTxs), abci.CodeTypeOK), nil, nil); err != nil {
   245  		t.Error(err)
   246  	}
   247  	ensureFire(t, mempool.TxsAvailable(), timeoutMS)
   248  	ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
   249  
   250  	// send a bunch more txs. we already fired for this height so it shouldnt fire again
   251  	moreTxs := checkTxs(t, mempool, 50, UnknownPeerID)
   252  	ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
   253  
   254  	// now call update with all the txs. it should not fire as there are no txs left
   255  	committedTxs = append(txs, moreTxs...) //nolint: gocritic
   256  	if err := mempool.Update(2, committedTxs, abciResponses(len(committedTxs), abci.CodeTypeOK), nil, nil); err != nil {
   257  		t.Error(err)
   258  	}
   259  	ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
   260  
   261  	// send a bunch more txs, it should only fire once
   262  	checkTxs(t, mempool, 100, UnknownPeerID)
   263  	ensureFire(t, mempool.TxsAvailable(), timeoutMS)
   264  	ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
   265  }
   266  
   267  func TestSerialReap(t *testing.T) {
   268  	app := counter.NewApplication(true)
   269  	app.SetOption(abci.RequestSetOption{Key: "serial", Value: "on"})
   270  	cc := proxy.NewLocalClientCreator(app)
   271  
   272  	mempool, cleanup := newMempoolWithApp(cc)
   273  	defer cleanup()
   274  	mempool.config.MaxTxNumPerBlock = 10000
   275  
   276  	appConnCon, _ := cc.NewABCIClient()
   277  	appConnCon.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "consensus"))
   278  	err := appConnCon.Start()
   279  	require.Nil(t, err)
   280  
   281  	cacheMap := make(map[string]struct{})
   282  	deliverTxsRange := func(start, end int) {
   283  		// Deliver some txs.
   284  		for i := start; i < end; i++ {
   285  
   286  			// This will succeed
   287  			txBytes := make([]byte, 8)
   288  			binary.BigEndian.PutUint64(txBytes, uint64(i))
   289  			err := mempool.CheckTx(txBytes, nil, TxInfo{})
   290  			_, cached := cacheMap[string(txBytes)]
   291  			if cached {
   292  				require.NotNil(t, err, "expected error for cached tx")
   293  			} else {
   294  				require.Nil(t, err, "expected no err for uncached tx")
   295  			}
   296  			cacheMap[string(txBytes)] = struct{}{}
   297  
   298  			// Duplicates are cached and should return error
   299  			err = mempool.CheckTx(txBytes, nil, TxInfo{})
   300  			require.NotNil(t, err, "Expected error after CheckTx on duplicated tx")
   301  		}
   302  	}
   303  
   304  	reapCheck := func(exp int) {
   305  		txs := mempool.ReapMaxBytesMaxGas(-1, -1)
   306  		require.Equal(t, len(txs), exp, fmt.Sprintf("Expected to reap %v txs but got %v", exp, len(txs)))
   307  	}
   308  
   309  	updateRange := func(start, end int) {
   310  		txs := make([]types.Tx, 0)
   311  		for i := start; i < end; i++ {
   312  			txBytes := make([]byte, 8)
   313  			binary.BigEndian.PutUint64(txBytes, uint64(i))
   314  			txs = append(txs, txBytes)
   315  		}
   316  		if err := mempool.Update(0, txs, abciResponses(len(txs), abci.CodeTypeOK), nil, nil); err != nil {
   317  			t.Error(err)
   318  		}
   319  	}
   320  
   321  	commitRange := func(start, end int) {
   322  		// Deliver some txs.
   323  		for i := start; i < end; i++ {
   324  			txBytes := make([]byte, 8)
   325  			binary.BigEndian.PutUint64(txBytes, uint64(i))
   326  			res, err := appConnCon.DeliverTxSync(abci.RequestDeliverTx{Tx: txBytes})
   327  			if err != nil {
   328  				t.Errorf("client error committing tx: %v", err)
   329  			}
   330  			if res.IsErr() {
   331  				t.Errorf("error committing tx. Code:%v result:%X log:%v",
   332  					res.Code, res.Data, res.Log)
   333  			}
   334  		}
   335  		res, err := appConnCon.CommitSync(abci.RequestCommit{})
   336  		if err != nil {
   337  			t.Errorf("client error committing: %v", err)
   338  		}
   339  		if len(res.Data) != 8 {
   340  			t.Errorf("error committing. Hash:%X", res.Data)
   341  		}
   342  	}
   343  
   344  	//----------------------------------------
   345  
   346  	// Deliver some txs.
   347  	deliverTxsRange(0, 100)
   348  
   349  	// Reap the txs.
   350  	reapCheck(100)
   351  
   352  	// Reap again.  We should get the same amount
   353  	reapCheck(100)
   354  
   355  	// Deliver 0 to 999, we should reap 900 new txs
   356  	// because 100 were already counted.
   357  	deliverTxsRange(0, 1000)
   358  
   359  	// Reap the txs.
   360  	reapCheck(BlockMaxTxNum)
   361  
   362  	// Reap again.  We should get the same amount
   363  	reapCheck(BlockMaxTxNum)
   364  
   365  	// Commit from the conensus AppConn
   366  	commitRange(0, BlockMaxTxNum)
   367  	updateRange(0, BlockMaxTxNum)
   368  
   369  	// We should have 500 left.
   370  	reapCheck(BlockMaxTxNum)
   371  
   372  	// Deliver 100 invalid txs and 100 valid txs
   373  	deliverTxsRange(900, 1100)
   374  
   375  	// We should have 300 now.
   376  	reapCheck(BlockMaxTxNum)
   377  }
   378  
   379  // Size of the amino encoded TxMessage is the length of the
   380  // encoded byte array, plus 1 for the struct field, plus 4
   381  // for the amino prefix.
   382  func txMessageSize(tx types.Tx) int {
   383  	return amino.ByteSliceSize(tx) + 1 + 4
   384  }
   385  
   386  func TestMempoolMaxMsgSize(t *testing.T) {
   387  	app := kvstore.NewApplication()
   388  	cc := proxy.NewLocalClientCreator(app)
   389  	mempl, cleanup := newMempoolWithApp(cc)
   390  	defer cleanup()
   391  
   392  	maxTxSize := mempl.config.MaxTxBytes
   393  	maxMsgSize := calcMaxMsgSize(maxTxSize)
   394  
   395  	testCases := []struct {
   396  		len int
   397  		err bool
   398  	}{
   399  		// check small txs. no error
   400  		{10, false},
   401  		{1000, false},
   402  		{1000000, false},
   403  
   404  		// check around maxTxSize
   405  		// changes from no error to error
   406  		{maxTxSize - 2, false},
   407  		{maxTxSize - 1, false},
   408  		{maxTxSize, false},
   409  		{maxTxSize + 1, true},
   410  		{maxTxSize + 2, true},
   411  
   412  		// check around maxMsgSize. all error
   413  		{maxMsgSize - 1, true},
   414  		{maxMsgSize, true},
   415  		{maxMsgSize + 1, true},
   416  	}
   417  
   418  	for i, testCase := range testCases {
   419  		caseString := fmt.Sprintf("case %d, len %d", i, testCase.len)
   420  
   421  		tx := tmrand.Bytes(testCase.len)
   422  		err := mempl.CheckTx(tx, nil, TxInfo{})
   423  		msg := &TxMessage{tx, ""}
   424  		encoded := cdc.MustMarshalBinaryBare(msg)
   425  		require.Equal(t, len(encoded), txMessageSize(tx), caseString)
   426  		if !testCase.err {
   427  			require.True(t, len(encoded) <= maxMsgSize, caseString)
   428  			require.NoError(t, err, caseString)
   429  		} else {
   430  			require.True(t, len(encoded) > maxMsgSize, caseString)
   431  			require.Equal(t, err, ErrTxTooLarge{maxTxSize, testCase.len}, caseString)
   432  		}
   433  	}
   434  
   435  }
   436  
   437  func TestMempoolTxsBytes(t *testing.T) {
   438  	app := kvstore.NewApplication()
   439  	cc := proxy.NewLocalClientCreator(app)
   440  	config := cfg.ResetTestRoot("mempool_test")
   441  	config.Mempool.MaxTxsBytes = 10
   442  	mempool, cleanup := newMempoolWithAppAndConfig(cc, config)
   443  	defer cleanup()
   444  
   445  	// 1. zero by default
   446  	assert.EqualValues(t, 0, mempool.TxsBytes())
   447  
   448  	// 2. len(tx) after CheckTx
   449  	err := mempool.CheckTx([]byte{0x01}, nil, TxInfo{})
   450  	require.NoError(t, err)
   451  	assert.EqualValues(t, 1, mempool.TxsBytes())
   452  
   453  	// 3. zero again after tx is removed by Update
   454  	mempool.Update(1, []types.Tx{[]byte{0x01}}, abciResponses(1, abci.CodeTypeOK), nil, nil)
   455  	assert.EqualValues(t, 0, mempool.TxsBytes())
   456  
   457  	// 4. zero after Flush
   458  	err = mempool.CheckTx([]byte{0x02, 0x03}, nil, TxInfo{})
   459  	require.NoError(t, err)
   460  	assert.EqualValues(t, 2, mempool.TxsBytes())
   461  
   462  	mempool.Flush()
   463  	assert.EqualValues(t, 0, mempool.TxsBytes())
   464  
   465  	// 5. ErrMempoolIsFull is returned when/if MaxTxsBytes limit is reached.
   466  	err = mempool.CheckTx([]byte{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, nil, TxInfo{})
   467  	require.NoError(t, err)
   468  	err = mempool.CheckTx([]byte{0x05}, nil, TxInfo{})
   469  	if assert.Error(t, err) {
   470  		assert.IsType(t, ErrMempoolIsFull{}, err)
   471  	}
   472  
   473  	// 6. zero after tx is rechecked and removed due to not being valid anymore
   474  	app2 := counter.NewApplication(true)
   475  	cc = proxy.NewLocalClientCreator(app2)
   476  	mempool, cleanup = newMempoolWithApp(cc)
   477  	defer cleanup()
   478  
   479  	txBytes := make([]byte, 8)
   480  	binary.BigEndian.PutUint64(txBytes, uint64(0))
   481  
   482  	err = mempool.CheckTx(txBytes, nil, TxInfo{})
   483  	require.NoError(t, err)
   484  	assert.EqualValues(t, 8, mempool.TxsBytes())
   485  
   486  	appConnCon, _ := cc.NewABCIClient()
   487  	appConnCon.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "consensus"))
   488  	err = appConnCon.Start()
   489  	require.Nil(t, err)
   490  	defer appConnCon.Stop()
   491  	res, err := appConnCon.DeliverTxSync(abci.RequestDeliverTx{Tx: txBytes})
   492  	require.NoError(t, err)
   493  	require.EqualValues(t, 0, res.Code)
   494  	res2, err := appConnCon.CommitSync(abci.RequestCommit{})
   495  	require.NoError(t, err)
   496  	require.NotEmpty(t, res2.Data)
   497  	// Pretend like we committed nothing so txBytes gets rechecked and removed.
   498  	// our config recheck flag default is false so cannot rechecked to remove unavailable txs
   499  	// add config to check whether to assert mempool txsbytes
   500  	height := int64(1)
   501  	mempool.Update(height, []types.Tx{}, abciResponses(0, abci.CodeTypeOK), nil, nil)
   502  	if cfg.DynamicConfig.GetMempoolRecheck() || height%cfg.DynamicConfig.GetMempoolForceRecheckGap() == 0 {
   503  		assert.EqualValues(t, 0, mempool.TxsBytes())
   504  	} else {
   505  		assert.EqualValues(t, len(txBytes), mempool.TxsBytes())
   506  	}
   507  }
   508  
   509  func abciResponses(n int, code uint32) []*abci.ResponseDeliverTx {
   510  	responses := make([]*abci.ResponseDeliverTx, 0, n)
   511  	for i := 0; i < n; i++ {
   512  		responses = append(responses, &abci.ResponseDeliverTx{Code: code})
   513  	}
   514  	return responses
   515  }
   516  
   517  func TestAddAndSortTx(t *testing.T) {
   518  	app := kvstore.NewApplication()
   519  	cc := proxy.NewLocalClientCreator(app)
   520  	config := cfg.ResetTestRoot("mempool_test")
   521  	config.Mempool.SortTxByGp = true
   522  	mempool, cleanup := newMempoolWithAppAndConfig(cc, config)
   523  	defer cleanup()
   524  
   525  	//tx := &mempoolTx{height: 1, gasWanted: 1, tx:[]byte{0x01}}
   526  	testCases := []struct {
   527  		Tx *mempoolTx
   528  	}{
   529  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("1"), from: "18", realTx: abci.MockTx{GasPrice: big.NewInt(3780)}}},
   530  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("2"), from: "6", realTx: abci.MockTx{GasPrice: big.NewInt(5853)}}},
   531  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("3"), from: "7", realTx: abci.MockTx{GasPrice: big.NewInt(8315)}}},
   532  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("4"), from: "10", realTx: abci.MockTx{GasPrice: big.NewInt(9526)}}},
   533  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("5"), from: "15", realTx: abci.MockTx{GasPrice: big.NewInt(9140)}}},
   534  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("6"), from: "9", realTx: abci.MockTx{GasPrice: big.NewInt(9227)}}},
   535  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("7"), from: "3", realTx: abci.MockTx{GasPrice: big.NewInt(761)}}},
   536  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("8"), from: "18", realTx: abci.MockTx{GasPrice: big.NewInt(9740)}}},
   537  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("9"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(6574)}}},
   538  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("10"), from: "8", realTx: abci.MockTx{GasPrice: big.NewInt(9656)}}},
   539  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("11"), from: "12", realTx: abci.MockTx{GasPrice: big.NewInt(6554)}}},
   540  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("12"), from: "16", realTx: abci.MockTx{GasPrice: big.NewInt(5609)}}},
   541  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("13"), from: "6", realTx: abci.MockTx{GasPrice: big.NewInt(2791), Nonce: 1}}},
   542  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("14"), from: "18", realTx: abci.MockTx{GasPrice: big.NewInt(2698), Nonce: 1}}},
   543  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("15"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(6925), Nonce: 1}}},
   544  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("16"), from: "3", realTx: abci.MockTx{GasPrice: big.NewInt(3171)}}},
   545  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("17"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(2965), Nonce: 2}}},
   546  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("18"), from: "19", realTx: abci.MockTx{GasPrice: big.NewInt(2484)}}},
   547  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("19"), from: "13", realTx: abci.MockTx{GasPrice: big.NewInt(9722)}}},
   548  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("20"), from: "7", realTx: abci.MockTx{GasPrice: big.NewInt(4236), Nonce: 1}}},
   549  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("21"), from: "18", realTx: abci.MockTx{GasPrice: big.NewInt(1780)}}},
   550  	}
   551  
   552  	for _, exInfo := range testCases {
   553  		mempool.addTx(exInfo.Tx)
   554  	}
   555  	require.Equal(t, 18, mempool.txs.Len(), fmt.Sprintf("Expected to txs length %v but got %v", 18, mempool.txs.Len()))
   556  
   557  	// The txs in mempool should sorted, the output should be (head -> tail):
   558  	//
   559  	//Address:  18  , GasPrice:  9740  , Nonce:  0
   560  	//Address:  13  , GasPrice:  9722  , Nonce:  0
   561  	//Address:  8  , GasPrice:  9656  , Nonce:  0
   562  	//Address:  10  , GasPrice:  9526  , Nonce:  0
   563  	//Address:  9  , GasPrice:  9227  , Nonce:  0
   564  	//Address:  15  , GasPrice:  9140  , Nonce:  0
   565  	//Address:  7  , GasPrice:  8315  , Nonce:  0
   566  	//Address:  1  , GasPrice:  6574  , Nonce:  0
   567  	//Address:  1  , GasPrice:  6925  , Nonce:  1
   568  	//Address:  12  , GasPrice:  6554  , Nonce:  0
   569  	//Address:  6  , GasPrice:  5853  , Nonce:  0
   570  	//Address:  16  , GasPrice:  5609  , Nonce:  0
   571  	//Address:  7  , GasPrice:  4236  , Nonce:  1
   572  	//Address:  3  , GasPrice:  3171  , Nonce:  0
   573  	//Address:  1  , GasPrice:  2965  , Nonce:  2
   574  	//Address:  6  , GasPrice:  2791  , Nonce:  1
   575  	//Address:  18  , GasPrice:  2698  , Nonce:  1
   576  	//Address:  19  , GasPrice:  2484  , Nonce:  0
   577  
   578  	require.Equal(t, 3, mempool.GetUserPendingTxsCnt("1"))
   579  	require.Equal(t, 1, mempool.GetUserPendingTxsCnt("15"))
   580  	require.Equal(t, 2, mempool.GetUserPendingTxsCnt("18"))
   581  
   582  	require.Equal(t, "18", mempool.txs.Front().Address)
   583  	require.Equal(t, big.NewInt(9740), mempool.txs.Front().GasPrice)
   584  	require.Equal(t, uint64(0), mempool.txs.Front().Nonce)
   585  
   586  	require.Equal(t, "19", mempool.txs.Back().Address)
   587  	require.Equal(t, big.NewInt(2484), mempool.txs.Back().GasPrice)
   588  	require.Equal(t, uint64(0), mempool.txs.Back().Nonce)
   589  
   590  	require.Equal(t, true, checkTx(mempool.txs.Front()))
   591  
   592  	addressList := mempool.GetAddressList()
   593  	for _, addr := range addressList {
   594  		require.Equal(t, true, checkAccNonce(addr, mempool.txs.Front()))
   595  	}
   596  
   597  	txs := mempool.ReapMaxBytesMaxGas(-1, -1)
   598  	require.Equal(t, 18, len(txs), fmt.Sprintf("Expected to reap %v txs but got %v", 18, len(txs)))
   599  
   600  	mempool.Flush()
   601  	require.Equal(t, 0, mempool.txs.Len())
   602  	require.Equal(t, 0, mempool.txs.BroadcastLen())
   603  	require.Equal(t, 0, len(mempool.GetAddressList()))
   604  
   605  }
   606  
   607  func TestReplaceTx(t *testing.T) {
   608  	app := kvstore.NewApplication()
   609  	cc := proxy.NewLocalClientCreator(app)
   610  	config := cfg.ResetTestRoot("mempool_test")
   611  	mempool, cleanup := newMempoolWithAppAndConfig(cc, config)
   612  	defer cleanup()
   613  
   614  	//tx := &mempoolTx{height: 1, gasWanted: 1, tx:[]byte{0x01}}
   615  	testCases := []struct {
   616  		Tx *mempoolTx
   617  	}{
   618  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("10000"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(9740)}}},
   619  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("10001"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(5853), Nonce: 1}}},
   620  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("10002"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(8315), Nonce: 2}}},
   621  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("10003"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(9526), Nonce: 3}}},
   622  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("10004"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(9140), Nonce: 4}}},
   623  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("10002"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(9227), Nonce: 2}}},
   624  	}
   625  
   626  	for _, exInfo := range testCases {
   627  		mempool.addTx(exInfo.Tx)
   628  	}
   629  	require.Equal(t, 5, mempool.txs.Len(), fmt.Sprintf("Expected to txs length %v but got %v", 5, mempool.txs.Len()))
   630  
   631  	var nonces []uint64
   632  	var gasPrices []uint64
   633  	for e := mempool.txs.Front(); e != nil; e = e.Next() {
   634  		nonces = append(nonces, e.Nonce)
   635  		gasPrices = append(gasPrices, e.GasPrice.Uint64())
   636  	}
   637  
   638  	require.Equal(t, []uint64{0, 1, 2, 3, 4}, nonces)
   639  	require.Equal(t, []uint64{9740, 5853, 9227, 9526, 9140}, gasPrices)
   640  }
   641  
   642  func TestAddAndSortTxByRandom(t *testing.T) {
   643  	app := kvstore.NewApplication()
   644  	cc := proxy.NewLocalClientCreator(app)
   645  	config := cfg.ResetTestRoot("mempool_test")
   646  	mempool, cleanup := newMempoolWithAppAndConfig(cc, config)
   647  	defer cleanup()
   648  
   649  	AddrNonce := make(map[string]int)
   650  	for i := 0; i < 1000; i++ {
   651  		mempool.addTx(generateNode(AddrNonce, i))
   652  	}
   653  
   654  	require.Equal(t, true, checkTx(mempool.txs.Front()))
   655  	addressList := mempool.GetAddressList()
   656  	for _, addr := range addressList {
   657  		require.Equal(t, true, checkAccNonce(addr, mempool.txs.Front()))
   658  	}
   659  }
   660  
   661  func TestReapUserTxs(t *testing.T) {
   662  	app := kvstore.NewApplication()
   663  	cc := proxy.NewLocalClientCreator(app)
   664  	config := cfg.ResetTestRoot("mempool_test")
   665  	mempool, cleanup := newMempoolWithAppAndConfig(cc, config)
   666  	defer cleanup()
   667  
   668  	//tx := &mempoolTx{height: 1, gasWanted: 1, tx:[]byte{0x01}}
   669  	testCases := []struct {
   670  		Tx *mempoolTx
   671  	}{
   672  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("1"), from: "18", realTx: abci.MockTx{GasPrice: big.NewInt(9740)}}},
   673  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("2"), from: "6", realTx: abci.MockTx{GasPrice: big.NewInt(5853)}}},
   674  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("3"), from: "7", realTx: abci.MockTx{GasPrice: big.NewInt(8315)}}},
   675  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("4"), from: "10", realTx: abci.MockTx{GasPrice: big.NewInt(9526)}}},
   676  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("5"), from: "15", realTx: abci.MockTx{GasPrice: big.NewInt(9140)}}},
   677  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("6"), from: "9", realTx: abci.MockTx{GasPrice: big.NewInt(9227)}}},
   678  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("7"), from: "3", realTx: abci.MockTx{GasPrice: big.NewInt(761)}}},
   679  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("8"), from: "18", realTx: abci.MockTx{GasPrice: big.NewInt(3780)}}},
   680  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("9"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(6574)}}},
   681  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("10"), from: "8", realTx: abci.MockTx{GasPrice: big.NewInt(9656)}}},
   682  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("11"), from: "12", realTx: abci.MockTx{GasPrice: big.NewInt(6554)}}},
   683  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("12"), from: "16", realTx: abci.MockTx{GasPrice: big.NewInt(5609)}}},
   684  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("13"), from: "6", realTx: abci.MockTx{GasPrice: big.NewInt(2791), Nonce: 1}}},
   685  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("14"), from: "18", realTx: abci.MockTx{GasPrice: big.NewInt(2698), Nonce: 1}}},
   686  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("15"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(6925), Nonce: 1}}},
   687  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("16"), from: "3", realTx: abci.MockTx{GasPrice: big.NewInt(3171)}}},
   688  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("17"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(2965), Nonce: 2}}},
   689  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("18"), from: "19", realTx: abci.MockTx{GasPrice: big.NewInt(2484)}}},
   690  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("19"), from: "13", realTx: abci.MockTx{GasPrice: big.NewInt(9722)}}},
   691  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("20"), from: "7", realTx: abci.MockTx{GasPrice: big.NewInt(4236), Nonce: 1}}},
   692  	}
   693  
   694  	for _, exInfo := range testCases {
   695  		mempool.addTx(exInfo.Tx)
   696  	}
   697  	require.Equal(t, 18, mempool.txs.Len(), fmt.Sprintf("Expected to txs length %v but got %v", 18,
   698  		mempool.txs.Len()))
   699  
   700  	require.Equal(t, 3, mempool.ReapUserTxsCnt("1"), fmt.Sprintf("Expected to txs length of %s "+
   701  		"is %v but got %v", "1", 3, mempool.ReapUserTxsCnt("1")))
   702  
   703  	require.Equal(t, 0, mempool.ReapUserTxsCnt("111"), fmt.Sprintf("Expected to txs length of %s "+
   704  		"is %v but got %v", "111", 0, mempool.ReapUserTxsCnt("111")))
   705  
   706  	require.Equal(t, 3, len(mempool.ReapUserTxs("1", -1)), fmt.Sprintf("Expected to txs length "+
   707  		"of %s is %v but got %v", "1", 3, len(mempool.ReapUserTxs("1", -1))))
   708  
   709  	require.Equal(t, 3, len(mempool.ReapUserTxs("1", 100)), fmt.Sprintf("Expected to txs length "+
   710  		"of %s is %v but got %v", "1", 3, len(mempool.ReapUserTxs("1", 100))))
   711  
   712  	require.Equal(t, 0, len(mempool.ReapUserTxs("111", -1)), fmt.Sprintf("Expected to txs length "+
   713  		"of %s is %v but got %v", "111", 0, len(mempool.ReapUserTxs("111", -1))))
   714  
   715  	require.Equal(t, 0, len(mempool.ReapUserTxs("111", 100)), fmt.Sprintf("Expected to txs length "+
   716  		"of %s is %v but got %v", "111", 0, len(mempool.ReapUserTxs("111", 100))))
   717  }
   718  
   719  func generateNode(addrNonce map[string]int, idx int) *mempoolTx {
   720  	mrand.Seed(time.Now().UnixNano())
   721  	addr := strconv.Itoa(mrand.Int()%1000 + 1)
   722  	gasPrice := mrand.Int()%100000 + 1
   723  
   724  	nonce := 0
   725  	if n, ok := addrNonce[addr]; ok {
   726  		if gasPrice%177 == 0 {
   727  			nonce = n - 1
   728  		} else {
   729  			nonce = n
   730  		}
   731  	}
   732  	addrNonce[addr] = nonce + 1
   733  
   734  	tx := &mempoolTx{
   735  		height:    1,
   736  		gasWanted: int64(idx),
   737  		tx:        []byte(strconv.Itoa(idx)),
   738  		from:      addr,
   739  		realTx: abci.MockTx{
   740  			GasPrice: big.NewInt(int64(gasPrice)),
   741  			Nonce:    uint64(nonce),
   742  		},
   743  	}
   744  
   745  	return tx
   746  }
   747  
   748  func checkAccNonce(addr string, head *clist.CElement) bool {
   749  	nonce := uint64(0)
   750  
   751  	for head != nil {
   752  		if head.Address == addr {
   753  			if head.Nonce != nonce {
   754  				return false
   755  			}
   756  			nonce++
   757  		}
   758  
   759  		head = head.Next()
   760  	}
   761  
   762  	return true
   763  }
   764  
   765  func checkTx(head *clist.CElement) bool {
   766  	for head != nil {
   767  		next := head.Next()
   768  		if next == nil {
   769  			break
   770  		}
   771  
   772  		if head.Address == next.Address {
   773  			if head.Nonce >= next.Nonce {
   774  				return false
   775  			}
   776  		} else {
   777  			if head.GasPrice.Cmp(next.GasPrice) < 0 {
   778  				return false
   779  			}
   780  		}
   781  
   782  		head = head.Next()
   783  	}
   784  
   785  	return true
   786  }
   787  
   788  func TestMultiPriceBump(t *testing.T) {
   789  	tests := []struct {
   790  		rawPrice    *big.Int
   791  		priceBump   uint64
   792  		targetPrice *big.Int
   793  	}{
   794  		{big.NewInt(1), 0, big.NewInt(1)},
   795  		{big.NewInt(10), 1, big.NewInt(10)},
   796  		{big.NewInt(100), 0, big.NewInt(100)},
   797  		{big.NewInt(100), 5, big.NewInt(105)},
   798  		{big.NewInt(100), 50, big.NewInt(150)},
   799  		{big.NewInt(100), 150, big.NewInt(250)},
   800  	}
   801  	for _, tt := range tests {
   802  		require.True(t, tt.targetPrice.Cmp(MultiPriceBump(tt.rawPrice, int64(tt.priceBump))) == 0)
   803  	}
   804  }
   805  
   806  func TestAddAndSortTxConcurrency(t *testing.T) {
   807  	app := kvstore.NewApplication()
   808  	cc := proxy.NewLocalClientCreator(app)
   809  	config := cfg.ResetTestRoot("mempool_test")
   810  	config.Mempool.SortTxByGp = true
   811  	mempool, cleanup := newMempoolWithAppAndConfig(cc, config)
   812  	defer cleanup()
   813  
   814  	//tx := &mempoolTx{height: 1, gasWanted: 1, tx:[]byte{0x01}}
   815  	type Case struct {
   816  		Tx *mempoolTx
   817  	}
   818  
   819  	testCases := []Case{
   820  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("1"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(3780)}}},
   821  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("2"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(3780), Nonce: 1}}},
   822  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("3"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(5315), Nonce: 2}}},
   823  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("4"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(4526), Nonce: 3}}},
   824  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("5"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(2140), Nonce: 4}}},
   825  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("6"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(4227), Nonce: 5}}},
   826  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("7"), from: "2", realTx: abci.MockTx{GasPrice: big.NewInt(2161)}}},
   827  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("8"), from: "2", realTx: abci.MockTx{GasPrice: big.NewInt(5740), Nonce: 1}}},
   828  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("9"), from: "2", realTx: abci.MockTx{GasPrice: big.NewInt(6574), Nonce: 2}}},
   829  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("10"), from: "2", realTx: abci.MockTx{GasPrice: big.NewInt(9630), Nonce: 3}}},
   830  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("11"), from: "2", realTx: abci.MockTx{GasPrice: big.NewInt(6554), Nonce: 4}}},
   831  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("12"), from: "2", realTx: abci.MockTx{GasPrice: big.NewInt(5609), Nonce: 2}}},
   832  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("13"), from: "3", realTx: abci.MockTx{GasPrice: big.NewInt(2791)}}},
   833  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("14"), from: "3", realTx: abci.MockTx{GasPrice: big.NewInt(2698), Nonce: 1}}},
   834  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("15"), from: "2", realTx: abci.MockTx{GasPrice: big.NewInt(6925), Nonce: 3}}},
   835  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("16"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(4171), Nonce: 3}}},
   836  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("17"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(2965), Nonce: 2}}},
   837  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("18"), from: "3", realTx: abci.MockTx{GasPrice: big.NewInt(2484), Nonce: 2}}},
   838  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("19"), from: "3", realTx: abci.MockTx{GasPrice: big.NewInt(9722), Nonce: 1}}},
   839  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("20"), from: "2", realTx: abci.MockTx{GasPrice: big.NewInt(4236), Nonce: 3}}},
   840  		{&mempoolTx{height: 1, gasWanted: 1, tx: []byte("21"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(8780), Nonce: 4}}},
   841  	}
   842  
   843  	var wait sync.WaitGroup
   844  	for _, exInfo := range testCases {
   845  		wait.Add(1)
   846  		go func(p Case) {
   847  			mempool.addTx(p.Tx)
   848  			wait.Done()
   849  		}(exInfo)
   850  	}
   851  
   852  	wait.Wait()
   853  }
   854  
   855  func TestTxID(t *testing.T) {
   856  	var bytes = make([]byte, 256)
   857  	for i := 0; i < 10; i++ {
   858  		_, err := rand.Read(bytes)
   859  		require.NoError(t, err)
   860  		require.Equal(t, amino.HexEncodeToStringUpper(bytes), fmt.Sprintf("%X", bytes))
   861  	}
   862  }
   863  
   864  func BenchmarkTxID(b *testing.B) {
   865  	var bytes = make([]byte, 256)
   866  	_, _ = rand.Read(bytes)
   867  	var res string
   868  	b.Run("fmt", func(b *testing.B) {
   869  		b.ReportAllocs()
   870  		for i := 0; i < b.N; i++ {
   871  			res = fmt.Sprintf("%X", bytes)
   872  		}
   873  	})
   874  	b.Run("amino", func(b *testing.B) {
   875  		b.ReportAllocs()
   876  		for i := 0; i < b.N; i++ {
   877  			res = amino.HexEncodeToStringUpper(bytes)
   878  		}
   879  	})
   880  	_ = res
   881  }
   882  
   883  func TestReplaceTxWithMultiAddrs(t *testing.T) {
   884  	app := kvstore.NewApplication()
   885  	cc := proxy.NewLocalClientCreator(app)
   886  	config := cfg.ResetTestRoot("mempool_test")
   887  	mempool, cleanup := newMempoolWithAppAndConfig(cc, config)
   888  	defer cleanup()
   889  
   890  	tx1 := &mempoolTx{height: 1, gasWanted: 1, tx: []byte("10002"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(9740), Nonce: 1}}
   891  	mempool.addTx(tx1)
   892  	tx2 := &mempoolTx{height: 1, gasWanted: 1, tx: []byte("90000"), from: "2", realTx: abci.MockTx{GasPrice: big.NewInt(10717), Nonce: 1}}
   893  	mempool.addTx(tx2)
   894  	tx3 := &mempoolTx{height: 1, gasWanted: 1, tx: []byte("90000"), from: "3", realTx: abci.MockTx{GasPrice: big.NewInt(10715), Nonce: 1}}
   895  	mempool.addTx(tx3)
   896  	tx4 := &mempoolTx{height: 1, gasWanted: 1, tx: []byte("10001"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(10716), Nonce: 2}}
   897  	mempool.addTx(tx4)
   898  	tx5 := &mempoolTx{height: 1, gasWanted: 1, tx: []byte("10001"), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(10712), Nonce: 1}}
   899  	mempool.addTx(tx5)
   900  
   901  	var nonces []uint64
   902  	for e := mempool.txs.Front(); e != nil; e = e.Next() {
   903  		if e.Address == "1" {
   904  			nonces = append(nonces, e.Nonce)
   905  		}
   906  	}
   907  	require.Equal(t, []uint64{1, 2}, nonces)
   908  }
   909  
   910  func BenchmarkMempoolLogUpdate(b *testing.B) {
   911  	logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "benchmark")
   912  	var options []log.Option
   913  	options = append(options, log.AllowErrorWith("module", "benchmark"))
   914  	logger = log.NewFilter(logger, options...)
   915  
   916  	mem := &CListMempool{height: 123456, logger: logger}
   917  	addr := "address"
   918  	nonce := uint64(123456)
   919  
   920  	b.Run("pool", func(b *testing.B) {
   921  		b.ReportAllocs()
   922  		for i := 0; i < b.N; i++ {
   923  			mem.logUpdate(addr, nonce)
   924  		}
   925  	})
   926  
   927  	b.Run("logger", func(b *testing.B) {
   928  		b.ReportAllocs()
   929  		for i := 0; i < b.N; i++ {
   930  			mem.logger.Debug("mempool update", "address", addr, "nonce", nonce)
   931  		}
   932  	})
   933  }
   934  
   935  func BenchmarkMempoolLogAddTx(b *testing.B) {
   936  	logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "benchmark")
   937  	var options []log.Option
   938  	options = append(options, log.AllowErrorWith("module", "benchmark"))
   939  	logger = log.NewFilter(logger, options...)
   940  
   941  	mem := &CListMempool{height: 123456, logger: logger, txs: NewBaseTxQueue()}
   942  	tx := []byte("tx")
   943  
   944  	memTx := &mempoolTx{
   945  		height: mem.Height(),
   946  		tx:     tx,
   947  	}
   948  
   949  	r := &abci.Response_CheckTx{}
   950  
   951  	b.Run("pool", func(b *testing.B) {
   952  		b.ReportAllocs()
   953  		for i := 0; i < b.N; i++ {
   954  			mem.logAddTx(memTx, r)
   955  		}
   956  	})
   957  
   958  	b.Run("logger", func(b *testing.B) {
   959  		b.ReportAllocs()
   960  		for i := 0; i < b.N; i++ {
   961  			mem.logger.Info("Added good transaction",
   962  				"tx", txIDStringer{tx, mem.height},
   963  				"res", r,
   964  				"height", memTx.height,
   965  				"total", mem.Size(),
   966  			)
   967  		}
   968  	})
   969  }
   970  
   971  func TestTxOrTxHashToKey(t *testing.T) {
   972  	var tx = make([]byte, 256)
   973  	rand.Read(tx)
   974  
   975  	old := types.GetVenusHeight()
   976  
   977  	types.UnittestOnlySetMilestoneVenusHeight(1)
   978  
   979  	venus := types.GetVenusHeight()
   980  	txhash := types.Tx(tx).Hash(venus)
   981  
   982  	require.Equal(t, txKey(tx), txOrTxHashToKey(tx, nil, venus))
   983  	require.Equal(t, txKey(tx), txOrTxHashToKey(tx, txhash, venus))
   984  	require.Equal(t, txKey(tx), txOrTxHashToKey(tx, txhash, venus-1))
   985  	require.Equal(t, txKey(tx), txOrTxHashToKey(tx, types.Tx(tx).Hash(venus-1), venus-1))
   986  	require.NotEqual(t, txKey(tx), txOrTxHashToKey(tx, types.Tx(tx).Hash(venus-1), venus))
   987  
   988  	types.UnittestOnlySetMilestoneVenusHeight(old)
   989  }
   990  
   991  func TestCListMempool_GetEnableDeleteMinGPTx(t *testing.T) {
   992  
   993  	testCases := []struct {
   994  		name     string
   995  		prepare  func(mempool *CListMempool, tt *testing.T)
   996  		execFunc func(mempool *CListMempool, tt *testing.T)
   997  	}{
   998  		{
   999  			name: "normal mempool is full add tx failed, disableDeleteMinGPTx",
  1000  			prepare: func(mempool *CListMempool, tt *testing.T) {
  1001  				mempool.Flush()
  1002  				err := mempool.CheckTx([]byte{0x01}, nil, TxInfo{})
  1003  				require.NoError(tt, err)
  1004  			},
  1005  			execFunc: func(mempool *CListMempool, tt *testing.T) {
  1006  				err := mempool.CheckTx([]byte{0x02}, nil, TxInfo{})
  1007  				require.Error(tt, err)
  1008  				_, ok := err.(ErrMempoolIsFull)
  1009  				require.True(t, ok)
  1010  			},
  1011  		},
  1012  		{
  1013  			name: "normal mempool is full add tx failed, enableDeleteMinGPTx",
  1014  			prepare: func(mempool *CListMempool, tt *testing.T) {
  1015  				mempool.Flush()
  1016  				err := mempool.CheckTx([]byte{0x02}, nil, TxInfo{})
  1017  				require.NoError(tt, err)
  1018  				moc := cfg.MockDynamicConfig{}
  1019  				moc.SetEnableDeleteMinGPTx(true)
  1020  				cfg.SetDynamicConfig(moc)
  1021  			},
  1022  			execFunc: func(mempool *CListMempool, tt *testing.T) {
  1023  				err := mempool.CheckTx([]byte{0x03}, nil, TxInfo{})
  1024  				require.NoError(tt, err)
  1025  				require.Equal(tt, 1, mempool.Size())
  1026  				tx := mempool.txs.Back().Value.(*mempoolTx).tx
  1027  				require.Equal(tt, byte(0x02), tx[0])
  1028  			},
  1029  		},
  1030  	}
  1031  
  1032  	for _, tc := range testCases {
  1033  		t.Run(tc.name, func(tt *testing.T) {
  1034  			app := kvstore.NewApplication()
  1035  			cc := proxy.NewLocalClientCreator(app)
  1036  			mempool, cleanup := newMempoolWithApp(cc)
  1037  			mempool.config.MaxTxsBytes = 1 //  in unit test we only use tx bytes to  control mempool weather full
  1038  			defer cleanup()
  1039  
  1040  			tc.prepare(mempool, tt)
  1041  			tc.execFunc(mempool, tt)
  1042  		})
  1043  	}
  1044  
  1045  }
  1046  
  1047  func TestConsumePendingtxConcurrency(t *testing.T) {
  1048  
  1049  	app := kvstore.NewApplication()
  1050  	cc := proxy.NewLocalClientCreator(app)
  1051  	mem, cleanup := newMempoolWithApp(cc)
  1052  	defer cleanup()
  1053  	mem.pendingPool = newPendingPool(500000, 3, 10, 500000)
  1054  
  1055  	for i := 0; i < 10000; i++ {
  1056  		mem.pendingPool.addTx(&mempoolTx{height: 1, gasWanted: 1, tx: []byte(strconv.Itoa(i)), from: "1", realTx: abci.MockTx{GasPrice: big.NewInt(3780), Nonce: uint64(i)}})
  1057  	}
  1058  	wg := &sync.WaitGroup{}
  1059  	wg.Add(1)
  1060  	startWg := &sync.WaitGroup{}
  1061  	startWg.Add(1)
  1062  	go func() {
  1063  		startWg.Wait()
  1064  		mem.consumePendingTx("1", 0)
  1065  		wg.Done()
  1066  	}()
  1067  	startWg.Done()
  1068  	mem.consumePendingTx("1", 5000)
  1069  	wg.Wait()
  1070  	require.Equal(t, 0, mem.pendingPool.Size())
  1071  }
  1072  
  1073  func TestCheckAndGetWrapCMTx(t *testing.T) {
  1074  	wCMTx := &types.WrapCMTx{Tx: []byte("123456"), Nonce: 2}
  1075  	wdata, err := cdc.MarshalJSON(wCMTx)
  1076  	assert.NoError(t, err)
  1077  
  1078  	testcase := []struct {
  1079  		tx     types.Tx
  1080  		txInfo TxInfo
  1081  		res    *types.WrapCMTx
  1082  	}{
  1083  		{
  1084  			tx:     []byte("123"),
  1085  			txInfo: TxInfo{wrapCMTx: &types.WrapCMTx{Tx: []byte("123"), Nonce: 1}},
  1086  			res:    &types.WrapCMTx{Tx: []byte("123"), Nonce: 1},
  1087  		},
  1088  		{
  1089  			tx:     []byte("123"),
  1090  			txInfo: TxInfo{},
  1091  			res:    nil,
  1092  		},
  1093  		{
  1094  			tx:     wdata,
  1095  			txInfo: TxInfo{},
  1096  			res:    wCMTx,
  1097  		},
  1098  	}
  1099  
  1100  	clistMem := &CListMempool{}
  1101  	for _, tc := range testcase {
  1102  		re := clistMem.CheckAndGetWrapCMTx(tc.tx, tc.txInfo)
  1103  		if re != nil {
  1104  			assert.Equal(t, *re, *tc.res)
  1105  		} else {
  1106  			assert.Equal(t, re, tc.res)
  1107  		}
  1108  	}
  1109  }