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 := ¶ms.ChainConfig{} 140 api.cn.chainConfig = &*emptyConfig 141 assert.Equal(t, emptyConfig, api.ChainConfig()) 142 143 nonEmptyConfig := ¶ms.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 = ¶ms.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 }