diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index a8e89a03408ec2501f12449637cfee6a094f6915..cc856603e3b95d70edb66dabcdf8901107101181 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -413,7 +413,7 @@ func copyDb(ctx *cli.Context) error { if syncMode == downloader.FastSync { //syncBloom = trie.NewSyncBloom(uint64(ctx.GlobalInt(utils.CacheFlag.Name)/2), chainDb) } - dl := downloader.New(0, chainDb, syncBloom, new(event.TypeMux), chain, nil, nil, true) + dl := downloader.New(0, chainDb, syncBloom, new(event.TypeMux), chain, nil, nil, ethdb.DefaultStorageMode) // Create a source peer to satisfy downloader requests from db, err := ethdb.NewBoltDatabase(ctx.Args().First()) diff --git a/cmd/hack/hack.go b/cmd/hack/hack.go index dc8c5dc5c8732f73138ac1d250cafe5a7eb873b8..59dd11fff63adbe8c359514ab7a86bce51aa86f3 100644 --- a/cmd/hack/hack.go +++ b/cmd/hack/hack.go @@ -2431,7 +2431,7 @@ func testStage4(chaindata string, block uint64) error { ch := make(chan struct{}) stageState := &stagedsync.StageState{Stage: stages.Execution, BlockNumber: stage4progress} blockchain, _ := core.NewBlockChain(db, nil, params.MainnetChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, nil) - if err = stagedsync.SpawnExecuteBlocksStage(stageState, db, blockchain, block, ch, nil); err != nil { + if err = stagedsync.SpawnExecuteBlocksStage(stageState, db, blockchain, block, ch, nil, false); err != nil { return err } return nil diff --git a/cmd/restapi/apis/retrace_tx_api.go b/cmd/restapi/apis/retrace_tx_api.go index d27a6cc4cc1d971807f8851fba1334a57af17a45..5be72d94d429e737f0581e19594deab941bb624d 100644 --- a/cmd/restapi/apis/retrace_tx_api.go +++ b/cmd/restapi/apis/retrace_tx_api.go @@ -127,7 +127,7 @@ func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWrit ctx := chainConfig.WithEIPsFlags(context.Background(), header.Number) if err := ibs.CommitBlock(ctx, blockWriter); err != nil { - return fmt.Errorf("commiting block %d failed: %v", block.NumberU64(), err) + return fmt.Errorf("committing block %d failed: %v", block.NumberU64(), err) } return nil } diff --git a/cmd/state/stateless/stateless.go b/cmd/state/stateless/stateless.go index 5c5cd292eea9a949156c645c68a3630d4f47b6ef..03e0ddf6c6a533b07352f8c585698dc97d2e7569 100644 --- a/cmd/state/stateless/stateless.go +++ b/cmd/state/stateless/stateless.go @@ -460,7 +460,7 @@ func Stateless( blockWriter := tds.DbStateWriter() err = statedb.CommitBlock(ctx, blockWriter) if err != nil { - fmt.Printf("Commiting block %d failed: %v", blockNum, err) + fmt.Printf("Committing block %d failed: %v", blockNum, err) return } if writeHistory { diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index a60b09bf16903f1bed648a30bf6e1bfd07e87283..9fb73b096c714b51345dcc0f17e2b3f19c1b426f 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -439,7 +439,7 @@ var ( * p - write preimages to the DB * r - write receipts to the DB * t - write tx lookup index to the DB`, - Value: eth.DefaultStorageMode.ToString(), + Value: ethdb.DefaultStorageMode.ToString(), } ArchiveSyncInterval = cli.IntFlag{ Name: "archive-sync-interval", @@ -1554,7 +1554,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { cfg.EnableDebugProtocol = ctx.GlobalBool(DebugProtocolFlag.Name) - mode, err := eth.StorageModeFromString(ctx.GlobalString(StorageModeFlag.Name)) + mode, err := ethdb.StorageModeFromString(ctx.GlobalString(StorageModeFlag.Name)) if err != nil { Fatalf(fmt.Sprintf("error while parsing mode: %v", err)) } diff --git a/common/dbutils/bucket.go b/common/dbutils/bucket.go index 1501089e753a130bb9d0f7123627aaac41d669a1..7af73b231027fbadf289bd59c1323653ceee6a36 100644 --- a/common/dbutils/bucket.go +++ b/common/dbutils/bucket.go @@ -142,8 +142,6 @@ var ( StorageModeTxIndex = []byte("smTxIndex") //StorageModePreImages - does node save hash to value mapping StorageModePreImages = []byte("smPreImages") - //StorageModeThinHistory - does thin history mode enabled - StorageModeThinHistory = []byte("smThinHistory") //StorageModeIntermediateTrieHash - does IntermediateTrieHash feature enabled StorageModeIntermediateTrieHash = []byte("smIntermediateTrieHash") @@ -192,7 +190,6 @@ var Buckets = [][]byte{ StorageModeReceipts, StorageModeTxIndex, StorageModePreImages, - StorageModeThinHistory, CliqueBucket, SyncStageProgress, SyncStageUnwind, diff --git a/core/blockchain.go b/core/blockchain.go index 60b35e191cdb801fc51ce0c7c29458854a6615ae..1caebae78c5256afe4bc2cc182fed0bfa4303b33 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2474,9 +2474,9 @@ func (bc *BlockChain) waitJobs() { bc.quitMu.Unlock() } -// ExecuteBlockEuphemerally runs a block from provided stateReader and +// ExecuteBlockEphemerally runs a block from provided stateReader and // writes the result to the provided stateWriter -func ExecuteBlockEuphemerally( +func ExecuteBlockEphemerally( chainConfig *params.ChainConfig, vmConfig *vm.Config, chainContext ChainContext, @@ -2485,7 +2485,7 @@ func ExecuteBlockEuphemerally( stateReader state.StateReader, stateWriter state.WriterWithChangeSets, dests vm.Cache, -) error { +) (types.Receipts, error) { ibs := state.New(stateReader) header := block.Header() var receipts types.Receipts @@ -2500,7 +2500,7 @@ func ExecuteBlockEuphemerally( ibs.Prepare(tx.Hash(), block.Hash(), i) receipt, err := ApplyTransaction(chainConfig, chainContext, nil, gp, ibs, noop, header, tx, usedGas, *vmConfig, dests) if err != nil { - return fmt.Errorf("tx %x failed: %v", tx.Hash(), err) + return nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err) } receipts = append(receipts, receipt) } @@ -2508,23 +2508,23 @@ func ExecuteBlockEuphemerally( if chainConfig.IsByzantium(header.Number) { receiptSha := types.DeriveSha(receipts) if receiptSha != block.Header().ReceiptHash { - return fmt.Errorf("mismatched receipt headers for block %d", block.NumberU64()) + return nil, fmt.Errorf("mismatched receipt headers for block %d", block.NumberU64()) } } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) if _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts); err != nil { - return fmt.Errorf("finalize of block %d failed: %v", block.NumberU64(), err) + return nil, fmt.Errorf("finalize of block %d failed: %v", block.NumberU64(), err) } ctx := chainConfig.WithEIPsFlags(context.Background(), header.Number) if err := ibs.CommitBlock(ctx, stateWriter); err != nil { - return fmt.Errorf("commiting block %d failed: %v", block.NumberU64(), err) + return nil, fmt.Errorf("committing block %d failed: %v", block.NumberU64(), err) } if err := stateWriter.WriteChangeSets(); err != nil { - return fmt.Errorf("writing changesets for block %d failed: %v", block.NumberU64(), err) + return nil, fmt.Errorf("writing changesets for block %d failed: %v", block.NumberU64(), err) } - return nil + return receipts, nil } diff --git a/core/state/database.go b/core/state/database.go index 2c223db69730a60e70b67c661f5109bfc2ce4869..323713abbf2c6484b7173afde712cef59064bbe6 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -1292,12 +1292,12 @@ func (tds *TrieDbState) TrieStateWriter() *TrieStateWriter { // DbStateWriter creates a writer that is designed to write changes into the database batch func (tds *TrieDbState) DbStateWriter() *DbStateWriter { - return &DbStateWriter{blockNr: tds.blockNr, stateDb: tds.db, changeDb: tds.db, pw: tds.pw, csw: NewChangeSetWriter()} + return &DbStateWriter{blockNr: tds.blockNr, db: tds.db, pw: tds.pw, csw: NewChangeSetWriter()} } // DbStateWriter creates a writer that is designed to write changes into the database batch func (tds *TrieDbState) PlainStateWriter() *PlainStateWriter { - return NewPlainStateWriter(tds.db, tds.db, tds.blockNr) + return NewPlainStateWriter(tds.db, tds.blockNr) } func (tsw *TrieStateWriter) UpdateAccountData(_ context.Context, address common.Address, original, account *accounts.Account) error { diff --git a/core/state/db_state_writer.go b/core/state/db_state_writer.go index c32fa6279493a5d604b3854d1d2629c74fc15b50..3e393b0f5c8d97c318e7472c0b4a0ee5fbc2d754 100644 --- a/core/state/db_state_writer.go +++ b/core/state/db_state_writer.go @@ -19,26 +19,24 @@ import ( var _ WriterWithChangeSets = (*DbStateWriter)(nil) -func NewDbStateWriter(stateDb, changeDb ethdb.Database, blockNr uint64) *DbStateWriter { +func NewDbStateWriter(db ethdb.Database, blockNr uint64) *DbStateWriter { return &DbStateWriter{ - stateDb: stateDb, - changeDb: changeDb, - blockNr: blockNr, - pw: &PreimageWriter{db: stateDb, savePreimages: false}, - csw: NewChangeSetWriter(), + db: db, + blockNr: blockNr, + pw: &PreimageWriter{db: db, savePreimages: false}, + csw: NewChangeSetWriter(), } } type DbStateWriter struct { - stateDb ethdb.Database - changeDb ethdb.Database - pw *PreimageWriter - blockNr uint64 - csw *ChangeSetWriter - accountCache *fastcache.Cache - storageCache *fastcache.Cache - codeCache *fastcache.Cache - codeSizeCache *fastcache.Cache + db ethdb.Database + pw *PreimageWriter + blockNr uint64 + csw *ChangeSetWriter + accountCache *fastcache.Cache + storageCache *fastcache.Cache + codeCache *fastcache.Cache + codeSizeCache *fastcache.Cache } func (dsw *DbStateWriter) SetAccountCache(accountCache *fastcache.Cache) { @@ -86,7 +84,7 @@ func (dsw *DbStateWriter) UpdateAccountData(ctx context.Context, address common. } value := make([]byte, account.EncodingLengthForStorage()) account.EncodeForStorage(value) - if err := dsw.stateDb.Put(dbutils.CurrentStateBucket, addrHash[:], value); err != nil { + if err := dsw.db.Put(dbutils.CurrentStateBucket, addrHash[:], value); err != nil { return err } if dsw.accountCache != nil { @@ -103,13 +101,13 @@ func (dsw *DbStateWriter) DeleteAccount(ctx context.Context, address common.Addr if err != nil { return err } - if err := rawdb.DeleteAccount(dsw.stateDb, addrHash); err != nil { + if err := rawdb.DeleteAccount(dsw.db, addrHash); err != nil { return err } if original.Incarnation > 0 { var b [8]byte binary.BigEndian.PutUint64(b[:], original.Incarnation) - if err := dsw.stateDb.Put(dbutils.IncarnationMapBucket, address[:], b[:]); err != nil { + if err := dsw.db.Put(dbutils.IncarnationMapBucket, address[:], b[:]); err != nil { return err } } @@ -132,7 +130,7 @@ func (dsw *DbStateWriter) UpdateAccountCode(address common.Address, incarnation return err } //save contract code mapping - if err := dsw.stateDb.Put(dbutils.CodeBucket, codeHash[:], code); err != nil { + if err := dsw.db.Put(dbutils.CodeBucket, codeHash[:], code); err != nil { return err } addrHash, err := common.HashData(address.Bytes()) @@ -140,7 +138,7 @@ func (dsw *DbStateWriter) UpdateAccountCode(address common.Address, incarnation return err } //save contract to codeHash mapping - if err := dsw.stateDb.Put(dbutils.ContractCodeBucket, dbutils.GenerateStoragePrefix(addrHash[:], incarnation), codeHash[:]); err != nil { + if err := dsw.db.Put(dbutils.ContractCodeBucket, dbutils.GenerateStoragePrefix(addrHash[:], incarnation), codeHash[:]); err != nil { return err } if dsw.codeCache != nil { @@ -181,16 +179,16 @@ func (dsw *DbStateWriter) WriteAccountStorage(ctx context.Context, address commo dsw.storageCache.Set(compositeKey, v) } if len(v) == 0 { - return dsw.stateDb.Delete(dbutils.CurrentStateBucket, compositeKey) + return dsw.db.Delete(dbutils.CurrentStateBucket, compositeKey) } - return dsw.stateDb.Put(dbutils.CurrentStateBucket, compositeKey, v) + return dsw.db.Put(dbutils.CurrentStateBucket, compositeKey, v) } func (dsw *DbStateWriter) CreateContract(address common.Address) error { if err := dsw.csw.CreateContract(address); err != nil { return err } - if err := dsw.stateDb.Delete(dbutils.IncarnationMapBucket, address[:]); err != nil { + if err := dsw.db.Delete(dbutils.IncarnationMapBucket, address[:]); err != nil { return err } return nil @@ -209,7 +207,7 @@ func (dsw *DbStateWriter) WriteChangeSets() error { return err } key := dbutils.EncodeTimestamp(dsw.blockNr) - if err = dsw.changeDb.Put(dbutils.AccountChangeSetBucket, key, accountSerialised); err != nil { + if err = dsw.db.Put(dbutils.AccountChangeSetBucket, key, accountSerialised); err != nil { return err } storageChanges, err := dsw.csw.GetStorageChanges() @@ -222,7 +220,7 @@ func (dsw *DbStateWriter) WriteChangeSets() error { if err != nil { return err } - if err = dsw.changeDb.Put(dbutils.StorageChangeSetBucket, key, storageSerialized); err != nil { + if err = dsw.db.Put(dbutils.StorageChangeSetBucket, key, storageSerialized); err != nil { return err } } @@ -234,7 +232,7 @@ func (dsw *DbStateWriter) WriteHistory() error { if err != nil { return err } - err = writeIndex(dsw.blockNr, accountChanges, dbutils.AccountsHistoryBucket, dsw.changeDb) + err = writeIndex(dsw.blockNr, accountChanges, dbutils.AccountsHistoryBucket, dsw.db) if err != nil { return err } @@ -243,7 +241,7 @@ func (dsw *DbStateWriter) WriteHistory() error { if err != nil { return err } - err = writeIndex(dsw.blockNr, storageChanges, dbutils.StorageHistoryBucket, dsw.changeDb) + err = writeIndex(dsw.blockNr, storageChanges, dbutils.StorageHistoryBucket, dsw.db) if err != nil { return err } diff --git a/core/state/plain_state_writer.go b/core/state/plain_state_writer.go index 4ca0e317ac19007e63088ff6092c58e36b474e59..17d774f10e50370a79739f6f4a7c1f69d68fae3a 100644 --- a/core/state/plain_state_writer.go +++ b/core/state/plain_state_writer.go @@ -17,22 +17,20 @@ import ( var _ WriterWithChangeSets = (*PlainStateWriter)(nil) type PlainStateWriter struct { - stateDb ethdb.Database - changeDb ethdb.Database - csw *ChangeSetWriter - blockNumber uint64 - accountCache *fastcache.Cache - storageCache *fastcache.Cache - codeCache *fastcache.Cache - codeSizeCache *fastcache.Cache + db ethdb.Database + csw *ChangeSetWriter + blockNumber uint64 + accountCache *fastcache.Cache + storageCache *fastcache.Cache + codeCache *fastcache.Cache + codeSizeCache *fastcache.Cache } -func NewPlainStateWriter(stateDb, changeDb ethdb.Database, blockNumber uint64) *PlainStateWriter { +func NewPlainStateWriter(db ethdb.Database, blockNumber uint64) *PlainStateWriter { return &PlainStateWriter{ - stateDb: stateDb, - changeDb: changeDb, - csw: NewChangeSetWriterPlain(), - blockNumber: blockNumber, + db: db, + csw: NewChangeSetWriterPlain(), + blockNumber: blockNumber, } } @@ -61,7 +59,7 @@ func (w *PlainStateWriter) UpdateAccountData(ctx context.Context, address common if w.accountCache != nil { w.accountCache.Set(address[:], value) } - return w.stateDb.Put(dbutils.PlainStateBucket, address[:], value) + return w.db.Put(dbutils.PlainStateBucket, address[:], value) } func (w *PlainStateWriter) UpdateAccountCode(address common.Address, incarnation uint64, codeHash common.Hash, code []byte) error { @@ -80,10 +78,10 @@ func (w *PlainStateWriter) UpdateAccountCode(address common.Address, incarnation binary.BigEndian.PutUint32(b[:], uint32(len(code))) w.codeSizeCache.Set(address[:], b[:]) } - if err := w.stateDb.Put(dbutils.CodeBucket, codeHash[:], code); err != nil { + if err := w.db.Put(dbutils.CodeBucket, codeHash[:], code); err != nil { return err } - return w.stateDb.Put(dbutils.PlainContractCodeBucket, dbutils.PlainGenerateStoragePrefix(address[:], incarnation), codeHash[:]) + return w.db.Put(dbutils.PlainContractCodeBucket, dbutils.PlainGenerateStoragePrefix(address[:], incarnation), codeHash[:]) } func (w *PlainStateWriter) DeleteAccount(ctx context.Context, address common.Address, original *accounts.Account) error { @@ -101,13 +99,13 @@ func (w *PlainStateWriter) DeleteAccount(ctx context.Context, address common.Add binary.BigEndian.PutUint32(b[:], 0) w.codeSizeCache.Set(address[:], b[:]) } - if err := w.stateDb.Delete(dbutils.PlainStateBucket, address[:]); err != nil { + if err := w.db.Delete(dbutils.PlainStateBucket, address[:]); err != nil { return err } if original.Incarnation > 0 { var b [8]byte binary.BigEndian.PutUint64(b[:], original.Incarnation) - if err := w.stateDb.Put(dbutils.IncarnationMapBucket, address[:], b[:]); err != nil { + if err := w.db.Put(dbutils.IncarnationMapBucket, address[:], b[:]); err != nil { return err } } @@ -128,16 +126,16 @@ func (w *PlainStateWriter) WriteAccountStorage(ctx context.Context, address comm w.storageCache.Set(compositeKey, v) } if len(v) == 0 { - return w.stateDb.Delete(dbutils.PlainStateBucket, compositeKey) + return w.db.Delete(dbutils.PlainStateBucket, compositeKey) } - return w.stateDb.Put(dbutils.PlainStateBucket, compositeKey, v) + return w.db.Put(dbutils.PlainStateBucket, compositeKey, v) } func (w *PlainStateWriter) CreateContract(address common.Address) error { if err := w.csw.CreateContract(address); err != nil { return err } - if err := w.stateDb.Delete(dbutils.IncarnationMapBucket, address[:]); err != nil { + if err := w.db.Delete(dbutils.IncarnationMapBucket, address[:]); err != nil { return err } return nil @@ -154,7 +152,7 @@ func (w *PlainStateWriter) WriteChangeSets() error { return err } key := dbutils.EncodeTimestamp(w.blockNumber) - if err = w.changeDb.Put(dbutils.PlainAccountChangeSetBucket, key, accountSerialised); err != nil { + if err = w.db.Put(dbutils.PlainAccountChangeSetBucket, key, accountSerialised); err != nil { return err } storageChanges, err := w.csw.GetStorageChanges() @@ -167,7 +165,7 @@ func (w *PlainStateWriter) WriteChangeSets() error { if err != nil { return err } - if err = w.changeDb.Put(dbutils.PlainStorageChangeSetBucket, key, storageSerialized); err != nil { + if err = w.db.Put(dbutils.PlainStorageChangeSetBucket, key, storageSerialized); err != nil { return err } } @@ -179,7 +177,7 @@ func (w *PlainStateWriter) WriteHistory() error { if err != nil { return err } - err = writeIndex(w.blockNumber, accountChanges, dbutils.AccountsHistoryBucket, w.changeDb) + err = writeIndex(w.blockNumber, accountChanges, dbutils.AccountsHistoryBucket, w.db) if err != nil { return err } @@ -188,7 +186,7 @@ func (w *PlainStateWriter) WriteHistory() error { if err != nil { return err } - err = writeIndex(w.blockNumber, storageChanges, dbutils.StorageHistoryBucket, w.changeDb) + err = writeIndex(w.blockNumber, storageChanges, dbutils.StorageHistoryBucket, w.db) if err != nil { return err } diff --git a/eth/backend.go b/eth/backend.go index 1ca9742ec261b2771134763cf82fa91cebd185cf..5c0c1e0962728283880b73935557707fb22834ab 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -29,7 +29,6 @@ import ( "github.com/ledgerwatch/turbo-geth/accounts" "github.com/ledgerwatch/turbo-geth/accounts/abi/bind" "github.com/ledgerwatch/turbo-geth/common" - "github.com/ledgerwatch/turbo-geth/common/dbutils" "github.com/ledgerwatch/turbo-geth/common/hexutil" "github.com/ledgerwatch/turbo-geth/consensus" "github.com/ledgerwatch/turbo-geth/consensus/clique" @@ -194,12 +193,12 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } } - err = setStorageModeIfNotExist(chainDb, config.StorageMode) + err = ethdb.SetStorageModeIfNotExist(chainDb, config.StorageMode) if err != nil { return nil, err } - sm, err := GetStorageModeFromDB(chainDb) + sm, err := ethdb.GetStorageModeFromDB(chainDb) if err != nil { return nil, err } @@ -662,86 +661,3 @@ func (s *Ethereum) Stop() error { s.eventMux.Stop() return nil } - -func setStorageModeIfNotExist(db ethdb.Database, sm StorageMode) error { - var ( - err error - ) - err = setModeOnEmpty(db, dbutils.StorageModeHistory, sm.History) - if err != nil { - return err - } - - err = setModeOnEmpty(db, dbutils.StorageModePreImages, sm.Preimages) - if err != nil { - return err - } - - err = setModeOnEmpty(db, dbutils.StorageModeReceipts, sm.Receipts) - if err != nil { - return err - } - - err = setModeOnEmpty(db, dbutils.StorageModeTxIndex, sm.TxIndex) - if err != nil { - return err - } - - return nil -} - -func setModeOnEmpty(db ethdb.Database, key []byte, currentValue bool) error { - _, err := db.Get(dbutils.DatabaseInfoBucket, key) - if err != nil && err != ethdb.ErrKeyNotFound { - return err - } - if err == ethdb.ErrKeyNotFound { - val := []byte{} - if currentValue { - val = []byte{1} - } - if err = db.Put(dbutils.DatabaseInfoBucket, key, val); err != nil { - return err - } - } - - return nil -} - -func GetStorageModeFromDB(db ethdb.Database) (StorageMode, error) { - var ( - sm StorageMode - v []byte - err error - ) - v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeHistory) - if err != nil && err != ethdb.ErrKeyNotFound { - return StorageMode{}, err - } - sm.History = len(v) > 0 - - v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModePreImages) - if err != nil && err != ethdb.ErrKeyNotFound { - return StorageMode{}, err - } - sm.Preimages = len(v) > 0 - - v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeReceipts) - if err != nil && err != ethdb.ErrKeyNotFound { - return StorageMode{}, err - } - sm.Receipts = len(v) > 0 - - v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeTxIndex) - if err != nil && err != ethdb.ErrKeyNotFound { - return StorageMode{}, err - } - sm.TxIndex = len(v) > 0 - - v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeThinHistory) - if err != nil && err != ethdb.ErrKeyNotFound { - return StorageMode{}, err - } - - return sm, nil -} diff --git a/eth/config.go b/eth/config.go index b77e8a12516c56f8689c1e0bb631f3d56fca4b13..2853885868559557a8c8f96be78b89ab3ee896aa 100644 --- a/eth/config.go +++ b/eth/config.go @@ -17,7 +17,6 @@ package eth import ( - "fmt" "math/big" "os" "os/user" @@ -30,6 +29,7 @@ import ( "github.com/ledgerwatch/turbo-geth/core" "github.com/ledgerwatch/turbo-geth/eth/downloader" "github.com/ledgerwatch/turbo-geth/eth/gasprice" + "github.com/ledgerwatch/turbo-geth/ethdb" "github.com/ledgerwatch/turbo-geth/miner" "github.com/ledgerwatch/turbo-geth/params" ) @@ -53,7 +53,7 @@ var DefaultConfig = Config{ TrieCleanCache: 256, TrieDirtyCache: 256, TrieTimeout: 60 * time.Minute, - StorageMode: DefaultStorageMode, + StorageMode: ethdb.DefaultStorageMode, Miner: miner.Config{ GasFloor: 8000000, GasCeil: 8000000, @@ -88,52 +88,6 @@ func init() { } } -type StorageMode struct { - History bool - Receipts bool - TxIndex bool - Preimages bool -} - -var DefaultStorageMode = StorageMode{History: true, Receipts: false, TxIndex: true, Preimages: true} - -func (m StorageMode) ToString() string { - modeString := "" - if m.History { - modeString += "h" - } - if m.Preimages { - modeString += "p" - } - if m.Receipts { - modeString += "r" - } - if m.TxIndex { - modeString += "t" - } - return modeString -} - -func StorageModeFromString(flags string) (StorageMode, error) { - mode := StorageMode{} - for _, flag := range flags { - switch flag { - case 'h': - mode.History = true - case 'r': - mode.Receipts = true - case 't': - mode.TxIndex = true - case 'p': - mode.Preimages = true - default: - return mode, fmt.Errorf("unexpected flag found: %c", flag) - } - } - - return mode, nil -} - //go:generate gencodec -type Config -formats toml -out gen_config.go type Config struct { @@ -153,7 +107,7 @@ type Config struct { NoPrefetch bool // Whether to disable prefetching and only load state on demand TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. - StorageMode StorageMode + StorageMode ethdb.StorageMode // DownloadOnly is set when the node does not need to process the blocks, but simply // download them diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 3af8f56a1fae656c53b97e8103cc741a4f015071..5b5d5632bb015e7f0709f412cf02dbab04ba7b99 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -156,9 +156,9 @@ type Downloader struct { bodyFetchHook func([]*types.Header) // Method to call upon starting a block body fetch receiptFetchHook func([]*types.Header) // Method to call upon starting a receipt fetch chainInsertHook func([]*fetchResult) // Method to call upon inserting a chain of blocks (possibly in multiple invocations) - // generate history index, disable/enable pruning - history bool - datadir string + + storageMode ethdb.StorageMode + datadir string headersState *stagedsync.StageState headersUnwinder stagedsync.Unwinder @@ -246,13 +246,13 @@ type BlockChain interface { } // New creates a new downloader to fetch hashes and blocks from remote peers. -func New(checkpoint uint64, stateDb ethdb.Database, stateBloom *trie.SyncBloom, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, history bool) *Downloader { +func New(checkpoint uint64, stateDB ethdb.Database, stateBloom *trie.SyncBloom, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, sm ethdb.StorageMode) *Downloader { if lightchain == nil { lightchain = chain } dl := &Downloader{ mode: FullSync, - stateDB: stateDb, + stateDB: stateDB, mux: mux, queue: newQueue(), peers: newPeerSet(), @@ -268,8 +268,7 @@ func New(checkpoint uint64, stateDb ethdb.Database, stateBloom *trie.SyncBloom, receiptWakeCh: make(chan bool, 1), headerProcCh: make(chan []*types.Header, 1), quitCh: make(chan struct{}), - //generate index, disable/enable pruning - history: history, + storageMode: sm, } go dl.qosTuner() return dl @@ -557,7 +556,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I d.blockchain, d.stateDB, p.id, - d.history, + d.storageMode, d.datadir, d.quitCh, fetchers, diff --git a/eth/downloader/downloader_stagedsync_test.go b/eth/downloader/downloader_stagedsync_test.go index ad1e24aa7d0049e83fd4a5374efedd78534f6d91..e62ae5a15a510b8d553a8b0ac4f678f2f7ea49e0 100644 --- a/eth/downloader/downloader_stagedsync_test.go +++ b/eth/downloader/downloader_stagedsync_test.go @@ -31,7 +31,7 @@ type stagedSyncTester struct { lock sync.RWMutex } -func newStagedSyncTester(history bool) *stagedSyncTester { +func newStagedSyncTester() *stagedSyncTester { tester := &stagedSyncTester{ peers: make(map[string]*stagedSyncTesterPeer), genesis: testGenesis, @@ -42,7 +42,7 @@ func newStagedSyncTester(history bool) *stagedSyncTester { rawdb.WriteTd(tester.db, tester.genesis.Hash(), tester.genesis.NumberU64(), tester.genesis.Difficulty()) rawdb.WriteBlock(context.Background(), tester.db, testGenesis) tester.currentHeader = tester.genesis.Header() - tester.downloader = New(uint64(StagedSync), tester.db, trie.NewSyncBloom(1, tester.db), new(event.TypeMux), tester, nil, tester.dropPeer, history) + tester.downloader = New(uint64(StagedSync), tester.db, trie.NewSyncBloom(1, tester.db), new(event.TypeMux), tester, nil, tester.dropPeer, ethdb.DefaultStorageMode) return tester } @@ -90,8 +90,8 @@ func (st *stagedSyncTester) CurrentHeader() *types.Header { return st.currentHeader } -// ExecuteBlockEuphemerally is part of the implementation of BlockChain interface defined in downloader.go -func (st *stagedSyncTester) ExecuteBlockEuphemerally(_ *types.Block, _ state.StateReader, _ *state.DbStateWriter) error { +// ExecuteBlockEphemerally is part of the implementation of BlockChain interface defined in downloader.go +func (st *stagedSyncTester) ExecuteBlockEphemerally(_ *types.Block, _ state.StateReader, _ *state.DbStateWriter) error { panic("") } @@ -323,7 +323,7 @@ func (stp *stagedSyncTesterPeer) RequestReceipts(hashes []common.Hash) error { } func TestUnwind(t *testing.T) { - tester := newStagedSyncTester(false) + tester := newStagedSyncTester() if err := tester.newPeer("peer", 65, testChainForkLightA); err != nil { t.Fatal(err) } diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index b30597a0348454314e4148267f397fc30a65b810..24658092342c285ad8d0f60dde337b1bedef8745 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -92,7 +92,7 @@ func newTester() *downloadTester { if err != nil { panic(err) } - tester.downloader = New(uint64(FullSync), tester.stateDb, trie.NewSyncBloom(1, tester.stateDb), new(event.TypeMux), tester, nil, tester.dropPeer, false) + tester.downloader = New(uint64(FullSync), tester.stateDb, trie.NewSyncBloom(1, tester.stateDb), new(event.TypeMux), tester, nil, tester.dropPeer, ethdb.DefaultStorageMode) return tester } diff --git a/eth/gen_config.go b/eth/gen_config.go index 6d61f6e73a97eecc9269c2af3535d11e297401b7..45a92847ce5e69105d60e3bd88ec09ecd570f821 100644 --- a/eth/gen_config.go +++ b/eth/gen_config.go @@ -11,6 +11,7 @@ import ( "github.com/ledgerwatch/turbo-geth/core" "github.com/ledgerwatch/turbo-geth/eth/downloader" "github.com/ledgerwatch/turbo-geth/eth/gasprice" + "github.com/ledgerwatch/turbo-geth/ethdb" "github.com/ledgerwatch/turbo-geth/miner" "github.com/ledgerwatch/turbo-geth/params" ) @@ -22,7 +23,7 @@ func (c Config) MarshalTOML() (interface{}, error) { NetworkID uint64 SyncMode downloader.SyncMode DiscoveryURLs []string - Pruning bool + Pruning bool NoPrefetch bool TxLookupLimit uint64 `toml:",omitempty"` Whitelist map[uint64]common.Hash `toml:"-"` @@ -97,7 +98,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { NetworkID *uint64 SyncMode *downloader.SyncMode DiscoveryURLs []string - Pruning *bool + Pruning *bool NoPrefetch *bool TxLookupLimit *uint64 `toml:",omitempty"` Whitelist map[uint64]common.Hash `toml:"-"` @@ -158,7 +159,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { c.Whitelist = dec.Whitelist } if dec.Mode != nil { - mode, err := StorageModeFromString(*dec.Mode) + mode, err := ethdb.StorageModeFromString(*dec.Mode) if err != nil { return err } diff --git a/eth/handler.go b/eth/handler.go index 96366269c3adfc2c0a432a462ce8a355c4edef58..6f8da55e29e65397d826d3c1585175c308446473 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -176,12 +176,12 @@ func (pm *ProtocolManager) SetDataDir(datadir string) { } func initPm(manager *ProtocolManager, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, tds *state.TrieDbState, chaindb ethdb.Database) { - sm, err := GetStorageModeFromDB(chaindb) + sm, err := ethdb.GetStorageModeFromDB(chaindb) if err != nil { log.Error("Get storage mode", "err", err) } // Construct the different synchronisation mechanisms - manager.downloader = downloader.New(manager.checkpointNumber, chaindb, nil /*stateBloom */, manager.eventMux, blockchain, nil, manager.removePeer, sm.History) + manager.downloader = downloader.New(manager.checkpointNumber, chaindb, nil /*stateBloom */, manager.eventMux, blockchain, nil, manager.removePeer, sm) manager.downloader.SetDataDir(manager.datadir) // Construct the fetcher (short sync) diff --git a/eth/stagedsync/stage_execute.go b/eth/stagedsync/stage_execute.go index 78e5d49bfd7914664505046fa6c937551ae7e665..6b7a9c2fbd1e09b4e0aa977a28b32327aa049ea8 100644 --- a/eth/stagedsync/stage_execute.go +++ b/eth/stagedsync/stage_execute.go @@ -22,7 +22,8 @@ import ( ) const ( - logInterval = 30 // seconds + logInterval = 30 // seconds + prof = false // whether to profile ) type progressLogger struct { @@ -76,11 +77,7 @@ func (l *progressLogger) Stop() { close(l.quit) } -const StateBatchSize = 50 * 1024 * 1024 // 50 Mb -const ChangeBatchSize = 1024 * 2014 // 1 Mb -const prof = false - -func SpawnExecuteBlocksStage(s *StageState, stateDB ethdb.Database, blockchain BlockChain, limit uint64, quit chan struct{}, dests vm.Cache) error { +func SpawnExecuteBlocksStage(s *StageState, stateDB ethdb.Database, blockchain BlockChain, limit uint64, quit chan struct{}, dests vm.Cache, writeReceipts bool) error { lastProcessedBlockNumber := s.BlockNumber nextBlockNumber := uint64(0) @@ -99,10 +96,9 @@ func SpawnExecuteBlocksStage(s *StageState, stateDB ethdb.Database, blockchain B } } - stateBatch := stateDB.NewBatch() - changeBatch := stateDB.NewBatch() + batch := stateDB.NewBatch() - progressLogger := NewProgressLogger(logInterval, stateBatch) + progressLogger := NewProgressLogger(logInterval, batch) progressLogger.Start(&nextBlockNumber) defer progressLogger.Stop() @@ -145,11 +141,11 @@ func SpawnExecuteBlocksStage(s *StageState, stateDB ethdb.Database, blockchain B cacheSetter } if core.UsePlainStateExecution { - stateReader = state.NewPlainStateReader(stateBatch) - stateWriter = state.NewPlainStateWriter(stateBatch, changeBatch, blockNum) + stateReader = state.NewPlainStateReader(batch) + stateWriter = state.NewPlainStateWriter(batch, blockNum) } else { - stateReader = state.NewDbStateReader(stateBatch) - stateWriter = state.NewDbStateWriter(stateBatch, changeBatch, blockNum) + stateReader = state.NewDbStateReader(batch) + stateWriter = state.NewDbStateWriter(batch, blockNum) } stateReader.SetAccountCache(accountCache) stateReader.SetStorageCache(storageCache) @@ -162,45 +158,48 @@ func SpawnExecuteBlocksStage(s *StageState, stateDB ethdb.Database, blockchain B stateWriter.SetCodeSizeCache(codeSizeCache) // where the magic happens - err := core.ExecuteBlockEuphemerally(chainConfig, vmConfig, blockchain, engine, block, stateReader, stateWriter, dests) + receipts, err := core.ExecuteBlockEphemerally(chainConfig, vmConfig, blockchain, engine, block, stateReader, stateWriter, dests) if err != nil { return err } - if err = s.Update(stateBatch, blockNum); err != nil { + if writeReceipts { + rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receipts) + } + + if err = s.Update(batch, blockNum); err != nil { return err } atomic.AddUint64(&nextBlockNumber, 1) - if stateBatch.BatchSize() >= StateBatchSize { + if batch.BatchSize() >= stateDB.IdealBatchSize() { start := time.Now() - if _, err = stateBatch.Commit(); err != nil { - return err - } - log.Info("State batch committed", "in", time.Since(start)) - } - if changeBatch.BatchSize() >= ChangeBatchSize { - if _, err = changeBatch.Commit(); err != nil { + if _, err = batch.Commit(); err != nil { return err } + log.Info("Batch committed", "in", time.Since(start)) } if prof { if blockNum-profileNumber == 100000 { - // Flush the profiler + // Flush the CPU profiler pprof.StopCPUProfile() + + // And the memory profiler + f, _ := os.Create(fmt.Sprintf("mem-%d.prof", profileNumber)) + defer f.Close() + runtime.GC() + if err = pprof.WriteHeapProfile(f); err != nil { + log.Error("could not save memory profile", "error", err) + } } } } - _, err := stateBatch.Commit() - if err != nil { - return fmt.Errorf("sync Execute: failed to write state batch commit: %v", err) - } - _, err = changeBatch.Commit() + _, err := batch.Commit() if err != nil { - return fmt.Errorf("sync Execute: failed to write change batch commit: %v", err) + return fmt.Errorf("sync Execute: failed to write batch commit: %v", err) } s.Done() return nil diff --git a/eth/stagedsync/stage_hashstate_test.go b/eth/stagedsync/stage_hashstate_test.go index f09f8ef86a66016dc7db12f547b685cb10b3ec5e..217ab73d3247400d7016d979b5f4a9d82ecff0e9 100644 --- a/eth/stagedsync/stage_hashstate_test.go +++ b/eth/stagedsync/stage_hashstate_test.go @@ -33,7 +33,7 @@ func TestPromoteHashedStateClearState(t *testing.T) { } _, err = m2.Commit() if err != nil { - t.Errorf("error while commiting state: %v", err) + t.Errorf("error while committing state: %v", err) } compareCurrentState(t, db1, db2, dbutils.CurrentStateBucket, dbutils.ContractCodeBucket) @@ -55,7 +55,7 @@ func TestPromoteHashedStateIncremental(t *testing.T) { } _, err = m2.Commit() if err != nil { - t.Errorf("error while commiting state: %v", err) + t.Errorf("error while committing state: %v", err) } generateBlocks(t, 51, 50, hashedWriterGen(db1), changeCodeWithIncarnations) @@ -68,7 +68,7 @@ func TestPromoteHashedStateIncremental(t *testing.T) { } _, err = m2.Commit() if err != nil { - t.Errorf("error while commiting state: %v", err) + t.Errorf("error while committing state: %v", err) } compareCurrentState(t, db1, db2, dbutils.CurrentStateBucket) @@ -92,7 +92,7 @@ func TestPromoteHashedStateIncrementalMixed(t *testing.T) { _, err = m2.Commit() if err != nil { - t.Errorf("error while commiting state: %v", err) + t.Errorf("error while committing state: %v", err) } compareCurrentState(t, db1, db2, dbutils.CurrentStateBucket) } diff --git a/eth/stagedsync/stagedsync.go b/eth/stagedsync/stagedsync.go index 43153622286bca886d6430f8a4fbc01acc07f889..2f68a51bf61acb5f3a67e6391a6314fcd9221e16 100644 --- a/eth/stagedsync/stagedsync.go +++ b/eth/stagedsync/stagedsync.go @@ -13,7 +13,7 @@ func PrepareStagedSync( blockchain BlockChain, stateDB ethdb.Database, pid string, - history bool, + storageMode ethdb.StorageMode, datadir string, quitCh chan struct{}, headersFetchers []func() error, @@ -56,7 +56,7 @@ func PrepareStagedSync( ID: stages.Execution, Description: "Executing blocks w/o hash checks", ExecFunc: func(s *StageState, u Unwinder) error { - return SpawnExecuteBlocksStage(s, stateDB, blockchain, 0 /* limit (meaning no limit) */, quitCh, dests) + return SpawnExecuteBlocksStage(s, stateDB, blockchain, 0 /* limit (meaning no limit) */, quitCh, dests, storageMode.Receipts) }, UnwindFunc: func(u *UnwindState, s *StageState) error { return unwindExecutionStage(u, s, stateDB) @@ -85,7 +85,7 @@ func PrepareStagedSync( { ID: stages.AccountHistoryIndex, Description: "Generating account history index", - Disabled: !history, + Disabled: !storageMode.History, DisabledDescription: "Enable by adding `h` to --storage-mode", ExecFunc: func(s *StageState, u Unwinder) error { return spawnAccountHistoryIndex(s, stateDB, datadir, core.UsePlainStateExecution, quitCh) @@ -97,7 +97,7 @@ func PrepareStagedSync( { ID: stages.StorageHistoryIndex, Description: "Generating storage history index", - Disabled: !history, + Disabled: !storageMode.History, DisabledDescription: "Enable by adding `h` to --storage-mode", ExecFunc: func(s *StageState, u Unwinder) error { return spawnStorageHistoryIndex(s, stateDB, datadir, core.UsePlainStateExecution, quitCh) diff --git a/eth/stagedsync/testutil.go b/eth/stagedsync/testutil.go index f08546de4408bf6cd5b21c2410069149fe462c37..d77e0edf016924f116decd76f33ce4790567be20 100644 --- a/eth/stagedsync/testutil.go +++ b/eth/stagedsync/testutil.go @@ -55,13 +55,13 @@ type stateWriterGen func(uint64) state.WriterWithChangeSets func hashedWriterGen(db ethdb.Database) stateWriterGen { return func(blockNum uint64) state.WriterWithChangeSets { - return state.NewDbStateWriter(db, db, blockNum) + return state.NewDbStateWriter(db, blockNum) } } func plainWriterGen(db ethdb.Database) stateWriterGen { return func(blockNum uint64) state.WriterWithChangeSets { - return state.NewPlainStateWriter(db, db, blockNum) + return state.NewPlainStateWriter(db, blockNum) } } func generateBlocks(t *testing.T, from uint64, numberOfBlocks uint64, stateWriterGen stateWriterGen, difficulty int) { diff --git a/ethdb/storage_mode.go b/ethdb/storage_mode.go new file mode 100644 index 0000000000000000000000000000000000000000..53c14cbe8b34a6349bf3f1c57dde546d32d589f3 --- /dev/null +++ b/ethdb/storage_mode.go @@ -0,0 +1,132 @@ +package ethdb + +import ( + "errors" + "fmt" + + "github.com/ledgerwatch/turbo-geth/common/dbutils" +) + +type StorageMode struct { + History bool + Receipts bool + TxIndex bool + Preimages bool +} + +var DefaultStorageMode = StorageMode{History: true, Receipts: false, TxIndex: true, Preimages: true} + +func (m StorageMode) ToString() string { + modeString := "" + if m.History { + modeString += "h" + } + if m.Preimages { + modeString += "p" + } + if m.Receipts { + modeString += "r" + } + if m.TxIndex { + modeString += "t" + } + return modeString +} + +func StorageModeFromString(flags string) (StorageMode, error) { + mode := StorageMode{} + for _, flag := range flags { + switch flag { + case 'h': + mode.History = true + case 'r': + mode.Receipts = true + case 't': + mode.TxIndex = true + case 'p': + mode.Preimages = true + default: + return mode, fmt.Errorf("unexpected flag found: %c", flag) + } + } + + return mode, nil +} + +func GetStorageModeFromDB(db Database) (StorageMode, error) { + var ( + sm StorageMode + v []byte + err error + ) + v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeHistory) + if err != nil && !errors.Is(err, ErrKeyNotFound) { + return StorageMode{}, err + } + sm.History = len(v) > 0 + + v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModePreImages) + if err != nil && !errors.Is(err, ErrKeyNotFound) { + return StorageMode{}, err + } + sm.Preimages = len(v) > 0 + + v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeReceipts) + if err != nil && !errors.Is(err, ErrKeyNotFound) { + return StorageMode{}, err + } + sm.Receipts = len(v) > 0 + + v, err = db.Get(dbutils.DatabaseInfoBucket, dbutils.StorageModeTxIndex) + if err != nil && !errors.Is(err, ErrKeyNotFound) { + return StorageMode{}, err + } + sm.TxIndex = len(v) > 0 + + return sm, nil +} + +func SetStorageModeIfNotExist(db Database, sm StorageMode) error { + var ( + err error + ) + err = setModeOnEmpty(db, dbutils.StorageModeHistory, sm.History) + if err != nil { + return err + } + + err = setModeOnEmpty(db, dbutils.StorageModePreImages, sm.Preimages) + if err != nil { + return err + } + + err = setModeOnEmpty(db, dbutils.StorageModeReceipts, sm.Receipts) + if err != nil { + return err + } + + err = setModeOnEmpty(db, dbutils.StorageModeTxIndex, sm.TxIndex) + if err != nil { + return err + } + + return nil +} + +func setModeOnEmpty(db Database, key []byte, currentValue bool) error { + _, err := db.Get(dbutils.DatabaseInfoBucket, key) + if err != nil && !errors.Is(err, ErrKeyNotFound) { + return err + } + if errors.Is(err, ErrKeyNotFound) { + val := []byte{} + if currentValue { + val = []byte{1} + } + if err = db.Put(dbutils.DatabaseInfoBucket, key, val); err != nil { + return err + } + } + + return nil +} diff --git a/eth/backend_test.go b/ethdb/storage_mode_test.go similarity index 79% rename from eth/backend_test.go rename to ethdb/storage_mode_test.go index c8c80190734b98cfd1debca30cfb9ef4d6fa9b5d..96e76ac4a8e464d359cbf899a3cf27abdaf68207 100644 --- a/eth/backend_test.go +++ b/ethdb/storage_mode_test.go @@ -1,15 +1,14 @@ -package eth +package ethdb import ( "reflect" "testing" "github.com/davecgh/go-spew/spew" - "github.com/ledgerwatch/turbo-geth/ethdb" ) func TestSetStorageModeIfNotExist(t *testing.T) { - db := ethdb.NewMemDatabase() + db := NewMemDatabase() sm, err := GetStorageModeFromDB(db) if err != nil { t.Fatal(err) @@ -19,7 +18,7 @@ func TestSetStorageModeIfNotExist(t *testing.T) { t.Fatal() } - err = setStorageModeIfNotExist(db, StorageMode{ + err = SetStorageModeIfNotExist(db, StorageMode{ true, true, true, @@ -43,5 +42,4 @@ func TestSetStorageModeIfNotExist(t *testing.T) { spew.Dump(sm) t.Fatal("not equal") } - }