github.com/klaytn/klaytn@v1.12.1/node/cn/api_backend_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 cn
    18  
    19  import (
    20  	"encoding/json"
    21  	"math/big"
    22  	"testing"
    23  
    24  	"github.com/golang/mock/gomock"
    25  	"github.com/klaytn/klaytn/blockchain"
    26  	"github.com/klaytn/klaytn/blockchain/state"
    27  	"github.com/klaytn/klaytn/blockchain/types"
    28  	"github.com/klaytn/klaytn/blockchain/vm"
    29  	"github.com/klaytn/klaytn/common"
    30  	"github.com/klaytn/klaytn/common/hexutil"
    31  	"github.com/klaytn/klaytn/consensus"
    32  	"github.com/klaytn/klaytn/consensus/gxhash"
    33  	"github.com/klaytn/klaytn/consensus/istanbul/backend"
    34  	mocks3 "github.com/klaytn/klaytn/event/mocks"
    35  	"github.com/klaytn/klaytn/governance"
    36  	"github.com/klaytn/klaytn/networks/rpc"
    37  	mocks2 "github.com/klaytn/klaytn/node/cn/mocks"
    38  	"github.com/klaytn/klaytn/params"
    39  	"github.com/klaytn/klaytn/reward"
    40  	"github.com/klaytn/klaytn/storage/database"
    41  	"github.com/klaytn/klaytn/work/mocks"
    42  	"github.com/stretchr/testify/assert"
    43  	"golang.org/x/net/context"
    44  )
    45  
    46  func newCNAPIBackend(t *testing.T) (*gomock.Controller, *mocks.MockBlockChain, *mocks2.MockMiner, *CNAPIBackend) {
    47  	mockCtrl := gomock.NewController(t)
    48  
    49  	mockBlockChain := mocks.NewMockBlockChain(mockCtrl)
    50  	mockMiner := mocks2.NewMockMiner(mockCtrl)
    51  
    52  	cn := &CN{blockchain: mockBlockChain, miner: mockMiner}
    53  
    54  	return mockCtrl, mockBlockChain, mockMiner, &CNAPIBackend{cn: cn}
    55  }
    56  
    57  func TestCNAPIBackend_GetTxAndLookupInfoInCache(t *testing.T) {
    58  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
    59  	defer mockCtrl.Finish()
    60  
    61  	hash := hashes[0]
    62  
    63  	expectedTx := tx1
    64  	expectedBlockHash := hashes[1]
    65  	expectedBlockNum := uint64(111)
    66  	expectedIndex := uint64(999)
    67  
    68  	mockBlockChain.EXPECT().GetTxAndLookupInfoInCache(hash).Times(1).Return(expectedTx, expectedBlockHash, expectedBlockNum, expectedIndex)
    69  	tx, blockHash, blockNumber, index := api.GetTxAndLookupInfoInCache(hash)
    70  
    71  	assert.Equal(t, expectedTx, tx)
    72  	assert.Equal(t, expectedBlockHash, blockHash)
    73  	assert.Equal(t, expectedBlockNum, blockNumber)
    74  	assert.Equal(t, expectedIndex, index)
    75  }
    76  
    77  func TestCNAPIBackend_GetTxLookupInfoAndReceipt(t *testing.T) {
    78  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
    79  	defer mockCtrl.Finish()
    80  
    81  	hash := hashes[0]
    82  
    83  	expectedTx := tx1
    84  	expectedBlockHash := hashes[1]
    85  	expectedBlockNum := uint64(111)
    86  	expectedIndex := uint64(999)
    87  	expectedReceipt := newReceipt(123)
    88  
    89  	mockBlockChain.EXPECT().GetTxLookupInfoAndReceipt(hash).Times(1).Return(expectedTx, expectedBlockHash, expectedBlockNum, expectedIndex, expectedReceipt)
    90  	tx, blockHash, blockNumber, index, receipt := api.GetTxLookupInfoAndReceipt(context.Background(), hash)
    91  
    92  	assert.Equal(t, expectedTx, tx)
    93  	assert.Equal(t, expectedBlockHash, blockHash)
    94  	assert.Equal(t, expectedBlockNum, blockNumber)
    95  	assert.Equal(t, expectedIndex, index)
    96  	assert.Equal(t, expectedReceipt, receipt)
    97  }
    98  
    99  func TestCNAPIBackend_GetBlockReceiptsInCache(t *testing.T) {
   100  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   101  	defer mockCtrl.Finish()
   102  
   103  	hash := hashes[0]
   104  	expectedReceipts := types.Receipts{newReceipt(111), newReceipt(222)}
   105  
   106  	mockBlockChain.EXPECT().GetBlockReceiptsInCache(hash).Return(expectedReceipts).Times(1)
   107  
   108  	assert.Equal(t, expectedReceipts, api.GetBlockReceiptsInCache(hash))
   109  }
   110  
   111  func TestCNAPIBackend_GetTxLookupInfoAndReceiptInCache(t *testing.T) {
   112  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   113  	defer mockCtrl.Finish()
   114  
   115  	hash := hashes[0]
   116  
   117  	expectedTx := tx1
   118  	expectedBlockHash := hashes[1]
   119  	expectedBlockNum := uint64(111)
   120  	expectedIndex := uint64(999)
   121  	expectedReceipt := newReceipt(123)
   122  
   123  	mockBlockChain.EXPECT().GetTxLookupInfoAndReceiptInCache(hash).Times(1).Return(expectedTx, expectedBlockHash, expectedBlockNum, expectedIndex, expectedReceipt)
   124  	tx, blockHash, blockNumber, index, receipt := api.GetTxLookupInfoAndReceiptInCache(hash)
   125  
   126  	assert.Equal(t, expectedTx, tx)
   127  	assert.Equal(t, expectedBlockHash, blockHash)
   128  	assert.Equal(t, expectedBlockNum, blockNumber)
   129  	assert.Equal(t, expectedIndex, index)
   130  	assert.Equal(t, expectedReceipt, receipt)
   131  }
   132  
   133  func TestCNAPIBackend_ChainConfig(t *testing.T) {
   134  	mockCtrl, _, _, api := newCNAPIBackend(t)
   135  	defer mockCtrl.Finish()
   136  
   137  	assert.Nil(t, api.ChainConfig())
   138  
   139  	emptyConfig := &params.ChainConfig{}
   140  	api.cn.chainConfig = &*emptyConfig
   141  	assert.Equal(t, emptyConfig, api.ChainConfig())
   142  
   143  	nonEmptyConfig := &params.ChainConfig{ChainID: big.NewInt(123)}
   144  	api.cn.chainConfig = &*nonEmptyConfig
   145  	assert.Equal(t, nonEmptyConfig, api.ChainConfig())
   146  }
   147  
   148  func TestCNAPIBackend_CurrentBlock(t *testing.T) {
   149  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   150  	defer mockCtrl.Finish()
   151  
   152  	block := newBlock(123)
   153  	mockBlockChain.EXPECT().CurrentBlock().Return(block).Times(1)
   154  
   155  	assert.Equal(t, block, api.CurrentBlock())
   156  }
   157  
   158  func getTestConfig() *params.ChainConfig {
   159  	config := params.TestChainConfig.Copy()
   160  	config.Governance = params.GetDefaultGovernanceConfig()
   161  	config.Istanbul = params.GetDefaultIstanbulConfig()
   162  	return config
   163  }
   164  
   165  func testGov() *governance.MixedEngine {
   166  	db := database.NewDBManager(&database.DBConfig{DBType: database.MemoryDB})
   167  	config := params.TestChainConfig.Copy()
   168  	config.Governance = params.GetDefaultGovernanceConfig()
   169  	config.Istanbul = params.GetDefaultIstanbulConfig()
   170  	return governance.NewMixedEngine(config, db)
   171  }
   172  
   173  func TestCNAPIBackend_SetHead(t *testing.T) {
   174  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   175  	defer mockCtrl.Finish()
   176  
   177  	mockDownloader := mocks2.NewMockProtocolManagerDownloader(mockCtrl)
   178  	mockDownloader.EXPECT().Cancel().Times(1)
   179  	pm := &ProtocolManager{downloader: mockDownloader}
   180  	api.cn.protocolManager = pm
   181  	api.cn.engine = gxhash.NewFullFaker()
   182  	api.cn.governance = testGov()
   183  
   184  	number := uint64(123)
   185  	mockBlockChain.EXPECT().SetHead(number).Times(1)
   186  
   187  	api.SetHead(number)
   188  	block := newBlock(int(number))
   189  	expectedHeader := block.Header()
   190  	mockBlockChain.EXPECT().CurrentHeader().Return(expectedHeader).Times(1)
   191  	assert.Equal(t, expectedHeader, mockBlockChain.CurrentHeader())
   192  }
   193  
   194  func TestCNAPIBackend_HeaderByNumber(t *testing.T) {
   195  	blockNum := uint64(123)
   196  	block := newBlock(int(blockNum))
   197  	expectedHeader := block.Header()
   198  	{
   199  		mockCtrl, _, mockMiner, api := newCNAPIBackend(t)
   200  		mockMiner.EXPECT().PendingBlock().Return(block).Times(1)
   201  
   202  		header, err := api.HeaderByNumber(context.Background(), rpc.PendingBlockNumber)
   203  
   204  		assert.Equal(t, expectedHeader, header)
   205  		assert.NoError(t, err)
   206  
   207  		mockCtrl.Finish()
   208  	}
   209  	{
   210  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   211  		mockBlockChain.EXPECT().CurrentBlock().Return(block).Times(1)
   212  
   213  		header, err := api.HeaderByNumber(context.Background(), rpc.LatestBlockNumber)
   214  
   215  		assert.Equal(t, expectedHeader, header)
   216  		assert.NoError(t, err)
   217  
   218  		mockCtrl.Finish()
   219  	}
   220  	{
   221  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   222  		mockBlockChain.EXPECT().GetHeaderByNumber(blockNum).Return(nil).Times(1)
   223  
   224  		header, err := api.HeaderByNumber(context.Background(), rpc.BlockNumber(blockNum))
   225  
   226  		assert.Nil(t, header)
   227  		assert.Error(t, err)
   228  
   229  		mockCtrl.Finish()
   230  	}
   231  	{
   232  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   233  		mockBlockChain.EXPECT().GetHeaderByNumber(blockNum).Return(expectedHeader).Times(1)
   234  
   235  		header, err := api.HeaderByNumber(context.Background(), rpc.BlockNumber(blockNum))
   236  
   237  		assert.Equal(t, expectedHeader, header)
   238  		assert.NoError(t, err)
   239  
   240  		mockCtrl.Finish()
   241  	}
   242  }
   243  
   244  func TestCNAPIBackend_HeaderByNumberOrHash(t *testing.T) {
   245  	block := newBlock(123)
   246  	expectedHeader := block.Header()
   247  	{
   248  		mockCtrl, _, mockMiner, api := newCNAPIBackend(t)
   249  		mockMiner.EXPECT().PendingBlock().Return(block).Times(1)
   250  
   251  		header, err := api.HeaderByNumberOrHash(context.Background(), rpc.NewBlockNumberOrHashWithNumber(rpc.PendingBlockNumber))
   252  
   253  		assert.Equal(t, expectedHeader, header)
   254  		assert.NoError(t, err)
   255  
   256  		mockCtrl.Finish()
   257  	}
   258  	{
   259  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   260  		mockBlockChain.EXPECT().CurrentBlock().Return(block).Times(1)
   261  
   262  		header, err := api.HeaderByNumberOrHash(context.Background(), rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber))
   263  
   264  		assert.Equal(t, expectedHeader, header)
   265  		assert.NoError(t, err)
   266  
   267  		mockCtrl.Finish()
   268  	}
   269  	{
   270  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   271  		mockBlockChain.EXPECT().GetHeaderByNumber(uint64(123)).Return(expectedHeader).Times(1)
   272  
   273  		header, err := api.HeaderByNumberOrHash(context.Background(), rpc.NewBlockNumberOrHashWithNumber(rpc.BlockNumber(123)))
   274  
   275  		assert.Equal(t, expectedHeader, header)
   276  		assert.NoError(t, err)
   277  
   278  		mockCtrl.Finish()
   279  	}
   280  	{
   281  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   282  		mockBlockChain.EXPECT().GetHeaderByHash(hash1).Return(expectedHeader).Times(1)
   283  
   284  		header, err := api.HeaderByNumberOrHash(context.Background(), rpc.NewBlockNumberOrHashWithHash(hash1, false))
   285  
   286  		assert.Equal(t, expectedHeader, header)
   287  		assert.NoError(t, err)
   288  
   289  		mockCtrl.Finish()
   290  	}
   291  }
   292  
   293  func TestCNAPIBackend_HeaderByHash(t *testing.T) {
   294  	{
   295  		blockNum := uint64(123)
   296  		block := newBlock(int(blockNum))
   297  		expectedHeader := block.Header()
   298  
   299  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   300  		mockBlockChain.EXPECT().GetHeaderByHash(hash1).Return(expectedHeader).Times(1)
   301  
   302  		header, err := api.HeaderByHash(context.Background(), hash1)
   303  
   304  		assert.Equal(t, expectedHeader, header)
   305  		assert.NoError(t, err)
   306  
   307  		mockCtrl.Finish()
   308  	}
   309  }
   310  
   311  func TestCNAPIBackend_BlockByNumber(t *testing.T) {
   312  	blockNum := uint64(123)
   313  	block := newBlock(int(blockNum))
   314  	expectedBlock := block
   315  	{
   316  		mockCtrl, _, mockMiner, api := newCNAPIBackend(t)
   317  		mockMiner.EXPECT().PendingBlock().Return(block).Times(1)
   318  
   319  		block, err := api.BlockByNumber(context.Background(), rpc.PendingBlockNumber)
   320  
   321  		assert.Equal(t, expectedBlock, block)
   322  		assert.NoError(t, err)
   323  
   324  		mockCtrl.Finish()
   325  	}
   326  	{
   327  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   328  		mockBlockChain.EXPECT().CurrentBlock().Return(block).Times(1)
   329  
   330  		block, err := api.BlockByNumber(context.Background(), rpc.LatestBlockNumber)
   331  
   332  		assert.Equal(t, expectedBlock, block)
   333  		assert.NoError(t, err)
   334  
   335  		mockCtrl.Finish()
   336  	}
   337  	{
   338  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   339  		mockBlockChain.EXPECT().GetBlockByNumber(blockNum).Return(nil).Times(1)
   340  
   341  		block, err := api.BlockByNumber(context.Background(), rpc.BlockNumber(blockNum))
   342  
   343  		assert.Nil(t, block)
   344  		assert.Error(t, err)
   345  
   346  		mockCtrl.Finish()
   347  	}
   348  	{
   349  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   350  		mockBlockChain.EXPECT().GetBlockByNumber(blockNum).Return(expectedBlock).Times(1)
   351  
   352  		block, err := api.BlockByNumber(context.Background(), rpc.BlockNumber(blockNum))
   353  
   354  		assert.Equal(t, expectedBlock, block)
   355  		assert.NoError(t, err)
   356  
   357  		mockCtrl.Finish()
   358  	}
   359  }
   360  
   361  func TestCNAPIBackend_BlockByNumberOrHash(t *testing.T) {
   362  	blockNum := uint64(123)
   363  	block := newBlock(int(blockNum))
   364  	expectedBlock := block
   365  	{
   366  		mockCtrl, _, mockMiner, api := newCNAPIBackend(t)
   367  		mockMiner.EXPECT().PendingBlock().Return(block).Times(1)
   368  
   369  		block, err := api.BlockByNumberOrHash(context.Background(), rpc.NewBlockNumberOrHashWithNumber(rpc.PendingBlockNumber))
   370  
   371  		assert.Equal(t, expectedBlock, block)
   372  		assert.NoError(t, err)
   373  
   374  		mockCtrl.Finish()
   375  	}
   376  	{
   377  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   378  		mockBlockChain.EXPECT().CurrentBlock().Return(expectedBlock).Times(1)
   379  
   380  		block, err := api.BlockByNumberOrHash(context.Background(), rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber))
   381  
   382  		assert.Equal(t, expectedBlock, block)
   383  		assert.NoError(t, err)
   384  
   385  		mockCtrl.Finish()
   386  	}
   387  	{
   388  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   389  		mockBlockChain.EXPECT().GetBlockByNumber(uint64(123)).Return(nil).Times(1)
   390  
   391  		block, err := api.BlockByNumberOrHash(context.Background(), rpc.NewBlockNumberOrHashWithNumber(rpc.BlockNumber(123)))
   392  
   393  		assert.Nil(t, block)
   394  		assert.Error(t, err)
   395  
   396  		mockCtrl.Finish()
   397  	}
   398  	{
   399  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   400  		mockBlockChain.EXPECT().GetBlockByHash(hash1).Return(expectedBlock).Times(1)
   401  
   402  		block, err := api.BlockByNumberOrHash(context.Background(), rpc.NewBlockNumberOrHashWithHash(hash1, false))
   403  
   404  		assert.Equal(t, expectedBlock, block)
   405  		assert.NoError(t, err)
   406  
   407  		mockCtrl.Finish()
   408  	}
   409  }
   410  
   411  func TestCNAPIBackend_StateAndHeaderByNumber(t *testing.T) {
   412  	blockNum := uint64(123)
   413  	block := newBlock(int(blockNum))
   414  
   415  	stateDB, err := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil, nil)
   416  	if err != nil {
   417  		t.Fatal(err)
   418  	}
   419  	stateDB.SetNonce(addrs[0], 123)
   420  	stateDB.SetNonce(addrs[1], 321)
   421  
   422  	expectedHeader := block.Header()
   423  	{
   424  		mockCtrl, _, mockMiner, api := newCNAPIBackend(t)
   425  		mockMiner.EXPECT().Pending().Return(block, stateDB).Times(1)
   426  
   427  		returnedStateDB, header, err := api.StateAndHeaderByNumber(context.Background(), rpc.PendingBlockNumber)
   428  
   429  		assert.Equal(t, stateDB, returnedStateDB)
   430  		assert.Equal(t, expectedHeader, header)
   431  		assert.NoError(t, err)
   432  
   433  		mockCtrl.Finish()
   434  	}
   435  	{
   436  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   437  
   438  		mockBlockChain.EXPECT().GetHeaderByNumber(blockNum).Return(nil).Times(1)
   439  		returnedStateDB, header, err := api.StateAndHeaderByNumber(context.Background(), rpc.BlockNumber(blockNum))
   440  
   441  		assert.Nil(t, returnedStateDB)
   442  		assert.Nil(t, header)
   443  		assert.Error(t, err)
   444  
   445  		mockCtrl.Finish()
   446  	}
   447  	{
   448  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   449  
   450  		mockBlockChain.EXPECT().GetHeaderByNumber(blockNum).Return(expectedHeader).Times(1)
   451  		mockBlockChain.EXPECT().StateAt(expectedHeader.Root).Return(stateDB, nil).Times(1)
   452  		returnedStateDB, header, err := api.StateAndHeaderByNumber(context.Background(), rpc.BlockNumber(blockNum))
   453  
   454  		assert.Equal(t, stateDB, returnedStateDB)
   455  		assert.Equal(t, expectedHeader, header)
   456  		assert.NoError(t, err)
   457  
   458  		mockCtrl.Finish()
   459  	}
   460  }
   461  
   462  func TestCNAPIBackend_GetBlock(t *testing.T) {
   463  	block := newBlock(123)
   464  	hash := hashes[0]
   465  	{
   466  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   467  		mockBlockChain.EXPECT().GetBlockByHash(hash).Return(nil).Times(1)
   468  
   469  		returnedBlock, err := api.BlockByHash(context.Background(), hash)
   470  		assert.Nil(t, returnedBlock)
   471  		assert.Error(t, err)
   472  
   473  		mockCtrl.Finish()
   474  	}
   475  	{
   476  		mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   477  		mockBlockChain.EXPECT().GetBlockByHash(hash).Return(block).Times(1)
   478  
   479  		returnedBlock, err := api.BlockByHash(context.Background(), hash)
   480  		assert.Equal(t, block, returnedBlock)
   481  		assert.NoError(t, err)
   482  
   483  		mockCtrl.Finish()
   484  	}
   485  }
   486  
   487  func TestCNAPIBackend_GetTxAndLookupInfo(t *testing.T) {
   488  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   489  	defer mockCtrl.Finish()
   490  
   491  	hash := hashes[0]
   492  
   493  	expectedTx := tx1
   494  	expectedBlockHash := hashes[1]
   495  	expectedBlockNum := uint64(111)
   496  	expectedIndex := uint64(999)
   497  
   498  	mockBlockChain.EXPECT().GetTxAndLookupInfo(hash).Times(1).Return(expectedTx, expectedBlockHash, expectedBlockNum, expectedIndex)
   499  	tx, blockHash, blockNumber, index := api.GetTxAndLookupInfo(hash)
   500  
   501  	assert.Equal(t, expectedTx, tx)
   502  	assert.Equal(t, expectedBlockHash, blockHash)
   503  	assert.Equal(t, expectedBlockNum, blockNumber)
   504  	assert.Equal(t, expectedIndex, index)
   505  }
   506  
   507  func TestCNAPIBackend_GetBlockReceipts(t *testing.T) {
   508  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   509  	defer mockCtrl.Finish()
   510  
   511  	hash := hashes[0]
   512  	expectedReceipts := types.Receipts{newReceipt(111), newReceipt(222)}
   513  
   514  	mockBlockChain.EXPECT().GetReceiptsByBlockHash(hash).Return(expectedReceipts).Times(1)
   515  
   516  	assert.Equal(t, expectedReceipts, api.GetBlockReceipts(context.Background(), hash))
   517  }
   518  
   519  func TestCNAPIBackend_GetLogs(t *testing.T) {
   520  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   521  	defer mockCtrl.Finish()
   522  
   523  	hash := hashes[0]
   524  	expectedLogs := [][]*types.Log{{{BlockNumber: 123}}, {{BlockNumber: 321}}}
   525  	mockBlockChain.EXPECT().GetLogsByHash(hash).Return(expectedLogs).Times(1)
   526  
   527  	logs, err := api.GetLogs(context.Background(), hash)
   528  	assert.Equal(t, expectedLogs, logs)
   529  	assert.NoError(t, err)
   530  }
   531  
   532  func TestCNAPIBackend_GetTd(t *testing.T) {
   533  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   534  	defer mockCtrl.Finish()
   535  
   536  	td := big.NewInt(123)
   537  	hash := hashes[0]
   538  	mockBlockChain.EXPECT().GetTdByHash(hash).Return(td).Times(1)
   539  
   540  	assert.Equal(t, td, api.GetTd(hash))
   541  }
   542  
   543  func TestCNAPIBackend_SubscribeEvents(t *testing.T) {
   544  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   545  	mockTxPool := mocks.NewMockTxPool(mockCtrl)
   546  	api.cn.txPool = mockTxPool
   547  	defer mockCtrl.Finish()
   548  
   549  	rmCh := make(chan<- blockchain.RemovedLogsEvent)
   550  	ceCh := make(chan<- blockchain.ChainEvent)
   551  	chCh := make(chan<- blockchain.ChainHeadEvent)
   552  	csCh := make(chan<- blockchain.ChainSideEvent)
   553  	leCh := make(chan<- []*types.Log)
   554  	txCh := make(chan<- blockchain.NewTxsEvent)
   555  
   556  	sub := mocks3.NewMockSubscription(mockCtrl)
   557  
   558  	mockBlockChain.EXPECT().SubscribeRemovedLogsEvent(rmCh).Return(sub).Times(1)
   559  	mockBlockChain.EXPECT().SubscribeChainEvent(ceCh).Return(sub).Times(1)
   560  	mockBlockChain.EXPECT().SubscribeChainHeadEvent(chCh).Return(sub).Times(1)
   561  	mockBlockChain.EXPECT().SubscribeChainSideEvent(csCh).Return(sub).Times(1)
   562  	mockBlockChain.EXPECT().SubscribeLogsEvent(leCh).Return(sub).Times(1)
   563  
   564  	mockTxPool.EXPECT().SubscribeNewTxsEvent(txCh).Return(sub).Times(1)
   565  
   566  	assert.Equal(t, sub, api.SubscribeRemovedLogsEvent(rmCh))
   567  	assert.Equal(t, sub, api.SubscribeChainEvent(ceCh))
   568  	assert.Equal(t, sub, api.SubscribeChainHeadEvent(chCh))
   569  	assert.Equal(t, sub, api.SubscribeChainSideEvent(csCh))
   570  	assert.Equal(t, sub, api.SubscribeLogsEvent(leCh))
   571  
   572  	assert.Equal(t, sub, api.SubscribeNewTxsEvent(txCh))
   573  }
   574  
   575  func TestCNAPIBackend_SendTx(t *testing.T) {
   576  	mockCtrl, _, _, api := newCNAPIBackend(t)
   577  	mockTxPool := mocks.NewMockTxPool(mockCtrl)
   578  	mockTxPool.EXPECT().AddLocal(tx1).Return(expectedErr).Times(1)
   579  	api.cn.txPool = mockTxPool
   580  
   581  	defer mockCtrl.Finish()
   582  
   583  	assert.Equal(t, expectedErr, api.SendTx(context.Background(), tx1))
   584  }
   585  
   586  func TestCNAPIBackend_GetPoolTransactions(t *testing.T) {
   587  	{
   588  		mockCtrl, _, _, api := newCNAPIBackend(t)
   589  		mockTxPool := mocks.NewMockTxPool(mockCtrl)
   590  		mockTxPool.EXPECT().Pending().Return(nil, expectedErr).Times(1)
   591  		api.cn.txPool = mockTxPool
   592  
   593  		txs, ReturnedErr := api.GetPoolTransactions()
   594  		assert.Nil(t, txs)
   595  		assert.Equal(t, expectedErr, ReturnedErr)
   596  		mockCtrl.Finish()
   597  	}
   598  	{
   599  		mockCtrl, _, _, api := newCNAPIBackend(t)
   600  		mockTxPool := mocks.NewMockTxPool(mockCtrl)
   601  
   602  		pendingTxs := map[common.Address]types.Transactions{addrs[0]: {tx1}}
   603  		mockTxPool.EXPECT().Pending().Return(pendingTxs, nil).Times(1)
   604  		api.cn.txPool = mockTxPool
   605  
   606  		txs, ReturnedErr := api.GetPoolTransactions()
   607  		assert.Equal(t, types.Transactions{tx1}, txs)
   608  		assert.NoError(t, ReturnedErr)
   609  		mockCtrl.Finish()
   610  	}
   611  }
   612  
   613  func TestCNAPIBackend_GetPoolTransaction(t *testing.T) {
   614  	hash := hashes[0]
   615  
   616  	mockCtrl, _, _, api := newCNAPIBackend(t)
   617  	mockTxPool := mocks.NewMockTxPool(mockCtrl)
   618  	mockTxPool.EXPECT().Get(hash).Return(tx1).Times(1)
   619  	api.cn.txPool = mockTxPool
   620  
   621  	defer mockCtrl.Finish()
   622  
   623  	assert.Equal(t, tx1, api.GetPoolTransaction(hash))
   624  }
   625  
   626  func TestCNAPIBackend_GetPoolNonce(t *testing.T) {
   627  	addr := addrs[0]
   628  	nonce := uint64(123)
   629  
   630  	mockCtrl, _, _, api := newCNAPIBackend(t)
   631  	mockTxPool := mocks.NewMockTxPool(mockCtrl)
   632  	mockTxPool.EXPECT().GetPendingNonce(addr).Return(nonce).Times(1)
   633  	api.cn.txPool = mockTxPool
   634  
   635  	defer mockCtrl.Finish()
   636  
   637  	assert.Equal(t, nonce, api.GetPoolNonce(context.Background(), addr))
   638  }
   639  
   640  func TestCNAPIBackend_Stats(t *testing.T) {
   641  	pending := 123
   642  	queued := 321
   643  
   644  	mockCtrl, _, _, api := newCNAPIBackend(t)
   645  	mockTxPool := mocks.NewMockTxPool(mockCtrl)
   646  	mockTxPool.EXPECT().Stats().Return(pending, queued).Times(1)
   647  	api.cn.txPool = mockTxPool
   648  
   649  	defer mockCtrl.Finish()
   650  
   651  	p, q := api.Stats()
   652  	assert.Equal(t, pending, p)
   653  	assert.Equal(t, queued, q)
   654  }
   655  
   656  func TestCNAPIBackend_TxPoolContent(t *testing.T) {
   657  	pending := map[common.Address]types.Transactions{addrs[0]: {tx1}}
   658  	queued := map[common.Address]types.Transactions{addrs[1]: {tx1}}
   659  
   660  	mockCtrl, _, _, api := newCNAPIBackend(t)
   661  	mockTxPool := mocks.NewMockTxPool(mockCtrl)
   662  	mockTxPool.EXPECT().Content().Return(pending, queued).Times(1)
   663  	api.cn.txPool = mockTxPool
   664  
   665  	defer mockCtrl.Finish()
   666  
   667  	p, q := api.TxPoolContent()
   668  	assert.Equal(t, pending, p)
   669  	assert.Equal(t, queued, q)
   670  }
   671  
   672  func TestCNAPIBackend_IsParallelDBWrite(t *testing.T) {
   673  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   674  	defer mockCtrl.Finish()
   675  
   676  	mockBlockChain.EXPECT().IsParallelDBWrite().Return(true).Times(1)
   677  	assert.True(t, api.IsParallelDBWrite())
   678  }
   679  
   680  func TestCNAPIBackend_IsSenderTxHashIndexingEnabled(t *testing.T) {
   681  	mockCtrl, mockBlockChain, _, api := newCNAPIBackend(t)
   682  	defer mockCtrl.Finish()
   683  
   684  	mockBlockChain.EXPECT().IsSenderTxHashIndexingEnabled().Return(true).Times(1)
   685  	assert.True(t, api.IsSenderTxHashIndexingEnabled())
   686  }
   687  
   688  type rewindTest struct {
   689  	canonicalBlocks int // Number of blocks to generate for the canonical chain (heavier)
   690  
   691  	setheadBlock       uint64 // Block number to set head back to
   692  	expCanonicalBlocks int    // Number of canonical blocks expected to remain in the database (excl. genesis)
   693  	expHeadHeader      uint64 // Block number of the expected head header
   694  	expHeadFastBlock   uint64 // Block number of the expected head fast sync block
   695  	expHeadBlock       uint64 // Block number of the expected head full block
   696  }
   697  
   698  func newCanonical(engine consensus.Engine, n int, full bool) (database.DBManager, *blockchain.BlockChain, error) {
   699  	var (
   700  		canonicalSeed = 1
   701  		db            = database.NewDBManager(&database.DBConfig{DBType: database.MemoryDB})
   702  		// TODO: Remove me
   703  		// db      = database.NewMemoryDBManager()
   704  		genesis = new(blockchain.Genesis).MustCommit(db)
   705  	)
   706  
   707  	// Initialize a fresh chain with only a genesis block
   708  	bc, _ := blockchain.NewBlockChain(db, nil, params.AllGxhashProtocolChanges, engine, vm.Config{})
   709  	// Create and inject the requested chain
   710  	if n == 0 {
   711  		return db, bc, nil
   712  	}
   713  	if full {
   714  		// Full block-chain requested
   715  		blocks := blockchain.MakeBlockChain(genesis, n, engine, db, canonicalSeed)
   716  		_, err := bc.InsertChain(blocks)
   717  		return db, bc, err
   718  	}
   719  	// Header-only chain requested
   720  	headers := blockchain.MakeHeaderChain(genesis.Header(), n, engine, db, canonicalSeed)
   721  	_, err := bc.InsertHeaderChain(headers, 1)
   722  	return db, bc, err
   723  }
   724  
   725  func expectedGovMap(t *testing.T, gov *governance.MixedEngine, num uint64, item string, value interface{}, expectedCacheSize int) {
   726  	_, govMap, err := gov.ReadGovernance(num)
   727  	assert.Nil(t, err)
   728  	assert.Equal(t, govMap[item], value)
   729  	assert.Equal(t, len(gov.IdxCache())-1, expectedCacheSize)
   730  }
   731  
   732  func TestSetHead(t *testing.T) {
   733  	headerGovTest(t, &rewindTest{
   734  		// `params.CheckpointInterval` is constant value of 1024.
   735  		// Make it longer to include its working coverage
   736  		canonicalBlocks:    1500,
   737  		setheadBlock:       6,
   738  		expCanonicalBlocks: 6,
   739  		expHeadHeader:      6,
   740  		expHeadFastBlock:   6,
   741  		expHeadBlock:       6,
   742  	})
   743  }
   744  
   745  func testCfg(epoch uint64) *params.ChainConfig {
   746  	config := params.TestChainConfig.Copy()
   747  	config.Governance = params.GetDefaultGovernanceConfig()
   748  	config.Istanbul = params.GetDefaultIstanbulConfig()
   749  	config.Istanbul.Epoch = epoch
   750  	return config
   751  }
   752  
   753  func headerGovTest(t *testing.T, tt *rewindTest) {
   754  	db, chain, err := newCanonical(gxhash.NewFullFaker(), 0, true)
   755  	if err != nil {
   756  		t.Fatalf("failed to create pristine chain: %v", err)
   757  	}
   758  	defer chain.Stop()
   759  
   760  	var (
   761  		epoch                 uint64 = 5
   762  		govBlockNum                  = 10
   763  		appliedGovBlockNum    uint64 = 20
   764  		stakingUpdateInterval uint64 = 1
   765  		stakingUpdateBlockNum uint64 = 15
   766  		gov                          = governance.NewMixedEngine(testCfg(epoch), db)
   767  	)
   768  	chain.Config().Istanbul = &params.IstanbulConfig{Epoch: epoch, ProposerPolicy: params.WeightedRandom}
   769  
   770  	canonblocks, _ := blockchain.GenerateChain(params.TestChainConfig, chain.CurrentBlock(), gxhash.NewFaker(), db, tt.canonicalBlocks, func(i int, b *blockchain.BlockGen) {
   771  		if i == govBlockNum-1 { // Subtract 1, because the callback starts to enumerate from zero
   772  			// "reward.mintingamount" = 123
   773  			govData := hexutil.MustDecode("0x9e7b227265776172642e6d696e74696e67616d6f756e74223a22313233227d")
   774  			b.SetGovData(govData)
   775  			gov.WriteGovernanceForNextEpoch(uint64(govBlockNum), govData)
   776  		}
   777  	})
   778  
   779  	if _, err := chain.InsertChain(canonblocks[:tt.canonicalBlocks]); err != nil {
   780  		t.Fatalf("Failed to import canonical chain start: %v", err)
   781  	}
   782  
   783  	// Store snapshot
   784  	snap := backend.Snapshot{Number: params.CheckpointInterval, Hash: chain.GetHeaderByNumber(params.CheckpointInterval).Hash()}
   785  	blob, err := json.Marshal(snap)
   786  	assert.Nil(t, err)
   787  	err = db.WriteIstanbulSnapshot(snap.Hash, blob)
   788  	assert.Nil(t, err)
   789  	_, err = db.ReadIstanbulSnapshot(snap.Hash)
   790  	assert.Nil(t, err)
   791  
   792  	// Initiailize staking info manager
   793  	dummy := reward.StakingInfo{BlockNum: stakingUpdateInterval}
   794  	blob, err = json.Marshal(dummy)
   795  	assert.Nil(t, err)
   796  	reward.SetTestStakingManagerWithStakingInfoCache(&dummy)
   797  	assert.NotNil(t, reward.GetStakingManager())
   798  	params.SetStakingUpdateInterval(stakingUpdateInterval)
   799  	// Write a value to DB
   800  	err = db.WriteStakingInfo(stakingUpdateBlockNum, blob)
   801  	assert.Nil(t, err)
   802  	_, err = db.ReadStakingInfo(stakingUpdateBlockNum)
   803  	assert.Nil(t, err)
   804  	assert.Equal(t, reward.TestGetStakingCacheSize(), 1)
   805  
   806  	// Before setHead
   807  	expectedGovMap(t, gov, appliedGovBlockNum, "reward.mintingamount", "123", 1)
   808  
   809  	// Set the head of the chain back to the requested number
   810  	err = doSetHead(chain, chain.Engine(), gov, tt.setheadBlock)
   811  	assert.Nil(t, err)
   812  
   813  	if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader {
   814  		t.Errorf("Head header mismatch!: have %d, want %d", head.Number, tt.expHeadHeader)
   815  	}
   816  	if head := chain.CurrentFastBlock(); head.NumberU64() != tt.expHeadFastBlock {
   817  		t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadFastBlock)
   818  	}
   819  	if head := chain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock {
   820  		t.Errorf("Head block mismatch!!: have %d, want %d", head.NumberU64(), tt.expHeadBlock)
   821  	}
   822  	// After setHead
   823  	// governance db and cachelookup
   824  	expectedGovMap(t, gov, appliedGovBlockNum, "reward.mintingamount", "0", 0)
   825  
   826  	// staking db and cache lookup
   827  	assert.Equal(t, reward.TestGetStakingCacheSize(), 0)
   828  	_, err = db.ReadStakingInfo(stakingUpdateBlockNum)
   829  	assert.Equal(t, err.Error(), "data is not found with the given key")
   830  
   831  	// snapshot db lookup
   832  	_, err = db.ReadIstanbulSnapshot(snap.Hash)
   833  	assert.Equal(t, err.Error(), "data is not found with the given key")
   834  
   835  	for _, b := range canonblocks[tt.expCanonicalBlocks:] {
   836  		if _, err := chain.InsertChain(types.Blocks{b}); err != nil {
   837  			t.Fatalf("Failed to import canonical chain start: %v", err)
   838  		}
   839  		if len(b.Header().Governance) > 0 {
   840  			assert.Equal(t, b.Header().Number.Uint64()%uint64(epoch), uint64(0))
   841  			gov.WriteGovernanceForNextEpoch(uint64(govBlockNum), b.Header().Governance)
   842  		}
   843  	}
   844  	if head := chain.CurrentBlock(); head.NumberU64() != uint64(tt.canonicalBlocks) {
   845  		t.Errorf("Head block mismatch!!: have %d, want %d", head.NumberU64(), tt.expHeadBlock)
   846  	}
   847  	// After setHead and sync
   848  	expectedGovMap(t, gov, appliedGovBlockNum, "reward.mintingamount", "123", 1)
   849  }