github.com/klaytn/klaytn@v1.12.1/node/cn/gasprice/gasprice_test.go (about)

     1  // Copyright 2019 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package gasprice
    18  
    19  import (
    20  	"context"
    21  	"math/big"
    22  	"testing"
    23  
    24  	"github.com/klaytn/klaytn/blockchain"
    25  	"github.com/klaytn/klaytn/blockchain/types"
    26  	"github.com/klaytn/klaytn/blockchain/vm"
    27  	"github.com/klaytn/klaytn/common"
    28  	"github.com/klaytn/klaytn/common/math"
    29  	"github.com/klaytn/klaytn/consensus/gxhash"
    30  	"github.com/klaytn/klaytn/crypto"
    31  	"github.com/klaytn/klaytn/networks/rpc"
    32  	"github.com/klaytn/klaytn/params"
    33  	"github.com/klaytn/klaytn/storage/database"
    34  
    35  	"github.com/golang/mock/gomock"
    36  	mock_api "github.com/klaytn/klaytn/api/mocks"
    37  	"github.com/stretchr/testify/assert"
    38  )
    39  
    40  const testHead = 32
    41  
    42  type testBackend struct {
    43  	chain *blockchain.BlockChain
    44  }
    45  
    46  func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
    47  	if number > testHead {
    48  		return nil, nil
    49  	}
    50  	if number == rpc.LatestBlockNumber {
    51  		number = testHead
    52  	}
    53  	return b.chain.GetHeaderByNumber(uint64(number)), nil
    54  }
    55  
    56  func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
    57  	if number > testHead {
    58  		return nil, nil
    59  	}
    60  	if number == rpc.LatestBlockNumber {
    61  		number = testHead
    62  	}
    63  	return b.chain.GetBlockByNumber(uint64(number)), nil
    64  }
    65  
    66  func (b *testBackend) GetBlockReceipts(ctx context.Context, hash common.Hash) types.Receipts {
    67  	return b.chain.GetReceiptsByBlockHash(hash)
    68  }
    69  
    70  func (b *testBackend) ChainConfig() *params.ChainConfig {
    71  	return b.chain.Config()
    72  }
    73  
    74  func (b *testBackend) CurrentBlock() *types.Block {
    75  	return b.chain.CurrentBlock()
    76  }
    77  
    78  func newTestBackend(t *testing.T) *testBackend {
    79  	var (
    80  		key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    81  		addr   = crypto.PubkeyToAddress(key.PublicKey)
    82  
    83  		gspec = &blockchain.Genesis{
    84  			Config: params.TestChainConfig,
    85  			Alloc:  blockchain.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
    86  		}
    87  		db      = database.NewMemoryDBManager()
    88  		genesis = gspec.MustCommit(db)
    89  	)
    90  	// Generate testing blocks
    91  	blocks, _ := blockchain.GenerateChain(gspec.Config, genesis, gxhash.NewFaker(), db, testHead+1, func(i int, b *blockchain.BlockGen) {
    92  		b.SetRewardbase(addr)
    93  
    94  		toaddr := common.Address{}
    95  		data := make([]byte, 1)
    96  		gas, _ := types.IntrinsicGas(data, nil, false, params.TestChainConfig.Rules(big.NewInt(0)))
    97  		signer := types.NewEIP155Signer(params.TestChainConfig.ChainID)
    98  		tx, _ := types.SignTx(types.NewTransaction(b.TxNonce(addr), toaddr, big.NewInt(1), gas, nil, data), signer, key)
    99  		b.AddTx(tx)
   100  	})
   101  	// Construct testing chain
   102  	chain, err := blockchain.NewBlockChain(db, nil, gspec.Config, gxhash.NewFaker(), vm.Config{})
   103  	if err != nil {
   104  		t.Fatalf("Failed to create local chain, %v", err)
   105  	}
   106  	chain.InsertChain(blocks)
   107  	return &testBackend{chain: chain}
   108  }
   109  
   110  func TestGasPrice_NewOracle(t *testing.T) {
   111  	mockCtrl := gomock.NewController(t)
   112  	defer mockCtrl.Finish()
   113  	mockBackend := mock_api.NewMockBackend(mockCtrl)
   114  	params := Config{}
   115  	oracle := NewOracle(mockBackend, params, nil)
   116  
   117  	assert.Nil(t, oracle.lastPrice)
   118  	assert.Equal(t, 1, oracle.checkBlocks)
   119  	assert.Equal(t, 0, oracle.maxEmpty)
   120  	assert.Equal(t, 5, oracle.maxBlocks)
   121  	assert.Equal(t, 0, oracle.percentile)
   122  
   123  	params = Config{Blocks: 2}
   124  	oracle = NewOracle(mockBackend, params, nil)
   125  
   126  	assert.Nil(t, oracle.lastPrice)
   127  	assert.Equal(t, 2, oracle.checkBlocks)
   128  	assert.Equal(t, 1, oracle.maxEmpty)
   129  	assert.Equal(t, 10, oracle.maxBlocks)
   130  	assert.Equal(t, 0, oracle.percentile)
   131  
   132  	params = Config{Percentile: -1}
   133  	oracle = NewOracle(mockBackend, params, nil)
   134  
   135  	assert.Nil(t, oracle.lastPrice)
   136  	assert.Equal(t, 1, oracle.checkBlocks)
   137  	assert.Equal(t, 0, oracle.maxEmpty)
   138  	assert.Equal(t, 5, oracle.maxBlocks)
   139  	assert.Equal(t, 0, oracle.percentile)
   140  
   141  	params = Config{Percentile: 101}
   142  	oracle = NewOracle(mockBackend, params, nil)
   143  
   144  	assert.Nil(t, oracle.lastPrice)
   145  	assert.Equal(t, 1, oracle.checkBlocks)
   146  	assert.Equal(t, 0, oracle.maxEmpty)
   147  	assert.Equal(t, 5, oracle.maxBlocks)
   148  	assert.Equal(t, 100, oracle.percentile)
   149  
   150  	params = Config{Percentile: 101, Default: big.NewInt(123)}
   151  	oracle = NewOracle(mockBackend, params, nil)
   152  
   153  	assert.Equal(t, big.NewInt(123), oracle.lastPrice)
   154  	assert.Equal(t, 1, oracle.checkBlocks)
   155  	assert.Equal(t, 0, oracle.maxEmpty)
   156  	assert.Equal(t, 5, oracle.maxBlocks)
   157  	assert.Equal(t, 100, oracle.percentile)
   158  }
   159  
   160  func TestGasPrice_SuggestPrice(t *testing.T) {
   161  	mockCtrl := gomock.NewController(t)
   162  	defer mockCtrl.Finish()
   163  	mockBackend := mock_api.NewMockBackend(mockCtrl)
   164  	params := Config{}
   165  	testBackend := newTestBackend(t)
   166  	chainConfig := testBackend.ChainConfig()
   167  	chainConfig.UnitPrice = 0
   168  	txPoolWith0 := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, chainConfig, testBackend.chain)
   169  	oracle := NewOracle(mockBackend, params, txPoolWith0)
   170  
   171  	currentBlock := testBackend.CurrentBlock()
   172  	mockBackend.EXPECT().ChainConfig().Return(chainConfig).Times(2)
   173  	mockBackend.EXPECT().CurrentBlock().Return(currentBlock).Times(2)
   174  
   175  	price, err := oracle.SuggestPrice(nil)
   176  	assert.Equal(t, price, common.Big0)
   177  	assert.Nil(t, err)
   178  
   179  	params = Config{Default: big.NewInt(123)}
   180  	chainConfig.UnitPrice = 25
   181  	txPoolWith25 := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, chainConfig, testBackend.chain)
   182  	oracle = NewOracle(mockBackend, params, txPoolWith25)
   183  
   184  	price, err = oracle.SuggestPrice(nil)
   185  	assert.Equal(t, big.NewInt(25), price)
   186  	assert.Nil(t, err)
   187  }