From e7c3787af03b2773338c97947ff96311f935e7e7 Mon Sep 17 00:00:00 2001 From: CoderZhi Date: Mon, 11 Mar 2024 18:55:07 +0200 Subject: [PATCH] clean up blockdao (#4164) * clean up blockdao * address comments * fix contract address * address conflict --- action/protocol/execution/protocol_test.go | 40 ++-- api/coreservice.go | 43 +++- api/grpcserver_integrity_test.go | 8 +- api/serverV2_integrity_test.go | 26 ++- blockchain/block/block.go | 15 ++ blockchain/blockdao/blockdao.go | 169 ++++---------- blockchain/blockdao/blockdao_test.go | 51 +++-- blockchain/integrity/benchmark_test.go | 23 +- blockchain/integrity/integrity_test.go | 129 +++++++---- blockindex/indexbuilder_test.go | 10 +- blocksync/blocksync_test.go | 25 ++- blocksync/buffer_test.go | 9 +- chainservice/builder.go | 14 +- consensus/scheme/rolldpos/rolldpos_test.go | 5 +- .../scheme/rolldpos/roundcalculator_test.go | 6 +- e2etest/bigint_test.go | 5 +- e2etest/contract_staking_test.go | 23 +- e2etest/local_test.go | 30 ++- e2etest/local_transfer_test.go | 5 +- e2etest/native_staking_test.go | 212 +++++++----------- e2etest/sgd_registry_test.go | 9 +- e2etest/staking_test.go | 4 +- gasstation/gasstattion_test.go | 9 +- test/mock/mock_blockdao/mock_blockdao.go | 59 ----- tools/iomigrater/cmds/check-height.go | 8 +- tools/iomigrater/cmds/migrate-db.go | 13 +- tools/staterecoverer/staterecoverer.go | 34 +-- 27 files changed, 507 insertions(+), 477 deletions(-) diff --git a/action/protocol/execution/protocol_test.go b/action/protocol/execution/protocol_test.go index 04c69d868a..21edfc01dc 100644 --- a/action/protocol/execution/protocol_test.go +++ b/action/protocol/execution/protocol_test.go @@ -40,6 +40,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/blockindex" "github.com/iotexproject/iotex-core/config" @@ -362,11 +363,19 @@ func (sct *SmartContractTest) runExecutions( if err := bc.CommitBlock(blk); err != nil { return nil, nil, err } - receipts := []*action.Receipt{} - for _, hash := range hashes { - receipt, err := dao.GetReceiptByActionHash(hash, blk.Height()) - if err != nil { - return nil, nil, err + receipts, err := dao.GetReceipts(blk.Height()) + if err != nil { + return nil, nil, err + } + receiptMap := make(map[hash.Hash256]*action.Receipt, len(receipts)) + for _, receipt := range receipts { + receiptMap[receipt.ActionHash] = receipt + } + receipts = receipts[:0] + for _, h := range hashes { + receipt, ok := receiptMap[h] + if !ok { + return nil, nil, errors.Errorf("failed to find receipt for action %x", h) } receipts = append(receipts, receipt) } @@ -459,7 +468,9 @@ func (sct *SmartContractTest) prepareBlockchain( indexer, err := blockindex.NewIndexer(db.NewMemKVStore(), cfg.Genesis.Hash()) r.NoError(err) // create BlockDAO - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf, indexer}) + store, err := filedao.NewFileDAOInMemForTest() + r.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf, indexer}, cfg.DB.MaxCacheSize) r.NotNil(dao) bc := blockchain.NewBlockchain( cfg.Chain, @@ -704,7 +715,9 @@ func TestProtocol_Handle(t *testing.T) { require.NoError(err) // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf, indexer}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf, indexer}, cfg.DB.MaxCacheSize) require.NotNil(dao) bc := blockchain.NewBlockchain( cfg.Chain, @@ -743,8 +756,7 @@ func TestProtocol_Handle(t *testing.T) { eHash, err := selp.Hash() require.NoError(err) - r, _ := dao.GetReceiptByActionHash(eHash, blk.Height()) - require.NotNil(r) + r := blk.Receipts[0] require.Equal(eHash, r.ActionHash) contract, err := address.FromString(r.ContractAddress) require.NoError(err) @@ -758,7 +770,7 @@ func TestProtocol_Handle(t *testing.T) { require.NoError(err) require.Equal(data[31:], c) - exe, _, err := dao.GetActionByActionHash(eHash, blk.Height()) + exe, _, err := blk.ActionByHash(eHash) require.NoError(err) exeHash, err := exe.Hash() require.NoError(err) @@ -809,9 +821,7 @@ func TestProtocol_Handle(t *testing.T) { */ eHash, err = selp.Hash() require.NoError(err) - r, err = dao.GetReceiptByActionHash(eHash, blk.Height()) - require.NoError(err) - require.Equal(eHash, r.ActionHash) + require.Equal(eHash, blk.Receipts[0].ActionHash) // read from key 0 data, err = hex.DecodeString("6d4ce63c") @@ -835,9 +845,7 @@ func TestProtocol_Handle(t *testing.T) { eHash, err = selp.Hash() require.NoError(err) - r, err = dao.GetReceiptByActionHash(eHash, blk.Height()) - require.NoError(err) - require.Equal(eHash, r.ActionHash) + require.Equal(eHash, blk.Receipts[0].ActionHash) data, _ = hex.DecodeString("608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a7230582002faabbefbbda99b20217cf33cb8ab8100caf1542bf1f48117d72e2c59139aea0029") execution1, err := action.NewExecution(action.EmptyAddress, 4, big.NewInt(0), uint64(100000), big.NewInt(10), data) diff --git a/api/coreservice.go b/api/coreservice.go index afd0e9df14..25f7ec8e97 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -781,11 +781,15 @@ func (core *coreService) ReceiptByActionHash(h hash.Hash256) (*action.Receipt, e if err != nil { return nil, errors.Wrap(ErrNotFound, err.Error()) } - receipt, err := core.dao.GetReceiptByActionHash(h, actIndex.BlockHeight()) + + receipts, err := core.dao.GetReceipts(actIndex.BlockHeight()) if err != nil { - return nil, errors.Wrap(ErrNotFound, err.Error()) + return nil, err + } + if receipt := filterReceipts(receipts, h); receipt != nil { + return receipt, nil } - return receipt, nil + return nil, errors.Wrapf(ErrNotFound, "failed to find receipt for action %x", h) } // TransactionLogByActionHash returns transaction log by action hash @@ -1089,7 +1093,7 @@ func (core *coreService) ActionByActionHash(h hash.Hash256) (*action.SealedEnvel if err != nil { return nil, hash.ZeroHash256, 0, 0, errors.Wrap(ErrNotFound, err.Error()) } - selp, index, err := core.dao.GetActionByActionHash(h, actIndex.BlockHeight()) + selp, index, err := blk.ActionByHash(h) if err != nil { return nil, hash.ZeroHash256, 0, 0, errors.Wrap(ErrNotFound, err.Error()) } @@ -1237,10 +1241,14 @@ func (core *coreService) committedAction(selp *action.SealedEnvelope, blkHash ha return nil, err } sender := selp.SenderAddress() - receipt, err := core.dao.GetReceiptByActionHash(actHash, blkHeight) + receipts, err := core.dao.GetReceipts(blkHeight) if err != nil { return nil, err } + receipt := filterReceipts(receipts, actHash) + if receipt == nil { + return nil, errors.Wrapf(ErrNotFound, "failed to find receipt for action %x", actHash) + } gas := new(big.Int) gas = gas.Mul(selp.GasPrice(), big.NewInt(int64(receipt.GasConsumed))) @@ -1301,12 +1309,22 @@ func (core *coreService) reverseActionsInBlock(blk *block.Block, reverseStart, c if reverseStart > size || count == 0 { return nil } + // TODO (saito): fix overflow start := size - (reverseStart + count) if start < 0 { start = 0 } end := size - 1 - reverseStart res := make([]*iotexapi.ActionInfo, 0, start-end+1) + receipts, err := core.dao.GetReceipts(blkHeight) + if err != nil { + log.Logger("api").Debug("Skipping action due to failing to get receipt", zap.Error(err)) + return nil + } + receiptMap := make(map[hash.Hash256]*action.Receipt, len(receipts)) + for _, receipt := range receipts { + receiptMap[receipt.ActionHash] = receipt + } for idx := start; idx <= end; idx++ { selp := blk.Actions[idx] actHash, err := selp.Hash() @@ -1314,9 +1332,9 @@ func (core *coreService) reverseActionsInBlock(blk *block.Block, reverseStart, c log.Logger("api").Debug("Skipping action due to hash error", zap.Error(err)) continue } - receipt, err := core.dao.GetReceiptByActionHash(actHash, blkHeight) - if err != nil { - log.Logger("api").Debug("Skipping action due to failing to get receipt", zap.Error(err)) + receipt, ok := receiptMap[actHash] + if !ok { + log.Logger("api").With(zap.String("actionHash", hex.EncodeToString(actHash[:]))).Debug("Skipping action due to failing to get receipt") continue } gas := new(big.Int).Mul(selp.GasPrice(), big.NewInt(int64(receipt.GasConsumed))) @@ -1819,3 +1837,12 @@ func (core *coreService) simulateExecution(ctx context.Context, addr address.Add }) return core.sf.SimulateExecution(ctx, addr, exec) } + +func filterReceipts(receipts []*action.Receipt, actHash hash.Hash256) *action.Receipt { + for _, r := range receipts { + if r.ActionHash == actHash { + return r + } + } + return nil +} diff --git a/api/grpcserver_integrity_test.go b/api/grpcserver_integrity_test.go index ae19fb3c51..06092d1e9e 100644 --- a/api/grpcserver_integrity_test.go +++ b/api/grpcserver_integrity_test.go @@ -1470,7 +1470,9 @@ func TestGrpcServer_ReadContractIntegrity(t *testing.T) { require.NoError(err) ai, err := indexer.GetActionIndex(hash[:]) require.NoError(err) - exec, _, err := dao.GetActionByActionHash(hash, ai.BlockHeight()) + blk, err := dao.GetBlockByHeight(ai.BlockHeight()) + require.NoError(err) + exec, _, err := blk.ActionByHash(hash) require.NoError(err) request := &iotexapi.ReadContractRequest{ Execution: exec.Proto().GetCore().GetExecution(), @@ -1522,7 +1524,9 @@ func TestGrpcServer_EstimateGasForActionIntegrity(t *testing.T) { require.NoError(err) ai, err := indexer.GetActionIndex(hash[:]) require.NoError(err) - act, _, err := dao.GetActionByActionHash(hash, ai.BlockHeight()) + blk, err := dao.GetBlockByHeight(ai.BlockHeight()) + require.NoError(err) + act, _, err := blk.ActionByHash(hash) require.NoError(err) request := &iotexapi.EstimateGasForActionRequest{Action: act.Proto()} diff --git a/api/serverV2_integrity_test.go b/api/serverV2_integrity_test.go index 589966709a..8994d9b664 100644 --- a/api/serverV2_integrity_test.go +++ b/api/serverV2_integrity_test.go @@ -31,6 +31,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/blockindex" "github.com/iotexproject/iotex-core/consensus" @@ -225,6 +226,10 @@ func deployContractV2(bc blockchain.Blockchain, dao blockdao.BlockDAO, actPool a if err != nil { return "", err } + h1, err := ex1.Hash() + if err != nil { + return "", err + } if err := actPool.Add(context.Background(), ex1); err != nil { return "", err } @@ -237,19 +242,12 @@ func deployContractV2(bc blockchain.Blockchain, dao blockdao.BlockDAO, actPool a } actPool.Reset() // get deployed contract address - var contract string - if dao != nil { - ex1Hash, err := ex1.Hash() - if err != nil { - return "", err + for _, receipt := range blk.Receipts { + if receipt.ActionHash == h1 { + return receipt.ContractAddress, nil } - r, err := dao.GetReceiptByActionHash(ex1Hash, height+1) - if err != nil { - return "", err - } - contract = r.ContractAddress } - return contract, nil + return "", errors.New("failed to find execution receipt") } func addActsToActPool(ctx context.Context, ap actpool.ActPool) error { @@ -313,7 +311,11 @@ func setupChain(cfg testConfig) (blockchain.Blockchain, blockdao.BlockDAO, block return nil, nil, nil, nil, nil, nil, nil, "", errors.New("failed to create bloomfilter indexer") } // create BlockDAO - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf, indexer, bfIndexer}) + store, err := filedao.NewFileDAOInMemForTest() + if err != nil { + return nil, nil, nil, nil, nil, nil, nil, "", errors.Wrap(err, "failed to create dao in memory") + } + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf, indexer, bfIndexer}, 16) if dao == nil { return nil, nil, nil, nil, nil, nil, nil, "", errors.New("failed to create blockdao") } diff --git a/blockchain/block/block.go b/blockchain/block/block.go index 17f0d5fc6e..d037f907ea 100644 --- a/blockchain/block/block.go +++ b/blockchain/block/block.go @@ -8,6 +8,7 @@ package block import ( "time" + "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/pkg/errors" "go.uber.org/zap" @@ -95,3 +96,17 @@ func (b *Block) TransactionLog() *BlkTransactionLog { } return &blkLog } + +// ActionByHash returns the action of a given hash +func (b *Block) ActionByHash(h hash.Hash256) (*action.SealedEnvelope, uint32, error) { + for i, act := range b.Actions { + actHash, err := act.Hash() + if err != nil { + return nil, 0, errors.Errorf("hash failed for action %d", i) + } + if actHash == h { + return act, uint32(i), nil + } + } + return nil, 0, errors.Errorf("block does not have action %x", h) +} diff --git a/blockchain/blockdao/blockdao.go b/blockchain/blockdao/blockdao.go index 7d55e18f86..79eaedd366 100644 --- a/blockchain/blockdao/blockdao.go +++ b/blockchain/blockdao/blockdao.go @@ -19,8 +19,6 @@ import ( "github.com/iotexproject/iotex-core/action" "github.com/iotexproject/iotex-core/blockchain/block" - "github.com/iotexproject/iotex-core/blockchain/filedao" - "github.com/iotexproject/iotex-core/db" "github.com/iotexproject/iotex-core/pkg/lifecycle" "github.com/iotexproject/iotex-core/pkg/log" "github.com/iotexproject/iotex-core/pkg/prometheustimer" @@ -40,14 +38,24 @@ var ( type ( // BlockDAO represents the block data access object BlockDAO interface { - filedao.FileDAO - GetActionByActionHash(hash.Hash256, uint64) (*action.SealedEnvelope, uint32, error) - GetReceiptByActionHash(hash.Hash256, uint64) (*action.Receipt, error) - DeleteBlockToTarget(uint64) error + Start(ctx context.Context) error + Stop(ctx context.Context) error + Height() (uint64, error) + GetBlockHash(uint64) (hash.Hash256, error) + GetBlockHeight(hash.Hash256) (uint64, error) + GetBlock(hash.Hash256) (*block.Block, error) + GetBlockByHeight(uint64) (*block.Block, error) + GetReceipts(uint64) ([]*action.Receipt, error) + ContainsTransactionLog() bool + TransactionLogs(uint64) (*iotextypes.TransactionLogs, error) + PutBlock(context.Context, *block.Block) error + Header(hash.Hash256) (*block.Header, error) + HeaderByHeight(uint64) (*block.Header, error) + FooterByHeight(uint64) (*block.Footer, error) } blockDAO struct { - blockStore filedao.FileDAO + blockStore BlockDAO indexers []BlockIndexer timerFactory *prometheustimer.TimerFactory lifecycle lifecycle.Lifecycle @@ -58,23 +66,38 @@ type ( } ) -// NewBlockDAO instantiates a block DAO -func NewBlockDAO(indexers []BlockIndexer, cfg db.Config, deser *block.Deserializer) BlockDAO { - blkStore, err := filedao.NewFileDAO(cfg, deser) - if err != nil { - log.L().Fatal(err.Error(), zap.Any("cfg", cfg)) +// NewBlockDAOWithIndexersAndCache returns a BlockDAO with indexers which will consume blocks appended, and +// caches which will speed up reading +func NewBlockDAOWithIndexersAndCache(blkStore BlockDAO, indexers []BlockIndexer, cacheSize int) BlockDAO { + if blkStore == nil { return nil } - return createBlockDAO(blkStore, indexers, cfg) -} -// NewBlockDAOInMemForTest creates a in-memory block DAO for testing -func NewBlockDAOInMemForTest(indexers []BlockIndexer) BlockDAO { - blkStore, err := filedao.NewFileDAOInMemForTest() + blockDAO := &blockDAO{ + blockStore: blkStore, + indexers: indexers, + } + + blockDAO.lifecycle.Add(blkStore) + for _, indexer := range indexers { + blockDAO.lifecycle.Add(indexer) + } + if cacheSize > 0 { + blockDAO.headerCache = cache.NewThreadSafeLruCache(cacheSize) + blockDAO.bodyCache = cache.NewThreadSafeLruCache(cacheSize) + blockDAO.footerCache = cache.NewThreadSafeLruCache(cacheSize) + } + timerFactory, err := prometheustimer.New( + "iotex_block_dao_perf", + "Performance of block DAO", + []string{"type"}, + []string{"default"}, + ) if err != nil { return nil } - return createBlockDAO(blkStore, indexers, db.Config{MaxCacheSize: 16}) + blockDAO.timerFactory = timerFactory + return blockDAO } // Start starts block DAO and initiates the top height if it doesn't exist @@ -192,36 +215,6 @@ func (dao *blockDAO) Header(h hash.Hash256) (*block.Header, error) { return header, nil } -func (dao *blockDAO) GetActionByActionHash(h hash.Hash256, height uint64) (*action.SealedEnvelope, uint32, error) { - blk, err := dao.blockStore.GetBlockByHeight(height) - if err != nil { - return nil, 0, err - } - for i, act := range blk.Actions { - actHash, err := act.Hash() - if err != nil { - return nil, 0, errors.Errorf("hash failed for block %d", height) - } - if actHash == h { - return act, uint32(i), nil - } - } - return nil, 0, errors.Errorf("block %d does not have action %x", height, h) -} - -func (dao *blockDAO) GetReceiptByActionHash(h hash.Hash256, height uint64) (*action.Receipt, error) { - receipts, err := dao.blockStore.GetReceipts(height) - if err != nil { - return nil, err - } - for _, r := range receipts { - if r.ActionHash == h { - return r, nil - } - } - return nil, errors.Errorf("receipt of action %x isn't found", h) -} - func (dao *blockDAO) GetReceipts(height uint64) ([]*action.Receipt, error) { timer := dao.timerFactory.NewTimer("get_receipt") defer timer.End() @@ -261,80 +254,6 @@ func (dao *blockDAO) PutBlock(ctx context.Context, blk *block.Block) error { return nil } -func (dao *blockDAO) DeleteTipBlock() error { - timer := dao.timerFactory.NewTimer("del_block") - defer timer.End() - return dao.blockStore.DeleteTipBlock() -} - -func (dao *blockDAO) DeleteBlockToTarget(targetHeight uint64) error { - tipHeight, err := dao.blockStore.Height() - if err != nil { - return err - } - ctx := context.Background() - for tipHeight > targetHeight { - blk, err := dao.blockStore.GetBlockByHeight(tipHeight) - if err != nil { - return errors.Wrap(err, "failed to get tip block") - } - // delete block index if there's indexer - for _, indexer := range dao.indexers { - if err := indexer.DeleteTipBlock(ctx, blk); err != nil { - return err - } - } - - if err := dao.blockStore.DeleteTipBlock(); err != nil { - return err - } - // purge from cache - h := blk.HashBlock() - lruCacheDel(dao.headerCache, tipHeight) - lruCacheDel(dao.headerCache, h) - lruCacheDel(dao.bodyCache, tipHeight) - lruCacheDel(dao.bodyCache, h) - lruCacheDel(dao.footerCache, tipHeight) - lruCacheDel(dao.footerCache, h) - - tipHeight-- - atomic.StoreUint64(&dao.tipHeight, tipHeight) - } - return nil -} - -func createBlockDAO(blkStore filedao.FileDAO, indexers []BlockIndexer, cfg db.Config) BlockDAO { - if blkStore == nil { - return nil - } - - blockDAO := &blockDAO{ - blockStore: blkStore, - indexers: indexers, - } - - blockDAO.lifecycle.Add(blkStore) - for _, indexer := range indexers { - blockDAO.lifecycle.Add(indexer) - } - if cfg.MaxCacheSize > 0 { - blockDAO.headerCache = cache.NewThreadSafeLruCache(cfg.MaxCacheSize) - blockDAO.bodyCache = cache.NewThreadSafeLruCache(cfg.MaxCacheSize) - blockDAO.footerCache = cache.NewThreadSafeLruCache(cfg.MaxCacheSize) - } - timerFactory, err := prometheustimer.New( - "iotex_block_dao_perf", - "Performance of block DAO", - []string{"type"}, - []string{"default"}, - ) - if err != nil { - return nil - } - blockDAO.timerFactory = timerFactory - return blockDAO -} - func lruCacheGet(c cache.LRUCache, key interface{}) (interface{}, bool) { if c != nil { return c.Get(key) @@ -347,9 +266,3 @@ func lruCachePut(c cache.LRUCache, k, v interface{}) { c.Add(k, v) } } - -func lruCacheDel(c cache.LRUCache, k interface{}) { - if c != nil { - c.Remove(k) - } -} diff --git a/blockchain/blockdao/blockdao_test.go b/blockchain/blockdao/blockdao_test.go index 9648bd8db8..a6c1c57072 100644 --- a/blockchain/blockdao/blockdao_test.go +++ b/blockchain/blockdao/blockdao_test.go @@ -84,6 +84,9 @@ func getTestBlocks(t *testing.T) []*block.Block { return []*block.Block{&blk1, &blk2, &blk3} } +// TODO: Move the test to filedao. The test is not for BlockDAO, but filedao. +// The current blockDAO's implementation is more about indexers and cache, which +// are not covered in the unit tests. func TestBlockDAO(t *testing.T) { require := require.New(t) @@ -273,21 +276,21 @@ func TestBlockDAO(t *testing.T) { for i, v := range daoTests[0].hashTotal { blk := blks[i/3] h := hash.BytesToHash256(v) - receipt, err := dao.GetReceiptByActionHash(h, blk.Height()) + receipt, err := receiptByActionHash(receipts[i/3], h) require.NoError(err) b1, err := receipt.Serialize() require.NoError(err) b2, err := receipts[i/3][i%3].Serialize() require.NoError(err) require.Equal(b1, b2) - action, actIndex, err := dao.GetActionByActionHash(h, blk.Height()) + action, actIndex, err := blk.ActionByHash(h) require.NoError(err) require.Equal(int(actIndex), i%3) require.Equal(blk.Actions[i%3], action) } } - testDeleteDao := func(dao BlockDAO, t *testing.T) { + testDeleteDao := func(dao filedao.FileDAO, t *testing.T) { ctx := protocol.WithBlockchainCtx( genesis.WithGenesisContext(context.Background(), genesis.Default), protocol.BlockchainCtx{ @@ -315,7 +318,14 @@ func TestBlockDAO(t *testing.T) { require.NoError(err) prevTipHash, err := dao.GetBlockHash(prevTipHeight) require.NoError(err) - require.NoError(dao.DeleteBlockToTarget(prevTipHeight - 1)) + for { + height, err := dao.Height() + require.NoError(err) + if height <= prevTipHeight-1 { + break + } + require.NoError(dao.DeleteTipBlock()) + } tipHeight, err := dao.Height() require.NoError(err) require.EqualValues(prevTipHeight-1, tipHeight) @@ -378,14 +388,14 @@ func TestBlockDAO(t *testing.T) { for i, v := range action.hashTotal { blk := blks[i/3] h := hash.BytesToHash256(v) - receipt, err := dao.GetReceiptByActionHash(h, blk.Height()) + receipt, err := receiptByActionHash(receipts[i/3], h) require.NoError(err) b1, err := receipt.Serialize() require.NoError(err) b2, err := receipts[i/3][i%3].Serialize() require.NoError(err) require.Equal(b1, b2) - action, actIndex, err := dao.GetActionByActionHash(h, blk.Height()) + action, actIndex, err := blk.ActionByHash(h) require.NoError(err) require.Equal(int(actIndex), i%3) require.Equal(blk.Actions[i%3], action) @@ -417,7 +427,7 @@ func TestBlockDAO(t *testing.T) { block.LoadGenesisHash(&genesis.Default) for _, v := range daoList { testutil.CleanupPath(testPath) - dao, err := createTestBlockDAO(v.inMemory, v.legacy, v.compressBlock, cfg) + dao, err := createFileDAO(v.inMemory, v.legacy, v.compressBlock, cfg) require.NoError(err) require.NotNil(dao) t.Run("test store blocks", func(t *testing.T) { @@ -427,7 +437,7 @@ func TestBlockDAO(t *testing.T) { for _, v := range daoList { testutil.CleanupPath(testPath) - dao, err := createTestBlockDAO(v.inMemory, v.legacy, v.compressBlock, cfg) + dao, err := createFileDAO(v.inMemory, v.legacy, v.compressBlock, cfg) require.NoError(err) require.NotNil(dao) t.Run("test delete blocks", func(t *testing.T) { @@ -436,21 +446,17 @@ func TestBlockDAO(t *testing.T) { } } -func createTestBlockDAO(inMemory, legacy bool, compressBlock string, cfg db.Config) (BlockDAO, error) { +func createFileDAO(inMemory, legacy bool, compressBlock string, cfg db.Config) (filedao.FileDAO, error) { if inMemory { - return NewBlockDAOInMemForTest(nil), nil + return filedao.NewFileDAOInMemForTest() } deser := block.NewDeserializer(4689) if legacy { - fileDAO, err := filedao.CreateFileDAO(true, cfg, deser) - if err != nil { - return nil, err - } - return createBlockDAO(fileDAO, nil, cfg), nil + return filedao.CreateFileDAO(true, cfg, deser) } cfg.Compressor = compressBlock - return NewBlockDAO(nil, cfg, deser), nil + return filedao.NewFileDAO(cfg, deser) } func BenchmarkBlockCache(b *testing.B) { @@ -472,7 +478,9 @@ func BenchmarkBlockCache(b *testing.B) { cfg.DbPath = testPath cfg.MaxCacheSize = cacheSize deser := block.NewDeserializer(4689) - blkDao := NewBlockDAO([]BlockIndexer{}, cfg, deser) + fileDAO, err := filedao.NewFileDAO(cfg, deser) + require.NoError(b, err) + blkDao := NewBlockDAOWithIndexersAndCache(fileDAO, []BlockIndexer{}, cfg.MaxCacheSize) require.NoError(b, blkDao.Start(context.Background())) defer func() { require.NoError(b, blkDao.Stop(context.Background())) @@ -514,3 +522,12 @@ func BenchmarkBlockCache(b *testing.B) { test(0, b) }) } + +func receiptByActionHash(receipts []*action.Receipt, h hash.Hash256) (*action.Receipt, error) { + for _, r := range receipts { + if r.ActionHash == h { + return r, nil + } + } + return nil, errors.Errorf("receipt of action %x isn't found", h) +} diff --git a/blockchain/integrity/benchmark_test.go b/blockchain/integrity/benchmark_test.go index 7fb235c27c..48cac0954b 100644 --- a/blockchain/integrity/benchmark_test.go +++ b/blockchain/integrity/benchmark_test.go @@ -8,12 +8,12 @@ package integrity import ( "context" "encoding/hex" - "errors" "math/big" "math/rand" "testing" "time" + "github.com/pkg/errors" "github.com/stretchr/testify/require" ethCrypto "github.com/iotexproject/go-pkgs/crypto" @@ -30,6 +30,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/blockindex" "github.com/iotexproject/iotex-core/config" @@ -260,7 +261,11 @@ func newChainInDB() (blockchain.Blockchain, actpool.ActPool, error) { // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) - dao := blockdao.NewBlockDAO(indexers, cfg.DB, deser) + store, err := filedao.NewFileDAO(cfg.DB, deser) + if err != nil { + return nil, nil, err + } + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, indexers, cfg.DB.MaxCacheSize) if dao == nil { return nil, nil, errors.New("pointer is nil") } @@ -340,11 +345,17 @@ func newChainInDB() (blockchain.Blockchain, actpool.ActPool, error) { if err != nil { return nil, nil, err } - r, err := dao.GetReceiptByActionHash(ex1Hash, 1) - if err != nil { - return nil, nil, err + var receipt *action.Receipt + for _, r := range blk.Receipts { + if r.ActionHash == ex1Hash { + receipt = r + break + } + } + if receipt == nil { + return nil, nil, errors.Errorf("failed to find receipt for %x", ex1Hash) } - _contractAddr = r.ContractAddress + _contractAddr = receipt.ContractAddress return bc, ap, nil } diff --git a/blockchain/integrity/integrity_test.go b/blockchain/integrity/integrity_test.go index c2c3d6f972..b071162ad7 100644 --- a/blockchain/integrity/integrity_test.go +++ b/blockchain/integrity/integrity_test.go @@ -38,6 +38,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/blockindex" "github.com/iotexproject/iotex-core/config" @@ -103,7 +104,7 @@ func addTestingConstantinopleBlocks(bc blockchain.Blockchain, dao blockdao.Block // get deployed contract address var contract string if dao != nil { - r, err := dao.GetReceiptByActionHash(_deployHash, 1) + r, err := receiptByActionHash(dao, 1, _deployHash) if err != nil { return err } @@ -208,7 +209,7 @@ func addTestingConstantinopleBlocks(bc blockchain.Blockchain, dao blockdao.Block } if dao != nil { - r, err := dao.GetReceiptByActionHash(_storeHash, 8) + r, err := receiptByActionHash(dao, 8, _storeHash) if err != nil { return err } @@ -230,7 +231,7 @@ func addTestingConstantinopleBlocks(bc blockchain.Blockchain, dao blockdao.Block } if dao != nil { - r, err := dao.GetReceiptByActionHash(_store2Hash, 9) + r, err := receiptByActionHash(dao, 9, _store2Hash) if err != nil { return err } @@ -341,7 +342,7 @@ func addTestingTsfBlocks(cfg config.Config, bc blockchain.Blockchain, dao blockd var contract string _, gateway := cfg.Plugins[config.GatewayPlugin] if gateway && !cfg.Chain.EnableAsyncIndexWrite { - r, err := dao.GetReceiptByActionHash(_deployHash, 2) + r, err := receiptByActionHash(dao, 2, _deployHash) if err != nil { return err } @@ -487,7 +488,9 @@ func TestCreateBlockchain(t *testing.T) { require.NoError(err) ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) bc := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -540,7 +543,9 @@ func TestGetBlockHash(t *testing.T) { require.NoError(err) ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) bc := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -601,7 +606,7 @@ func addTestingGetBlockHash(t *testing.T, g genesis.Genesis, bc blockchain.Block // get deployed contract address var contract string if dao != nil { - r, err := dao.GetReceiptByActionHash(_deployHash, 1) + r, err := receiptByActionHash(dao, 1, _deployHash) require.NoError(err) contract = r.ContractAddress } @@ -664,7 +669,7 @@ func addTestingGetBlockHash(t *testing.T, g genesis.Genesis, bc blockchain.Block for _, test := range tests { h, err := addOneBlock(contract, nonce, zero, gasLimit, gasPrice, getBlockHashCallData(int64(test.getHashHeight))) require.NoError(err) - r, err := dao.GetReceiptByActionHash(h, test.commitHeight) + r, err := receiptByActionHash(dao, test.commitHeight, h) require.NoError(err) if test.getHashHeight >= test.commitHeight { bcHash = hash.ZeroHash256 @@ -703,7 +708,9 @@ func TestBlockchain_MintNewBlock(t *testing.T) { require.NoError(t, err) ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(t, err) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(t, err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) bc := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -777,7 +784,9 @@ func TestBlockchain_MintNewBlock_PopAccount(t *testing.T) { require.NoError(t, err) ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(t, err) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(t, err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) bc := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -894,14 +903,25 @@ func createChain(cfg config.Config, inMem bool) (blockchain.Blockchain, factory. if err != nil { return nil, nil, nil, nil, err } + var store blockdao.BlockDAO // create BlockDAO if inMem { - dao = blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf, indexer}) + store, err = filedao.NewFileDAOInMemForTest() + if err != nil { + return nil, nil, nil, nil, err + } } else { cfg.DB.DbPath = cfg.Chain.ChainDBPath - dao = blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf, indexer}, - cfg.DB, block.NewDeserializer(cfg.Chain.EVMNetworkID)) + store, err = filedao.NewFileDAO(cfg.DB, block.NewDeserializer(cfg.Chain.EVMNetworkID)) } + if err != nil { + return nil, nil, nil, nil, err + } + dao = blockdao.NewBlockDAOWithIndexersAndCache( + store, + []blockdao.BlockIndexer{sf, indexer}, + cfg.DB.MaxCacheSize, + ) if dao == nil { return nil, nil, nil, nil, err } @@ -1010,7 +1030,7 @@ func TestConvertCleanAddress(t *testing.T) { // get deployed contract address var r *action.Receipt if dao != nil { - r, err = dao.GetReceiptByActionHash(h, 1) + r, err = receiptByActionHash(dao, 1, h) require.NoError(err) } @@ -1115,7 +1135,7 @@ func TestConvertCleanAddress(t *testing.T) { // verify contract execution h, err = ex1.Hash() require.NoError(err) - r, err = dao.GetReceiptByActionHash(h, 2) + r, err = receiptByActionHash(dao, 2, h) require.NoError(err) require.EqualValues(iotextypes.ReceiptStatus_Success, r.Status) require.EqualValues(2, r.BlockHeight) @@ -1127,7 +1147,7 @@ func TestConvertCleanAddress(t *testing.T) { h, err = ex2.Hash() require.NoError(err) require.Equal("eddf9e61fb9d8f5111840daef55e5fde0041f5702856532cdbb5a02998033d26", hex.EncodeToString(h[:])) - r, err = dao.GetReceiptByActionHash(h, 2) + r, err = receiptByActionHash(dao, 2, h) require.NoError(err) require.EqualValues(iotextypes.ReceiptStatus_Success, r.Status) require.EqualValues(2, r.BlockHeight) @@ -1184,7 +1204,7 @@ func TestConvertCleanAddress(t *testing.T) { } // verify deterministic deployment transaction - r, err = dao2.GetReceiptByActionHash(h, 2) + r, err = receiptByActionHash(dao2, 2, h) require.NoError(err) require.EqualValues(iotextypes.ReceiptStatus_Success, r.Status) require.EqualValues(2, r.BlockHeight) @@ -1220,8 +1240,9 @@ func TestConstantinople(t *testing.T) { require.NoError(err) // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf, indexer}, cfg.DB, deser) + store, err := filedao.NewFileDAO(cfg.DB, block.NewDeserializer(cfg.Chain.EVMNetworkID)) + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf, indexer}, cfg.DB.MaxCacheSize) require.NotNil(dao) bc := blockchain.NewBlockchain( cfg.Chain, @@ -1303,7 +1324,7 @@ func TestConstantinople(t *testing.T) { ai, err := indexer.GetActionIndex(v.h[:]) require.NoError(err) require.Equal(v.height, ai.BlockHeight()) - r, err := dao.GetReceiptByActionHash(v.h, v.height) + r, err := receiptByActionHash(dao, v.height, v.h) require.NoError(err) require.NotNil(r) require.Equal(uint64(1), r.Status) @@ -1314,7 +1335,9 @@ func TestConstantinople(t *testing.T) { } else { require.Empty(r.ContractAddress) } - a, _, err := dao.GetActionByActionHash(v.h, v.height) + blk, err := dao.GetBlockByHeight(v.height) + require.NoError(err) + a, _, err := blk.ActionByHash(v.h) require.NoError(err) require.NotNil(a) aHash, err := a.Hash() @@ -1352,7 +1375,7 @@ func TestConstantinople(t *testing.T) { } caller := identityset.Address(27) for _, v := range storeOutGasTests { - r, err := dao.GetReceiptByActionHash(v.actHash, v.height) + r, err := receiptByActionHash(dao, v.height, v.actHash) require.NoError(err) require.EqualValues(v.status, r.Status) @@ -1470,8 +1493,9 @@ func TestLoadBlockchainfromDB(t *testing.T) { cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) - dao := blockdao.NewBlockDAO(indexers, cfg.DB, deser) + store, err := filedao.NewFileDAO(cfg.DB, block.NewDeserializer(cfg.Chain.EVMNetworkID)) + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, indexers, cfg.DB.MaxCacheSize) require.NotNil(dao) bc := blockchain.NewBlockchain( cfg.Chain, @@ -1600,7 +1624,7 @@ func TestLoadBlockchainfromDB(t *testing.T) { // verify deployed contract ai, err := indexer.GetActionIndex(_deployHash[:]) require.NoError(err) - r, err := dao.GetReceiptByActionHash(_deployHash, ai.BlockHeight()) + r, err := receiptByActionHash(dao, ai.BlockHeight(), _deployHash) require.NoError(err) require.NotNil(r) require.Equal(uint64(1), r.Status) @@ -1614,7 +1638,7 @@ func TestLoadBlockchainfromDB(t *testing.T) { require.NotNil(f) require.True(f.Exist(funcSig[:])) require.True(f.Exist(_setTopic)) - r, err = dao.GetReceiptByActionHash(_setHash, 3) + r, err = receiptByActionHash(dao, 3, _setHash) require.NoError(err) require.EqualValues(1, r.Status) require.EqualValues(3, r.BlockHeight) @@ -1629,7 +1653,7 @@ func TestLoadBlockchainfromDB(t *testing.T) { require.True(f.Exist(funcSig[:])) require.True(f.Exist(_setTopic)) require.True(f.Exist(_getTopic)) - r, err = dao.GetReceiptByActionHash(_sarHash, 4) + r, err = receiptByActionHash(dao, 4, _sarHash) require.NoError(err) require.EqualValues(1, r.Status) require.EqualValues(4, r.BlockHeight) @@ -1778,8 +1802,9 @@ func TestBlockchainInitialCandidate(t *testing.T) { require.NoError(accountProtocol.Register(registry)) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath - deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg, deser) + store, err := filedao.NewFileDAO(dbcfg, block.NewDeserializer(cfg.Chain.EVMNetworkID)) + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, dbcfg.MaxCacheSize) bc := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -1823,7 +1848,9 @@ func TestBlockchain_AccountState(t *testing.T) { require.NoError(err) ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap)) require.NoError(bc.Start(ctx)) require.NotNil(bc) @@ -1852,7 +1879,9 @@ func TestNewAccountAction(t *testing.T) { require.NoError(err) ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap)) require.NoError(bc.Start(ctx)) require.NotNil(bc) @@ -1895,7 +1924,9 @@ func TestNewAccountAction(t *testing.T) { factoryCfg = factory.GenerateConfig(cfg.Chain, cfg.Genesis) sf1, err := factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry)) require.NoError(err) - dao1 := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf1}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao1 := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf1}, cfg.DB.MaxCacheSize) bc1 := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao1, factory.NewMinter(sf1, ap)) require.NoError(bc1.Start(ctx)) require.NotNil(bc1) @@ -1959,8 +1990,9 @@ func TestBlocks(t *testing.T) { require.NoError(err) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath - deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg, deser) + store, err := filedao.NewFileDAO(dbcfg, block.NewDeserializer(cfg.Chain.EVMNetworkID)) + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, dbcfg.MaxCacheSize) // Create a blockchain from scratch bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap)) @@ -2032,8 +2064,9 @@ func TestActions(t *testing.T) { require.NoError(err) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath - deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg, deser) + store, err := filedao.NewFileDAO(dbcfg, block.NewDeserializer(cfg.Chain.EVMNetworkID)) + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, dbcfg.MaxCacheSize) // Create a blockchain from scratch bc := blockchain.NewBlockchain( cfg.Chain, @@ -2095,7 +2128,9 @@ func TestBlockchain_AddRemoveSubscriber(t *testing.T) { req.NoError(err) ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) req.NoError(err) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + req.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) bc := blockchain.NewBlockchain(cfg.Chain, cfg.Genesis, dao, factory.NewMinter(sf, ap)) // mock ctrl := gomock.NewController(t) @@ -2233,7 +2268,7 @@ func deployXrc20(bc blockchain.Blockchain, dao blockdao.BlockDAO, ap actpool.Act require.NoError(bc.CommitBlock(blk)) selpHash, err := selp.Hash() require.NoError(err) - r, err := dao.GetReceiptByActionHash(selpHash, blk.Height()) + r, err := receiptByActionHash(dao, blk.Height(), selpHash) require.NoError(err) return r.ContractAddress } @@ -2323,8 +2358,9 @@ func newChain(t *testing.T, stateTX bool) (blockchain.Blockchain, factory.Factor cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) - dao := blockdao.NewBlockDAO(indexers, cfg.DB, deser) + store, err := filedao.NewFileDAO(cfg.DB, block.NewDeserializer(cfg.Chain.EVMNetworkID)) + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, indexers, cfg.DB.MaxCacheSize) require.NotNil(dao) bc := blockchain.NewBlockchain( cfg.Chain, @@ -2395,4 +2431,17 @@ func classifyActions(actions []*action.SealedEnvelope) ([]*action.Transfer, []*a return tsfs, exes } +func receiptByActionHash(dao blockdao.BlockDAO, height uint64, h hash.Hash256) (*action.Receipt, error) { + receipts, err := dao.GetReceipts(height) + if err != nil { + return nil, err + } + for _, receipt := range receipts { + if receipt.ActionHash == h { + return receipt, nil + } + } + return nil, errors.Errorf("failed to find receipt for %x", h) +} + // TODO: add func TestValidateBlock() diff --git a/blockindex/indexbuilder_test.go b/blockindex/indexbuilder_test.go index 19b1d4c513..a4956edd2d 100644 --- a/blockindex/indexbuilder_test.go +++ b/blockindex/indexbuilder_test.go @@ -15,6 +15,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/db" "github.com/iotexproject/iotex-core/test/identityset" @@ -161,16 +162,19 @@ func TestIndexBuilder(t *testing.T) { }() cfg := db.DefaultConfig cfg.DbPath = testPath - deser := block.NewDeserializer(blockchain.DefaultConfig.EVMNetworkID) + filestore, err := filedao.NewFileDAO(cfg, block.NewDeserializer(blockchain.DefaultConfig.EVMNetworkID)) + require.NoError(err) + memstore, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) for _, v := range []struct { dao blockdao.BlockDAO inMem bool }{ { - blockdao.NewBlockDAOInMemForTest(nil), true, + memstore, true, }, { - blockdao.NewBlockDAO(nil, cfg, deser), false, + filestore, false, }, } { t.Run("test indexbuilder", func(t *testing.T) { diff --git a/blocksync/blocksync_test.go b/blocksync/blocksync_test.go index 2a7a73e5ef..903a4cf535 100644 --- a/blocksync/blocksync_test.go +++ b/blocksync/blocksync_test.go @@ -27,6 +27,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/consensus" "github.com/iotexproject/iotex-core/db" @@ -200,7 +201,9 @@ func TestBlockSyncerProcessBlockTipHeight(t *testing.T) { require.NotNil(ap) require.NoError(err) ap.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, 16) chain := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -264,7 +267,9 @@ func TestBlockSyncerProcessBlockOutOfOrder(t *testing.T) { require.NotNil(ap1) require.NoError(err) ap1.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, 16) chain1 := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -289,7 +294,9 @@ func TestBlockSyncerProcessBlockOutOfOrder(t *testing.T) { require.NotNil(ap2) require.NoError(err) ap2.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf2, accountutil.AccountState)) - dao2 := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf2}) + store2, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao2 := blockdao.NewBlockDAOWithIndexersAndCache(store2, []blockdao.BlockIndexer{sf2}, 16) chain2 := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -362,7 +369,9 @@ func TestBlockSyncerProcessBlock(t *testing.T) { require.NotNil(ap1) require.NoError(err) ap1.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, 16) chain1 := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -386,7 +395,9 @@ func TestBlockSyncerProcessBlock(t *testing.T) { require.NotNil(ap2) require.NoError(err) ap2.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf2, accountutil.AccountState)) - dao2 := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf2}) + store2, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao2 := blockdao.NewBlockDAOWithIndexersAndCache(store2, []blockdao.BlockIndexer{sf2}, 16) chain2 := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -452,7 +463,9 @@ func TestBlockSyncerSync(t *testing.T) { require.NotNil(ap) require.NoError(err) ap.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, 16) chain := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, diff --git a/blocksync/buffer_test.go b/blocksync/buffer_test.go index 9938a8eeb4..7ce7ceaf66 100644 --- a/blocksync/buffer_test.go +++ b/blocksync/buffer_test.go @@ -23,6 +23,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/db" "github.com/iotexproject/iotex-core/state/factory" "github.com/iotexproject/iotex-core/test/identityset" @@ -47,7 +48,9 @@ func TestBlockBufferFlush(t *testing.T) { require.NotNil(ap) require.NoError(err) ap.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, 16) chain := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -139,7 +142,9 @@ func TestBlockBufferGetBlocksIntervalsToSync(t *testing.T) { ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NotNil(ap) require.NoError(err) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, 16) chain := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, diff --git a/chainservice/builder.go b/chainservice/builder.go index 95e3b6ce9e..88166ecb65 100644 --- a/chainservice/builder.go +++ b/chainservice/builder.go @@ -31,6 +31,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/blockindex" "github.com/iotexproject/iotex-core/blockindex/contractstaking" @@ -280,14 +281,21 @@ func (builder *Builder) buildBlockDAO(forTest bool) error { if builder.cs.bfIndexer != nil { indexers = append(indexers, builder.cs.bfIndexer) } + var ( + err error + store blockdao.BlockDAO + ) if forTest { - builder.cs.blockdao = blockdao.NewBlockDAOInMemForTest(indexers) + store, err = filedao.NewFileDAOInMemForTest() } else { dbConfig := builder.cfg.DB dbConfig.DbPath = builder.cfg.Chain.ChainDBPath - deser := block.NewDeserializer(builder.cfg.Chain.EVMNetworkID) - builder.cs.blockdao = blockdao.NewBlockDAO(indexers, dbConfig, deser) + store, err = filedao.NewFileDAO(dbConfig, block.NewDeserializer(builder.cfg.Chain.EVMNetworkID)) + } + if err != nil { + return err } + builder.cs.blockdao = blockdao.NewBlockDAOWithIndexersAndCache(store, indexers, builder.cfg.DB.MaxCacheSize) return nil } diff --git a/consensus/scheme/rolldpos/rolldpos_test.go b/consensus/scheme/rolldpos/rolldpos_test.go index a1c9a5a5aa..2246d8b49a 100644 --- a/consensus/scheme/rolldpos/rolldpos_test.go +++ b/consensus/scheme/rolldpos/rolldpos_test.go @@ -34,6 +34,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/consensus/consensusfsm" cp "github.com/iotexproject/iotex-core/crypto" @@ -461,7 +462,9 @@ func TestRollDPoSConsensus(t *testing.T) { require.NoError(t, acc.Register(registry)) rp := rolldpos.NewProtocol(g.NumCandidateDelegates, g.NumDelegates, g.NumSubEpochs) require.NoError(t, rp.Register(registry)) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(t, err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, db.DefaultConfig.MaxCacheSize) chain := blockchain.NewBlockchain( bc, g, diff --git a/consensus/scheme/rolldpos/roundcalculator_test.go b/consensus/scheme/rolldpos/roundcalculator_test.go index 04da5c0d4a..0569cee740 100644 --- a/consensus/scheme/rolldpos/roundcalculator_test.go +++ b/consensus/scheme/rolldpos/roundcalculator_test.go @@ -25,6 +25,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/db" "github.com/iotexproject/iotex-core/pkg/unit" @@ -185,8 +186,9 @@ func makeChain(t *testing.T) (blockchain.Blockchain, factory.Factory, actpool.Ac require.NoError(err) dbcfg := db.DefaultConfig dbcfg.DbPath = cfg.ChainDBPath - deser := block.NewDeserializer(cfg.EVMNetworkID) - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg, deser) + store, err := filedao.NewFileDAO(dbcfg, block.NewDeserializer(cfg.EVMNetworkID)) + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, dbcfg.MaxCacheSize) chain := blockchain.NewBlockchain( cfg, g, diff --git a/e2etest/bigint_test.go b/e2etest/bigint_test.go index 8bd5b8e1de..0903aec388 100644 --- a/e2etest/bigint_test.go +++ b/e2etest/bigint_test.go @@ -27,6 +27,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/db" @@ -98,7 +99,9 @@ func prepareBlockchain(ctx context.Context, _executor string, r *require.Asserti ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) r.NoError(err) ap.AddActionEnvelopeValidators(genericValidator) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + r.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) bc := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, diff --git a/e2etest/contract_staking_test.go b/e2etest/contract_staking_test.go index 765432680c..c560bdd784 100644 --- a/e2etest/contract_staking_test.go +++ b/e2etest/contract_staking_test.go @@ -28,6 +28,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/blockindex" "github.com/iotexproject/iotex-core/blockindex/contractstaking" @@ -1969,7 +1970,13 @@ func prepareContractStakingBlockchain(ctx context.Context, cfg config.Config, r }) r.NoError(err) // create BlockDAO - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf, indexer, contractStakeIndexer}) + store, err := filedao.NewFileDAOInMemForTest() + r.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache( + store, + []blockdao.BlockIndexer{sf, indexer, contractStakeIndexer}, + cfg.DB.MaxCacheSize, + ) r.NotNil(dao) bc := blockchain.NewBlockchain( cfg.Chain, @@ -2028,7 +2035,8 @@ func deployContracts( err = bc.CommitBlock(blk) r.NoError(err) - receipt, err := dao.GetReceiptByActionHash(selpHash, blk.Height()) + receipt := blk.Receipts[0] + r.Equal(selpHash, receipt.ActionHash) r.NoError(err) r.NotNil(receipt) r.Equal(uint64(iotextypes.ReceiptStatus_Success), receipt.Status) @@ -2094,10 +2102,14 @@ func writeContract(bc blockchain.Blockchain, err = bc.CommitBlock(blk) r.NoError(err) + receiptMap := make(map[hash.Hash256]*action.Receipt, len(blk.Receipts)) + for _, receipt := range blk.Receipts { + receiptMap[receipt.ActionHash] = receipt + } receipts := []*action.Receipt{} for _, hash := range hashes { - receipt, err := dao.GetReceiptByActionHash(hash, blk.Height()) - r.NoError(err) + receipt, ok := receiptMap[hash] + r.True(ok) receipts = append(receipts, receipt) } return receipts, blk @@ -2107,8 +2119,7 @@ func jumpBlocks(bc blockchain.Blockchain, count int, r *require.Assertions) { for i := 0; i < count; i++ { blk, err := bc.MintNewBlock(testutil.TimestampNow()) r.NoError(err) - err = bc.CommitBlock(blk) - r.NoError(err) + r.NoError(bc.CommitBlock(blk)) } } diff --git a/e2etest/local_test.go b/e2etest/local_test.go index 2bd2532b5d..de474b8bc2 100644 --- a/e2etest/local_test.go +++ b/e2etest/local_test.go @@ -30,6 +30,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/db" @@ -172,8 +173,9 @@ func TestLocalCommit(t *testing.T) { require.NoError(err) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath - deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf2}, dbcfg, deser) + store, err := filedao.NewFileDAO(dbcfg, block.NewDeserializer(cfg.Chain.EVMNetworkID)) + require.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf2}, dbcfg.MaxCacheSize) chain := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -514,13 +516,21 @@ func TestStartExistingBlockchain(t *testing.T) { // Recover to height 3 from empty state DB cfg.DB.DbPath = cfg.Chain.ChainDBPath deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) - dao := blockdao.NewBlockDAO(nil, cfg.DB, deser) + dao, err := filedao.NewFileDAO(cfg.DB, deser) + require.NoError(err) require.NoError(dao.Start(protocol.WithBlockchainCtx( genesis.WithGenesisContext(ctx, cfg.Genesis), protocol.BlockchainCtx{ ChainID: cfg.Chain.ID, }))) - require.NoError(dao.DeleteBlockToTarget(3)) + for { + height, err := dao.Height() + require.NoError(err) + if height <= 3 { + break + } + require.NoError(dao.DeleteTipBlock()) + } require.NoError(dao.Stop(ctx)) // Build states from height 1 to 3 @@ -538,13 +548,21 @@ func TestStartExistingBlockchain(t *testing.T) { // Recover to height 2 from an existing state DB with Height 3 require.NoError(svr.Stop(ctx)) cfg.DB.DbPath = cfg.Chain.ChainDBPath - dao = blockdao.NewBlockDAO(nil, cfg.DB, deser) + dao, err = filedao.NewFileDAO(cfg.DB, deser) + require.NoError(err) require.NoError(dao.Start(protocol.WithBlockchainCtx( genesis.WithGenesisContext(ctx, cfg.Genesis), protocol.BlockchainCtx{ ChainID: cfg.Chain.ID, }))) - require.NoError(dao.DeleteBlockToTarget(2)) + for { + height, err := dao.Height() + require.NoError(err) + if height <= 2 { + break + } + require.NoError(dao.DeleteTipBlock()) + } require.NoError(dao.Stop(ctx)) testutil.CleanupPath(testTriePath) testutil.CleanupPath(testContractStakeIndexPath) diff --git a/e2etest/local_transfer_test.go b/e2etest/local_transfer_test.go index a8869eed41..515f649290 100644 --- a/e2etest/local_transfer_test.go +++ b/e2etest/local_transfer_test.go @@ -33,6 +33,7 @@ import ( "github.com/iotexproject/iotex-core/actpool" "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/db" @@ -670,7 +671,9 @@ func TestEnforceChainID(t *testing.T) { require.NoError(err) ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) - blkMemDao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(err) + blkMemDao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) bc := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, diff --git a/e2etest/native_staking_test.go b/e2etest/native_staking_test.go index 861fb364b8..e47db46b4d 100644 --- a/e2etest/native_staking_test.go +++ b/e2etest/native_staking_test.go @@ -19,6 +19,7 @@ import ( "github.com/iotexproject/iotex-core/action/protocol/staking" "github.com/iotexproject/iotex-core/actpool" "github.com/iotexproject/iotex-core/blockchain" + "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/pkg/util/byteutil" @@ -90,7 +91,6 @@ func TestNativeStaking(t *testing.T) { bc := svr.ChainService(chainID).Blockchain() sf := svr.ChainService(chainID).StateFactory() ap := svr.ChainService(chainID).ActionPool() - dao := svr.ChainService(chainID).BlockDAO() require.NotNil(bc) prtcl, ok := svr.ChainService(chainID).Registry().Find("staking") require.True(ok) @@ -110,23 +110,33 @@ func TestNativeStaking(t *testing.T) { cand3PriKey := identityset.PrivateKey(4) fixedTime := time.Unix(cfg.Genesis.Timestamp, 0) - addOneTx := func(tx *action.SealedEnvelope, err error) (*action.SealedEnvelope, error) { + addOneTx := func(tx *action.SealedEnvelope, err error) (*action.SealedEnvelope, *action.Receipt, error) { if err != nil { - return tx, err + return tx, nil, err } if err := ap.Add(ctx, tx); err != nil { - return tx, err + return tx, nil, err } - if err := createAndCommitBlock(bc, ap, fixedTime); err != nil { - return tx, err + blk, err := createAndCommitBlock(bc, ap, fixedTime) + if err != nil { + return tx, nil, err + } + h, err := tx.Hash() + if err != nil { + return tx, nil, err + } + for _, r := range blk.Receipts { + if r.ActionHash == h { + return tx, r, nil + } } - return tx, nil + return tx, nil, errors.Errorf("failed to find receipt for %x", h) } - register1, err := addOneTx(action.SignedCandidateRegister(1, candidate1Name, cand1Addr.String(), cand1Addr.String(), + register1, r1, err := addOneTx(action.SignedCandidateRegister(1, candidate1Name, cand1Addr.String(), cand1Addr.String(), cand1Addr.String(), selfStake.String(), 91, true, nil, gasLimit, gasPrice, cand1PriKey)) require.NoError(err) - register2, err := addOneTx(action.SignedCandidateRegister(1, candidate2Name, cand2Addr.String(), cand2Addr.String(), + register2, _, err := addOneTx(action.SignedCandidateRegister(1, candidate2Name, cand2Addr.String(), cand2Addr.String(), cand2Addr.String(), selfStake.String(), 1, false, nil, gasLimit, gasPrice, cand2PriKey)) require.NoError(err) // check candidate state @@ -138,10 +148,6 @@ func TestNativeStaking(t *testing.T) { require.NoError(checkAccountState(cfg, sf, register2, true, initBalance, cand2Addr)) // get self-stake index from receipts - register1Hash, err := register1.Hash() - require.NoError(err) - r1, err := dao.GetReceiptByActionHash(register1Hash, 1) - require.NoError(err) require.EqualValues(iotextypes.ReceiptStatus_Success, r1.Status) logs := r1.Logs() require.Equal(3, len(logs[0].Topics)) @@ -156,11 +162,10 @@ func TestNativeStaking(t *testing.T) { voter2Addr := identityset.Address(3) voter2PriKey := identityset.PrivateKey(3) - cs1, err := action.SignedCreateStake(1, candidate1Name, vote.String(), 1, false, - nil, gasLimit, gasPrice, voter1PriKey) + cs1, r1, err := addOneTx(action.SignedCreateStake(1, candidate1Name, vote.String(), 1, false, + nil, gasLimit, gasPrice, voter1PriKey)) require.NoError(err) - require.NoError(ap.Add(context.Background(), cs1)) - cs2, err := addOneTx(action.SignedCreateStake(1, candidate1Name, vote.String(), 1, false, + cs2, r2, err := addOneTx(action.SignedCreateStake(1, candidate1Name, vote.String(), 1, false, nil, gasLimit, gasPrice, voter2PriKey)) require.NoError(err) @@ -173,10 +178,6 @@ func TestNativeStaking(t *testing.T) { require.NoError(checkAccountState(cfg, sf, cs2, false, initBalance, voter2Addr)) // get bucket index from receipts - cs1Hash, err := cs1.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(cs1Hash, 3) - require.NoError(err) require.EqualValues(iotextypes.ReceiptStatus_Success, r1.Status) logs = r1.Logs() require.Equal(3, len(logs[0].Topics)) @@ -184,28 +185,20 @@ func TestNativeStaking(t *testing.T) { require.Equal(hash.BytesToHash256(cand1Addr.Bytes()), logs[0].Topics[2]) voter1BucketIndex := byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:]) - cs2Hash, err := cs2.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(cs2Hash, 3) - require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_Success, r1.Status) - logs = r1.Logs() + require.EqualValues(iotextypes.ReceiptStatus_Success, r2.Status) + logs = r2.Logs() require.Equal(3, len(logs[0].Topics)) require.Equal(hash.BytesToHash256([]byte(staking.HandleCreateStake)), logs[0].Topics[0]) require.Equal(hash.BytesToHash256(cand1Addr.Bytes()), logs[0].Topics[2]) voter2BucketIndex := byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:]) // change candidate - cc, err := addOneTx(action.SignedChangeCandidate(2, candidate2Name, voter2BucketIndex, nil, + _, rc, err := addOneTx(action.SignedChangeCandidate(2, candidate2Name, voter2BucketIndex, nil, gasLimit, gasPrice, voter2PriKey)) require.NoError(err) - ccHash, err := cc.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(ccHash, 4) - require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_Success, r1.Status) - logs = r1.Logs() + require.EqualValues(iotextypes.ReceiptStatus_Success, rc.Status) + logs = rc.Logs() require.Equal(4, len(logs[0].Topics)) require.Equal(hash.BytesToHash256([]byte(staking.HandleChangeCandidate)), logs[0].Topics[0]) require.Equal(voter2BucketIndex, byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:])) @@ -219,15 +212,11 @@ func TestNativeStaking(t *testing.T) { require.NoError(checkCandidateState(sf, candidate2Name, cand2Addr.String(), selfStake, expectedVotes, cand2Addr)) // transfer stake - ts, err := addOneTx(action.SignedTransferStake(2, voter2Addr.String(), voter1BucketIndex, nil, gasLimit, gasPrice, voter1PriKey)) + _, rt, err := addOneTx(action.SignedTransferStake(2, voter2Addr.String(), voter1BucketIndex, nil, gasLimit, gasPrice, voter1PriKey)) require.NoError(err) - tsHash, err := ts.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(tsHash, 5) - require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_Success, r1.Status) - logs = r1.Logs() + require.EqualValues(iotextypes.ReceiptStatus_Success, rt.Status) + logs = rt.Logs() require.Equal(4, len(logs[0].Topics)) require.Equal(hash.BytesToHash256([]byte(staking.HandleTransferStake)), logs[0].Topics[0]) require.Equal(voter1BucketIndex, byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:])) @@ -249,15 +238,11 @@ func TestNativeStaking(t *testing.T) { require.Equal(voter1BucketIndex, bis[1]) // deposit to stake - ds, err := addOneTx(action.SignedDepositToStake(3, voter2BucketIndex, vote.String(), nil, gasLimit, gasPrice, voter2PriKey)) + ds, rd, err := addOneTx(action.SignedDepositToStake(3, voter2BucketIndex, vote.String(), nil, gasLimit, gasPrice, voter2PriKey)) require.NoError(err) - dsHash, err := ds.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(dsHash, 6) - require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_ErrInvalidBucketType, r1.Status) - logs = r1.Logs() + require.EqualValues(iotextypes.ReceiptStatus_ErrInvalidBucketType, rd.Status) + logs = rd.Logs() require.Equal(4, len(logs[0].Topics)) require.Equal(hash.BytesToHash256([]byte(staking.HandleDepositToStake)), logs[0].Topics[0]) require.Equal(voter2BucketIndex, byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:])) @@ -265,16 +250,12 @@ func TestNativeStaking(t *testing.T) { require.Equal(hash.BytesToHash256(cand2Addr.Bytes()), logs[0].Topics[3]) // restake - rs, err := addOneTx(action.SignedRestake(4, voter2BucketIndex, 1, true, nil, + _, rr, err := addOneTx(action.SignedRestake(4, voter2BucketIndex, 1, true, nil, gasLimit, gasPrice, voter2PriKey)) require.NoError(err) - rsHash, err := rs.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(rsHash, 7) - require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_Success, r1.Status) - logs = r1.Logs() + require.EqualValues(iotextypes.ReceiptStatus_Success, rr.Status) + logs = rr.Logs() require.Equal(3, len(logs[0].Topics)) require.Equal(hash.BytesToHash256([]byte(staking.HandleRestake)), logs[0].Topics[0]) require.Equal(voter2BucketIndex, byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:])) @@ -285,51 +266,53 @@ func TestNativeStaking(t *testing.T) { require.NoError(checkCandidateState(sf, candidate2Name, cand2Addr.String(), selfStake, expectedVotes, cand2Addr)) // deposit to stake again - ds, err = addOneTx(action.SignedDepositToStake(5, voter2BucketIndex, vote.String(), nil, gasLimit, gasPrice, voter2PriKey)) + ds, rd, err = addOneTx(action.SignedDepositToStake(5, voter2BucketIndex, vote.String(), nil, gasLimit, gasPrice, voter2PriKey)) require.NoError(err) // check voter account state require.NoError(checkAccountState(cfg, sf, ds, false, big.NewInt(0).Sub(initBalance, vote), voter2Addr)) // unstake voter stake - us, err := addOneTx(action.SignedReclaimStake(false, 6, voter1BucketIndex, nil, gasLimit, gasPrice, voter2PriKey)) + _, ru, err := addOneTx(action.SignedReclaimStake(false, 6, voter1BucketIndex, nil, gasLimit, gasPrice, voter2PriKey)) require.NoError(err) - usHash, err := us.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(usHash, 9) - require.NoError(err) - require.Equal(uint64(iotextypes.ReceiptStatus_ErrUnstakeBeforeMaturity), r1.Status) - logs = r1.Logs() + require.Equal(uint64(iotextypes.ReceiptStatus_ErrUnstakeBeforeMaturity), ru.Status) + logs = ru.Logs() require.Equal(3, len(logs[0].Topics)) require.Equal(hash.BytesToHash256([]byte(staking.HandleUnstake)), logs[0].Topics[0]) require.Equal(voter1BucketIndex, byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:])) require.Equal(hash.BytesToHash256(cand1Addr.Bytes()), logs[0].Topics[2]) unstakeTime := fixedTime.Add(time.Duration(1) * 24 * time.Hour) - addOneTx = func(tx *action.SealedEnvelope, err error) (*action.SealedEnvelope, error) { + addOneTx = func(tx *action.SealedEnvelope, err error) (*action.SealedEnvelope, *action.Receipt, error) { if err != nil { - return tx, err + return tx, nil, err } if err := ap.Add(ctx, tx); err != nil { - return tx, err + return tx, nil, err + } + blk, err := createAndCommitBlock(bc, ap, unstakeTime) + if err != nil { + return tx, nil, err + } + h, err := tx.Hash() + if err != nil { + return tx, nil, err } - if err := createAndCommitBlock(bc, ap, unstakeTime); err != nil { - return tx, err + for _, r := range blk.Receipts { + if r.ActionHash == h { + return tx, r, nil + } } - return tx, nil + return tx, nil, errors.Errorf("failed to find receipt for %x", h) } // unstake with correct timestamp - us, err = addOneTx(action.SignedReclaimStake(false, 7, voter1BucketIndex, nil, gasLimit, gasPrice, voter2PriKey)) + _, ru, err = addOneTx(action.SignedReclaimStake(false, 7, voter1BucketIndex, nil, gasLimit, gasPrice, voter2PriKey)) require.NoError(err) - usHash, err = us.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(usHash, 10) - require.NoError(err) - require.Equal(uint64(iotextypes.ReceiptStatus_Success), r1.Status) - logs = r1.Logs() + require.Equal(uint64(iotextypes.ReceiptStatus_Success), ru.Status) + logs = ru.Logs() require.Equal(3, len(logs[0].Topics)) require.Equal(hash.BytesToHash256([]byte(staking.HandleUnstake)), logs[0].Topics[0]) require.Equal(voter1BucketIndex, byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:])) @@ -339,15 +322,11 @@ func TestNativeStaking(t *testing.T) { require.NoError(checkCandidateState(sf, candidate1Name, cand1Addr.String(), selfStake, cand1Votes, cand1Addr)) // unstake self stake - us, err = addOneTx(action.SignedReclaimStake(false, 2, selfstakeIndex1, nil, gasLimit, gasPrice, cand1PriKey)) + _, ru, err = addOneTx(action.SignedReclaimStake(false, 2, selfstakeIndex1, nil, gasLimit, gasPrice, cand1PriKey)) require.NoError(err) - usHash, err = us.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(usHash, 11) - require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_ErrInvalidBucketType, r1.Status) - logs = r1.Logs() + require.EqualValues(iotextypes.ReceiptStatus_ErrInvalidBucketType, ru.Status) + logs = ru.Logs() require.Equal(3, len(logs[0].Topics)) require.Equal(hash.BytesToHash256([]byte(staking.HandleUnstake)), logs[0].Topics[0]) require.Equal(selfstakeIndex1, byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:])) @@ -357,15 +336,11 @@ func TestNativeStaking(t *testing.T) { require.NoError(checkCandidateState(sf, candidate1Name, cand1Addr.String(), selfStake, cand1Votes, cand1Addr)) // withdraw stake - ws, err := addOneTx(action.SignedReclaimStake(true, 3, selfstakeIndex1, nil, gasLimit, gasPrice, cand1PriKey)) + ws, rw, err := addOneTx(action.SignedReclaimStake(true, 3, selfstakeIndex1, nil, gasLimit, gasPrice, cand1PriKey)) require.NoError(err) - wsHash, err := ws.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(wsHash, 12) - require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_ErrWithdrawBeforeUnstake, r1.Status) - logs = r1.Logs() + require.EqualValues(iotextypes.ReceiptStatus_ErrWithdrawBeforeUnstake, rw.Status) + logs = rw.Logs() require.Equal(3, len(logs[0].Topics)) require.Equal(hash.BytesToHash256([]byte(staking.HandleWithdrawStake)), logs[0].Topics[0]) require.Equal(selfstakeIndex1, byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:])) @@ -373,15 +348,11 @@ func TestNativeStaking(t *testing.T) { // withdraw with correct timestamp unstakeTime = unstakeTime.Add(cfg.Genesis.WithdrawWaitingPeriod) - ws, err = addOneTx(action.SignedReclaimStake(true, 4, selfstakeIndex1, nil, gasLimit, gasPrice, cand1PriKey)) + ws, rw, err = addOneTx(action.SignedReclaimStake(true, 4, selfstakeIndex1, nil, gasLimit, gasPrice, cand1PriKey)) require.NoError(err) - wsHash, err = ws.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(wsHash, 13) - require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_ErrWithdrawBeforeUnstake, r1.Status) - logs = r1.Logs() + require.EqualValues(iotextypes.ReceiptStatus_ErrWithdrawBeforeUnstake, rw.Status) + logs = rw.Logs() require.Equal(3, len(logs[0].Topics)) require.Equal(hash.BytesToHash256([]byte(staking.HandleWithdrawStake)), logs[0].Topics[0]) require.Equal(selfstakeIndex1, byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:])) @@ -402,13 +373,9 @@ func TestNativeStaking(t *testing.T) { require.NoError(checkAccountState(cfg, sf, ws, true, big.NewInt(0).Sub(initBalance, selfStake), cand1Addr)) // register without stake - register3, err := addOneTx(action.SignedCandidateRegister(1, candidate3Name, cand3Addr.String(), cand3Addr.String(), + register3, r3, err := addOneTx(action.SignedCandidateRegister(1, candidate3Name, cand3Addr.String(), cand3Addr.String(), cand3Addr.String(), "0", 1, false, nil, gasLimit, gasPrice, cand3PriKey)) require.NoError(err) - register3Hash, err := register3.Hash() - require.NoError(err) - r3, err := dao.GetReceiptByActionHash(register3Hash, bc.TipHeight()) - require.NoError(err) require.EqualValues(iotextypes.ReceiptStatus_Success, r3.Status) require.NoError(checkCandidateState(sf, candidate3Name, cand3Addr.String(), big.NewInt(0), big.NewInt(0), cand3Addr)) require.NoError(checkAccountState(cfg, sf, register3, true, initBalance, cand3Addr)) @@ -426,35 +393,24 @@ func TestNativeStaking(t *testing.T) { t.Logf("\ncandidate=%+v, %+v\n", string(cand.CanName), cand.Votes.String()) } // stake bucket - cs3, err := addOneTx(action.SignedCreateStake(3, candidate3Name, selfStake.String(), 1, false, + _, cr3, err := addOneTx(action.SignedCreateStake(3, candidate3Name, selfStake.String(), 1, false, nil, gasLimit, gasPrice, voter1PriKey)) require.NoError(err) - cs3Hash, err := cs3.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(cs3Hash, bc.TipHeight()) - require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_Success, r1.Status) - logs = r1.Logs() + require.EqualValues(iotextypes.ReceiptStatus_Success, cr3.Status) + logs = cr3.Logs() require.Equal(3, len(logs[0].Topics)) require.Equal(hash.BytesToHash256([]byte(staking.HandleCreateStake)), logs[0].Topics[0]) endorseBucketIndex := byteutil.BytesToUint64BigEndian(logs[0].Topics[1][24:]) t.Logf("endorseBucketIndex=%+v", endorseBucketIndex) // endorse bucket - es, err := addOneTx(action.SignedCandidateEndorsement(4, endorseBucketIndex, true, gasLimit, gasPrice, voter1PriKey)) - require.NoError(err) - esHash, err := es.Hash() + _, esr, err := addOneTx(action.SignedCandidateEndorsement(4, endorseBucketIndex, true, gasLimit, gasPrice, voter1PriKey)) require.NoError(err) - r1, err = dao.GetReceiptByActionHash(esHash, bc.TipHeight()) require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_Success, r1.Status) + require.EqualValues(iotextypes.ReceiptStatus_Success, esr.Status) // candidate self stake - css, err := addOneTx(action.SignedCandidateActivate(2, endorseBucketIndex, gasLimit, gasPrice, cand3PriKey)) - require.NoError(err) - cssHash, err := css.Hash() + _, cssr, err := addOneTx(action.SignedCandidateActivate(2, endorseBucketIndex, gasLimit, gasPrice, cand3PriKey)) require.NoError(err) - r1, err = dao.GetReceiptByActionHash(cssHash, bc.TipHeight()) - require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_Success, r1.Status) + require.EqualValues(iotextypes.ReceiptStatus_Success, cssr.Status) ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{ BlockHeight: bc.TipHeight() + 1, }) @@ -466,13 +422,9 @@ func TestNativeStaking(t *testing.T) { t.Logf("\ncandidate=%+v, %+v\n", string(cand.CanName), cand.Votes.String()) } // unendorse bucket - es, err = addOneTx(action.SignedCandidateEndorsement(5, endorseBucketIndex, false, gasLimit, gasPrice, voter1PriKey)) - require.NoError(err) - esHash, err = es.Hash() - require.NoError(err) - r1, err = dao.GetReceiptByActionHash(esHash, bc.TipHeight()) + _, esr, err = addOneTx(action.SignedCandidateEndorsement(5, endorseBucketIndex, false, gasLimit, gasPrice, voter1PriKey)) require.NoError(err) - require.EqualValues(iotextypes.ReceiptStatus_Success, r1.Status) + require.EqualValues(iotextypes.ReceiptStatus_Success, esr.Status) ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{ BlockHeight: bc.TipHeight() + 1, }) @@ -601,14 +553,14 @@ func checkAccountState( return nil } -func createAndCommitBlock(bc blockchain.Blockchain, ap actpool.ActPool, blkTime time.Time) error { +func createAndCommitBlock(bc blockchain.Blockchain, ap actpool.ActPool, blkTime time.Time) (*block.Block, error) { blk, err := bc.MintNewBlock(blkTime) if err != nil { - return err + return nil, err } if err := bc.CommitBlock(blk); err != nil { - return err + return nil, err } ap.Reset() - return nil + return blk, nil } diff --git a/e2etest/sgd_registry_test.go b/e2etest/sgd_registry_test.go index 36b32f4733..5e7db30842 100644 --- a/e2etest/sgd_registry_test.go +++ b/e2etest/sgd_registry_test.go @@ -23,6 +23,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/blockindex" "github.com/iotexproject/iotex-core/config" @@ -63,7 +64,9 @@ func TestSGDRegistry(t *testing.T) { ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) r.NoError(err) ap.AddActionEnvelopeValidators(genericValidator) - dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + r.NoError(err) + dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, cfg.DB.MaxCacheSize) bc := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -97,8 +100,8 @@ func TestSGDRegistry(t *testing.T) { blk, err := bc.MintNewBlock(fixedTime) r.NoError(err) r.NoError(bc.CommitBlock(blk)) - receipt, err := dao.GetReceiptByActionHash(deployHash, 1) - r.NoError(err) + receipt := blk.Receipts[0] + r.Equal(receipt.ActionHash, deployHash) r.Equal(receipt.ContractAddress, "io1va03q4lcr608dr3nltwm64sfcz05czjuycsqgn") height, err := dao.Height() r.NoError(err) diff --git a/e2etest/staking_test.go b/e2etest/staking_test.go index 7611851840..19d3617911 100644 --- a/e2etest/staking_test.go +++ b/e2etest/staking_test.go @@ -75,8 +75,8 @@ func TestStakingContract(t *testing.T) { blk, err := bc.MintNewBlock(fixedTime) require.NoError(err) require.NoError(bc.CommitBlock(blk)) - r, err := dao.GetReceiptByActionHash(deployHash, 1) - require.NoError(err) + r := blk.Receipts[0] + require.Equal(r.ActionHash, deployHash) require.Equal(r.ContractAddress, "io1nw4l6qpph9apnzrmfk3u2dk28y5e05dpnk6nv0") // 20 voters, each create 60 buckets diff --git a/gasstation/gasstattion_test.go b/gasstation/gasstattion_test.go index 4fd4707ee7..5bf8000ed7 100644 --- a/gasstation/gasstattion_test.go +++ b/gasstation/gasstattion_test.go @@ -26,6 +26,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/db" "github.com/iotexproject/iotex-core/pkg/unit" @@ -85,7 +86,9 @@ func TestSuggestGasPriceForUserAction(t *testing.T) { require.NoError(t, err) ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(t, err) - blkMemDao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(t, err) + blkMemDao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, 16) bc := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, @@ -165,7 +168,9 @@ func TestSuggestGasPriceForSystemAction(t *testing.T) { require.NoError(t, err) ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(t, err) - blkMemDao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + store, err := filedao.NewFileDAOInMemForTest() + require.NoError(t, err) + blkMemDao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf}, 16) bc := blockchain.NewBlockchain( cfg.Chain, cfg.Genesis, diff --git a/test/mock/mock_blockdao/mock_blockdao.go b/test/mock/mock_blockdao/mock_blockdao.go index 47a86acee1..c763aca3b5 100644 --- a/test/mock/mock_blockdao/mock_blockdao.go +++ b/test/mock/mock_blockdao/mock_blockdao.go @@ -52,34 +52,6 @@ func (mr *MockBlockDAOMockRecorder) ContainsTransactionLog() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainsTransactionLog", reflect.TypeOf((*MockBlockDAO)(nil).ContainsTransactionLog)) } -// DeleteBlockToTarget mocks base method. -func (m *MockBlockDAO) DeleteBlockToTarget(arg0 uint64) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteBlockToTarget", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteBlockToTarget indicates an expected call of DeleteBlockToTarget. -func (mr *MockBlockDAOMockRecorder) DeleteBlockToTarget(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBlockToTarget", reflect.TypeOf((*MockBlockDAO)(nil).DeleteBlockToTarget), arg0) -} - -// DeleteTipBlock mocks base method. -func (m *MockBlockDAO) DeleteTipBlock() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteTipBlock") - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteTipBlock indicates an expected call of DeleteTipBlock. -func (mr *MockBlockDAOMockRecorder) DeleteTipBlock() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTipBlock", reflect.TypeOf((*MockBlockDAO)(nil).DeleteTipBlock)) -} - // FooterByHeight mocks base method. func (m *MockBlockDAO) FooterByHeight(arg0 uint64) (*block.Footer, error) { m.ctrl.T.Helper() @@ -95,22 +67,6 @@ func (mr *MockBlockDAOMockRecorder) FooterByHeight(arg0 interface{}) *gomock.Cal return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FooterByHeight", reflect.TypeOf((*MockBlockDAO)(nil).FooterByHeight), arg0) } -// GetActionByActionHash mocks base method. -func (m *MockBlockDAO) GetActionByActionHash(arg0 hash.Hash256, arg1 uint64) (*action.SealedEnvelope, uint32, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetActionByActionHash", arg0, arg1) - ret0, _ := ret[0].(*action.SealedEnvelope) - ret1, _ := ret[1].(uint32) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// GetActionByActionHash indicates an expected call of GetActionByActionHash. -func (mr *MockBlockDAOMockRecorder) GetActionByActionHash(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetActionByActionHash", reflect.TypeOf((*MockBlockDAO)(nil).GetActionByActionHash), arg0, arg1) -} - // GetBlock mocks base method. func (m *MockBlockDAO) GetBlock(arg0 hash.Hash256) (*block.Block, error) { m.ctrl.T.Helper() @@ -171,21 +127,6 @@ func (mr *MockBlockDAOMockRecorder) GetBlockHeight(arg0 interface{}) *gomock.Cal return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockHeight", reflect.TypeOf((*MockBlockDAO)(nil).GetBlockHeight), arg0) } -// GetReceiptByActionHash mocks base method. -func (m *MockBlockDAO) GetReceiptByActionHash(arg0 hash.Hash256, arg1 uint64) (*action.Receipt, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetReceiptByActionHash", arg0, arg1) - ret0, _ := ret[0].(*action.Receipt) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetReceiptByActionHash indicates an expected call of GetReceiptByActionHash. -func (mr *MockBlockDAOMockRecorder) GetReceiptByActionHash(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceiptByActionHash", reflect.TypeOf((*MockBlockDAO)(nil).GetReceiptByActionHash), arg0, arg1) -} - // GetReceipts mocks base method. func (m *MockBlockDAO) GetReceipts(arg0 uint64) ([]*action.Receipt, error) { m.ctrl.T.Helper() diff --git a/tools/iomigrater/cmds/check-height.go b/tools/iomigrater/cmds/check-height.go index aa72b4b437..c2e34228a7 100644 --- a/tools/iomigrater/cmds/check-height.go +++ b/tools/iomigrater/cmds/check-height.go @@ -8,6 +8,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/tools/iomigrater/common" ) @@ -54,8 +55,11 @@ func checkDbFileHeight(filePath string) (uint64, error) { } cfg.DB.DbPath = filePath - deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) - blockDao := blockdao.NewBlockDAO(nil, cfg.DB, deser) + store, err := filedao.NewFileDAO(cfg.DB, block.NewDeserializer(cfg.Chain.EVMNetworkID)) + if err != nil { + return uint64(0), err + } + blockDao := blockdao.NewBlockDAOWithIndexersAndCache(store, nil, cfg.DB.MaxCacheSize) // Load height value. ctx := context.Background() diff --git a/tools/iomigrater/cmds/migrate-db.go b/tools/iomigrater/cmds/migrate-db.go index 2108c4c841..3cb764e7e6 100644 --- a/tools/iomigrater/cmds/migrate-db.go +++ b/tools/iomigrater/cmds/migrate-db.go @@ -4,11 +4,12 @@ import ( "context" "fmt" + "github.com/pkg/errors" "github.com/schollz/progressbar/v2" "github.com/spf13/cobra" "github.com/iotexproject/iotex-core/blockchain/block" - "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/filedao" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/tools/iomigrater/common" ) @@ -115,10 +116,16 @@ func migrateDbFile() (err error) { cfg.DB.DbPath = oldFile deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) - oldDAO := blockdao.NewBlockDAO(nil, cfg.DB, deser) + oldDAO, err := filedao.NewFileDAO(cfg.DB, deser) + if err != nil { + return errors.Wrapf(err, "failed to create dao from %s", oldFile) + } cfg.DB.DbPath = newFile - newDAO := blockdao.NewBlockDAO(nil, cfg.DB, deser) + newDAO, err := filedao.NewFileDAO(cfg.DB, deser) + if err != nil { + return errors.Wrapf(err, "failed to create dao from %s", newFile) + } ctx := context.Background() if err := oldDAO.Start(ctx); err != nil { diff --git a/tools/staterecoverer/staterecoverer.go b/tools/staterecoverer/staterecoverer.go index ea8f28f6a7..ba3329326c 100644 --- a/tools/staterecoverer/staterecoverer.go +++ b/tools/staterecoverer/staterecoverer.go @@ -15,14 +15,12 @@ import ( "os" "strings" - "github.com/pkg/errors" "go.uber.org/zap" "github.com/iotexproject/iotex-core/blockchain/blockdao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/pkg/log" - "github.com/iotexproject/iotex-core/pkg/util/fileutil" "github.com/iotexproject/iotex-core/server/itx" "github.com/iotexproject/iotex-core/state/factory" ) @@ -109,19 +107,23 @@ func main() { // recoverChainAndState recovers the chain to target height and refresh state db if necessary func recoverChainAndState(dao blockdao.BlockDAO, sf factory.Factory, cfg config.Config, targetHeight uint64) error { - // recover the blockchain to target height(blockDAO) - if err := dao.DeleteBlockToTarget(targetHeight); err != nil { - return errors.Wrapf(err, "failed to recover blockchain to target height %d", targetHeight) - } - stateHeight, err := sf.Height() - if err != nil { - return err - } - if targetHeight < stateHeight { - // delete existing state DB (build from scratch) - if fileutil.FileExists(cfg.Chain.TrieDBPath) && os.Remove(cfg.Chain.TrieDBPath) != nil { - return errors.New("failed to delete existing state DB") + // TODO: not all indexers could be reverted, e.g., state factory. Thus, dao.DeleteTipBlockToTarget will always + // return error. Therefore, it is not hard to tell that this tool is not working. The right way is to revert indexer + // one by one. Before we implement it in that way, comment out the following code. + /* + if err := dao.DeleteBlockToTarget(targetHeight); err != nil { + return errors.Wrapf(err, "failed to recover blockchain to target height %d", targetHeight) } - } - return nil + stateHeight, err := sf.Height() + if err != nil { + return err + } + if targetHeight < stateHeight { + // delete existing state DB (build from scratch) + if fileutil.FileExists(cfg.Chain.TrieDBPath) && os.Remove(cfg.Chain.TrieDBPath) != nil { + return errors.New("failed to delete existing state DB") + } + } + */ + panic("not implemented") }