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