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

     1  package mempool
     2  
     3  import (
     4  	"math/big"
     5  	"testing"
     6  
     7  	"github.com/ethereum/go-ethereum/params"
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/okex/exchain/libs/tendermint/abci/example/kvstore"
    11  	cfg "github.com/okex/exchain/libs/tendermint/config"
    12  	"github.com/okex/exchain/libs/tendermint/proxy"
    13  	"github.com/okex/exchain/libs/tendermint/types"
    14  )
    15  
    16  // tx for recommended gas price test
    17  type RGPTX struct {
    18  	GU uint64
    19  	GP *big.Int
    20  }
    21  
    22  func NewRGPTX(gu uint64, gp *big.Int) RGPTX {
    23  	return RGPTX{
    24  		GU: gu,
    25  		GP: gp,
    26  	}
    27  }
    28  
    29  func TestCListMempool_RecommendGP(t *testing.T) {
    30  	testCases := []struct {
    31  		title               string
    32  		curBlockRGP         *big.Int
    33  		isCurBlockCongested bool
    34  
    35  		gpMaxTxNum   int64
    36  		gpMaxGasUsed int64
    37  		gpMode       int
    38  
    39  		prepare func(int, int64, int64)
    40  		// build txs for one block
    41  		buildTxs func(int, int64, *int64, bool, bool) []RGPTX
    42  
    43  		expectedTotalGU     []uint64
    44  		expectedRecommendGp []string
    45  		blocks              int
    46  
    47  		needMultiple bool
    48  		gpDecrease   bool
    49  		tpb          []int
    50  	}{
    51  		{
    52  			title:               "5/5 empty block, higher gp mode",
    53  			curBlockRGP:         big.NewInt(0),
    54  			gpMaxTxNum:          300,
    55  			gpMaxGasUsed:        40000000,
    56  			gpMode:              types.CongestionHigherGpMode,
    57  			prepare:             setMocConfig,
    58  			buildTxs:            generateTxs,
    59  			expectedTotalGU:     []uint64{0, 0, 0, 0, 0},
    60  			expectedRecommendGp: []string{"100000000", "100000000", "100000000", "100000000", "100000000"},
    61  			blocks:              5,
    62  			needMultiple:        false,
    63  			gpDecrease:          false,
    64  			tpb:                 []int{0, 0, 0, 0, 0},
    65  		},
    66  		{
    67  			title:               "4/6 empty block, higher gp mode",
    68  			curBlockRGP:         big.NewInt(0),
    69  			gpMaxTxNum:          300,
    70  			gpMaxGasUsed:        40000000,
    71  			gpMode:              types.CongestionHigherGpMode,
    72  			prepare:             setMocConfig,
    73  			buildTxs:            generateTxs,
    74  			expectedTotalGU:     []uint64{46329800, 0, 0, 0, 0, 46329800},
    75  			expectedRecommendGp: []string{"100200099", "100000000", "100000000", "100000000", "100000000", "100200099"},
    76  			blocks:              6,
    77  			needMultiple:        false,
    78  			gpDecrease:          false,
    79  			tpb:                 []int{200, 0, 0, 0, 0, 200},
    80  		},
    81  
    82  		{
    83  			title:               "4/6 uncongested block, higher gp mode",
    84  			curBlockRGP:         big.NewInt(0),
    85  			gpMaxTxNum:          300,
    86  			gpMaxGasUsed:        40000000,
    87  			gpMode:              types.CongestionHigherGpMode,
    88  			prepare:             setMocConfig,
    89  			buildTxs:            generateTxs,
    90  			expectedTotalGU:     []uint64{46329800, 23164900, 23164900, 23164900, 23164900, 46329800},
    91  			expectedRecommendGp: []string{"100200099", "100000000", "100000000", "100000000", "100000000", "100200500"},
    92  			blocks:              6,
    93  			needMultiple:        false,
    94  			gpDecrease:          false,
    95  			tpb:                 []int{200, 100, 100, 100, 100, 200},
    96  		},
    97  		{
    98  			title:               "0/5 empty block, higher gp mode",
    99  			curBlockRGP:         big.NewInt(0),
   100  			gpMaxTxNum:          300,
   101  			gpMaxGasUsed:        40000000,
   102  			gpMode:              types.CongestionHigherGpMode,
   103  			prepare:             setMocConfig,
   104  			buildTxs:            generateTxs,
   105  			expectedTotalGU:     []uint64{46329800, 46329800, 46329800, 46329800, 46329800},
   106  			expectedRecommendGp: []string{"100200099", "100200099", "100200299", "100200499", "100200699"},
   107  			blocks:              5,
   108  			needMultiple:        false,
   109  			gpDecrease:          false,
   110  			tpb:                 []int{200, 200, 200, 200, 200},
   111  		},
   112  		{
   113  			title:               "2/5 empty block, higher gp mode",
   114  			curBlockRGP:         big.NewInt(0),
   115  			gpMaxTxNum:          300,
   116  			gpMaxGasUsed:        40000000,
   117  			gpMode:              types.CongestionHigherGpMode,
   118  			prepare:             setMocConfig,
   119  			buildTxs:            generateTxs,
   120  			expectedTotalGU:     []uint64{46329800, 0, 46329800, 0, 46329800},
   121  			expectedRecommendGp: []string{"100200099", "100000000", "100200099", "100000000", "100200299"},
   122  			blocks:              5,
   123  			needMultiple:        false,
   124  			gpDecrease:          false,
   125  			tpb:                 []int{200, 0, 200, 0, 200},
   126  		},
   127  		{
   128  			title:               "2/5 empty block, uncongestion, higher gp mode",
   129  			curBlockRGP:         big.NewInt(0),
   130  			gpMaxTxNum:          300,
   131  			gpMaxGasUsed:        60000000,
   132  			gpMode:              types.CongestionHigherGpMode,
   133  			prepare:             setMocConfig,
   134  			buildTxs:            generateTxs,
   135  			expectedTotalGU:     []uint64{46329800, 0, 46329800, 0, 46329800},
   136  			expectedRecommendGp: []string{"100000000", "100000000", "100000000", "100000000", "100000000"},
   137  			blocks:              5,
   138  			needMultiple:        false,
   139  			gpDecrease:          false,
   140  			tpb:                 []int{200, 0, 200, 0, 200},
   141  		},
   142  		{
   143  			title:               "0/5 empty block, minimal gp mode",
   144  			curBlockRGP:         big.NewInt(0),
   145  			gpMaxTxNum:          300,
   146  			gpMaxGasUsed:        40000000,
   147  			gpMode:              types.MinimalGpMode,
   148  			prepare:             setMocConfig,
   149  			buildTxs:            generateTxs,
   150  			expectedTotalGU:     []uint64{46329800, 46329800, 46329800, 46329800, 46329800},
   151  			expectedRecommendGp: []string{"0", "0", "0", "0", "0"},
   152  			blocks:              5,
   153  			needMultiple:        false,
   154  			gpDecrease:          false,
   155  			tpb:                 []int{200, 200, 200, 200, 200},
   156  		},
   157  		{
   158  			title:               "0/5 empty block, gp decrease, normal gp mode",
   159  			curBlockRGP:         big.NewInt(0),
   160  			gpMaxTxNum:          300,
   161  			gpMaxGasUsed:        40000000,
   162  			gpMode:              types.NormalGpMode,
   163  			prepare:             setMocConfig,
   164  			buildTxs:            generateTxs,
   165  			expectedTotalGU:     []uint64{46329800, 46329800, 46329800, 46329800, 46329800},
   166  			expectedRecommendGp: []string{"100199802", "100199802", "100199801", "100199603", "100199603"},
   167  			blocks:              5,
   168  			needMultiple:        false,
   169  			gpDecrease:          true,
   170  			tpb:                 []int{200, 200, 200, 200, 200},
   171  		},
   172  		{
   173  			title:               "0/5 empty block, gp decrease, higher gp mode",
   174  			curBlockRGP:         big.NewInt(0),
   175  			gpMaxTxNum:          300,
   176  			gpMaxGasUsed:        40000000,
   177  			gpMode:              types.CongestionHigherGpMode,
   178  			prepare:             setMocConfig,
   179  			buildTxs:            generateTxs,
   180  			expectedTotalGU:     []uint64{46329800, 46329800, 46329800, 46329800, 46329800},
   181  			expectedRecommendGp: []string{"100199900", "100199700", "100199700", "100199700", "100199700"},
   182  			blocks:              5,
   183  			needMultiple:        false,
   184  			gpDecrease:          true,
   185  			tpb:                 []int{200, 200, 200, 200, 200},
   186  		},
   187  		{
   188  			title:               "0/5 empty block, normal mode",
   189  			curBlockRGP:         big.NewInt(0),
   190  			gpMaxTxNum:          300,
   191  			gpMaxGasUsed:        40000000,
   192  			gpMode:              types.NormalGpMode,
   193  			prepare:             setMocConfig,
   194  			buildTxs:            generateTxs,
   195  			expectedTotalGU:     []uint64{46329800, 46329800, 46329800, 46329800, 46329800},
   196  			expectedRecommendGp: []string{"100200001", "100200201", "100200400", "100200402", "100200602"},
   197  			blocks:              5,
   198  			needMultiple:        false,
   199  			gpDecrease:          false,
   200  			tpb:                 []int{200, 200, 200, 200, 200},
   201  		},
   202  		{
   203  			title:               "0/5 empty block, uncongestion, higher gp mode",
   204  			curBlockRGP:         big.NewInt(0),
   205  			gpMaxTxNum:          300,
   206  			gpMaxGasUsed:        60000000,
   207  			gpMode:              types.CongestionHigherGpMode,
   208  			prepare:             setMocConfig,
   209  			buildTxs:            generateTxs,
   210  			expectedTotalGU:     []uint64{46329800, 46329800, 46329800, 46329800, 46329800},
   211  			expectedRecommendGp: []string{"100000000", "100000000", "100000000", "100000000", "100000000"},
   212  			blocks:              5,
   213  			needMultiple:        false,
   214  			gpDecrease:          false,
   215  			tpb:                 []int{200, 200, 200, 200, 200},
   216  		},
   217  		{
   218  			title:               "0/5 empty block, uncongestion, gp multiple, higher gp mode",
   219  			curBlockRGP:         big.NewInt(0),
   220  			gpMaxTxNum:          300,
   221  			gpMaxGasUsed:        60000000,
   222  			gpMode:              types.CongestionHigherGpMode,
   223  			prepare:             setMocConfig,
   224  			buildTxs:            generateTxs,
   225  			expectedTotalGU:     []uint64{46329800, 46329800, 46329800, 46329800, 46329800},
   226  			expectedRecommendGp: []string{"100000000", "100000000", "100000000", "100000000", "100000000"},
   227  			blocks:              5,
   228  			needMultiple:        true,
   229  			gpDecrease:          false,
   230  			tpb:                 []int{200, 200, 200, 200, 200},
   231  		},
   232  		{
   233  			title:               "0/5 empty block, congestion, gp multiple, higher gp mode",
   234  			curBlockRGP:         big.NewInt(0),
   235  			gpMaxTxNum:          300,
   236  			gpMaxGasUsed:        40000000,
   237  			gpMode:              types.CongestionHigherGpMode,
   238  			prepare:             setMocConfig,
   239  			buildTxs:            generateTxs,
   240  			expectedTotalGU:     []uint64{46329800, 46329800, 46329800, 46329800, 46329800},
   241  			expectedRecommendGp: []string{"5060109900", "5060109900", "5060120000", "5060130100", "5060140200"},
   242  			blocks:              5,
   243  			needMultiple:        true,
   244  			gpDecrease:          false,
   245  			tpb:                 []int{200, 200, 200, 200, 200},
   246  		},
   247  		{
   248  			title:               "0/5 empty block, congestion, gp decrease, gp multiple, higher gp mode",
   249  			curBlockRGP:         big.NewInt(0),
   250  			gpMaxTxNum:          300,
   251  			gpMaxGasUsed:        40000000,
   252  			gpMode:              types.CongestionHigherGpMode,
   253  			prepare:             setMocConfig,
   254  			buildTxs:            generateTxs,
   255  			expectedTotalGU:     []uint64{46329800, 46329800, 46329800, 46329800, 46329800},
   256  			expectedRecommendGp: []string{"5060094901", "5060084801", "5060084801", "5060084801", "5060084801"},
   257  			blocks:              5,
   258  			needMultiple:        true,
   259  			gpDecrease:          true,
   260  			tpb:                 []int{200, 200, 200, 200, 200},
   261  		},
   262  		{
   263  			title:               "0/5 empty block, congestion, gp multiple, normal mode",
   264  			curBlockRGP:         big.NewInt(0),
   265  			gpMaxTxNum:          300,
   266  			gpMaxGasUsed:        40000000,
   267  			gpMode:              types.NormalGpMode,
   268  			prepare:             setMocConfig,
   269  			buildTxs:            generateTxs,
   270  			expectedTotalGU:     []uint64{46329800, 46329800, 46329800, 46329800, 46329800},
   271  			expectedRecommendGp: []string{"100200001", "100200201", "100200400", "100200402", "100200602"},
   272  			blocks:              5,
   273  			needMultiple:        true,
   274  			gpDecrease:          false,
   275  			tpb:                 []int{200, 200, 200, 200, 200},
   276  		},
   277  	}
   278  
   279  	for _, tc := range testCases {
   280  		t.Run(tc.title, func(tt *testing.T) {
   281  			// init mempool
   282  			app := kvstore.NewApplication()
   283  			cc := proxy.NewLocalClientCreator(app)
   284  			mempool, cleanup := newMempoolWithApp(cc)
   285  			defer cleanup()
   286  
   287  			tc.prepare(tc.gpMode, tc.gpMaxTxNum, tc.gpMaxGasUsed)
   288  			gpOffset := int64(200000)
   289  			baseGP := int64(params.GWei / 10)
   290  
   291  			for i := 0; i < tc.blocks; i++ {
   292  				totalGasUsed := uint64(0)
   293  				txs := tc.buildTxs(tc.tpb[i], baseGP, &gpOffset, tc.gpDecrease, tc.needMultiple)
   294  				for _, tx := range txs {
   295  					if cfg.DynamicConfig.GetDynamicGpMode() != types.MinimalGpMode {
   296  						mempool.gpo.CurrentBlockGPs.Update(tx.GP, tx.GU)
   297  					}
   298  					totalGasUsed += tx.GU
   299  				}
   300  				require.True(tt, totalGasUsed == tc.expectedTotalGU[i], "block gas expect %d, but get %d ", tc.expectedTotalGU[i], totalGasUsed)
   301  				if cfg.DynamicConfig.GetDynamicGpMode() != types.MinimalGpMode {
   302  					// calculate recommended GP
   303  					currentBlockGPsCopy := mempool.gpo.CurrentBlockGPs.Copy()
   304  					err := mempool.gpo.BlockGPQueue.Push(currentBlockGPsCopy)
   305  					require.Nil(tt, err)
   306  					tc.curBlockRGP, tc.isCurBlockCongested = mempool.gpo.RecommendGP()
   307  					tc.curBlockRGP = postProcessGP(tc.curBlockRGP, tc.isCurBlockCongested)
   308  					mempool.gpo.CurrentBlockGPs.Clear()
   309  				}
   310  				//fmt.Println("current recommended GP: ", tc.curBlockRGP)
   311  				require.True(tt, tc.expectedRecommendGp[i] == tc.curBlockRGP.String(), "recommend gas price expect %s, but get %s ", tc.expectedRecommendGp[i], tc.curBlockRGP.String())
   312  			}
   313  		})
   314  	}
   315  }
   316  
   317  func generateTxs(totalTxNum int, baseGP int64, gpOffset *int64, needDecreaseGP bool, needMultiple bool) []RGPTX {
   318  	// guPerTx is gas used of evm contract - Owner.sol
   319  	// bytecode := ethcommon.FromHex("0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36102c4806100dc6000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c010000000000000000000000000000000000000000000000000000000090048063893d20e814610058578063a6f9dae1146100a2575b600080fd5b6100606100e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e4600480360360208110156100b857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061010f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea265627a7a72315820f397f2733a89198bc7fed0764083694c5b828791f39ebcbc9e414bccef14b48064736f6c63430005100032")
   320  	guPerTx := uint64(231649)
   321  	txs := make([]RGPTX, 0)
   322  	for txCount := 0; txCount < totalTxNum/2; txCount++ {
   323  		curTxGp := baseGP + *gpOffset
   324  		if !needDecreaseGP {
   325  			*gpOffset++
   326  		} else {
   327  			*gpOffset--
   328  		}
   329  		tx := NewRGPTX(guPerTx, big.NewInt(curTxGp))
   330  		txs = append(txs, tx)
   331  	}
   332  
   333  	multiple := int64(1)
   334  	if needMultiple {
   335  		multiple = 100
   336  	}
   337  	for txCount := totalTxNum / 2; txCount < totalTxNum; txCount++ {
   338  		curTxGp := (baseGP + *gpOffset) * multiple
   339  		if !needDecreaseGP {
   340  			*gpOffset++
   341  		} else {
   342  			*gpOffset--
   343  		}
   344  		tx := NewRGPTX(guPerTx, big.NewInt(curTxGp))
   345  
   346  		txs = append(txs, tx)
   347  	}
   348  	return txs
   349  }
   350  
   351  func setMocConfig(gpMode int, gpMaxTxNum int64, gpMaxGasUsed int64) {
   352  	moc := cfg.MockDynamicConfig{}
   353  	moc.SetDynamicGpMode(gpMode)
   354  	moc.SetDynamicGpMaxTxNum(gpMaxTxNum)
   355  	moc.SetDynamicGpMaxGasUsed(gpMaxGasUsed)
   356  
   357  	cfg.SetDynamicConfig(moc)
   358  }
   359  
   360  func postProcessGP(recommendedGP *big.Int, isCongested bool) *big.Int {
   361  	// minGP for test is 0.1GWei
   362  	minGP := big.NewInt(100000000)
   363  	maxGP := new(big.Int).Mul(minGP, big.NewInt(5000))
   364  
   365  	rgp := new(big.Int).Set(minGP)
   366  	if cfg.DynamicConfig.GetDynamicGpMode() != types.MinimalGpMode {
   367  		// If current block is not congested, rgp == minimal gas price.
   368  		if isCongested {
   369  			rgp.Set(recommendedGP)
   370  		}
   371  
   372  		if rgp.Cmp(minGP) == -1 {
   373  			rgp.Set(minGP)
   374  		}
   375  
   376  		if rgp.Cmp(maxGP) == 1 {
   377  			rgp.Set(maxGP)
   378  		}
   379  	}
   380  	return rgp
   381  }