From 1994c36c7e0dbf6412185a6f1d426f0819094d82 Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Thu, 4 Jul 2024 09:47:45 +0800 Subject: [PATCH 01/18] fix: multi database compatibility with EIP-4844 --- cmd/geth/chaincmd.go | 1 + cmd/utils/flags.go | 1 - core/blockchain.go | 6 +++--- core/blockchain_reader.go | 2 +- core/chain_indexer.go | 4 ++-- core/headerchain.go | 4 ++-- core/rawdb/accessors_chain.go | 18 +++++++++--------- core/rawdb/chain_iterator.go | 4 ++-- core/rawdb/database.go | 6 ++++-- 9 files changed, 24 insertions(+), 22 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 27bc72e4d3..0ae4d53b34 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -64,6 +64,7 @@ var ( utils.CachePreimagesFlag, utils.OverrideBohr, utils.OverrideVerkle, + utils.MultiDataBaseFlag, }, utils.DatabaseFlags), Description: ` The init command initializes a new genesis block and definition for the network. diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index d6c1dd3687..62b3b2f397 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1153,7 +1153,6 @@ var ( DBEngineFlag, StateSchemeFlag, HttpHeaderFlag, - MultiDataBaseFlag, } ) diff --git a/core/blockchain.go b/core/blockchain.go index 25b9cbd7cb..fd5af92e30 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1558,7 +1558,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ if first.NumberU64() == 1 { if frozen, _ := bc.db.Ancients(); frozen == 0 { td := bc.genesisBlock.Difficulty() - writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []types.Receipts{nil}, td) + writeSize, err := rawdb.WriteAncientBlocks(bc.db.BlockStore(), []*types.Block{bc.genesisBlock}, []types.Receipts{nil}, td) if err != nil { log.Error("Error writing genesis to ancients", "err", err) return 0, err @@ -1576,7 +1576,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ // Write all chain data to ancients. td := bc.GetTd(first.Hash(), first.NumberU64()) - writeSize, err := rawdb.WriteAncientBlocksWithBlobs(bc.db, blockChain, receiptChain, td) + writeSize, err := rawdb.WriteAncientBlocksWithBlobs(bc.db.BlockStore(), blockChain, receiptChain, td) if err != nil { log.Error("Error importing chain data to ancients", "err", err) return 0, err @@ -1612,7 +1612,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ rawdb.DeleteBlockWithoutNumber(blockBatch, block.Hash(), block.NumberU64()) } // Delete side chain hash-to-number mappings. - for _, nh := range rawdb.ReadAllHashesInRange(bc.db, first.NumberU64(), last.NumberU64()) { + for _, nh := range rawdb.ReadAllHashesInRange(bc.db.BlockStore(), first.NumberU64(), last.NumberU64()) { if _, canon := canonHashes[nh.Hash]; !canon { rawdb.DeleteHeader(blockBatch, nh.Hash, nh.Number) } diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index d440590b8b..95cbc5d33e 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -252,7 +252,7 @@ func (bc *BlockChain) GetSidecarsByHash(hash common.Hash) types.BlobSidecars { if sidecars, ok := bc.sidecarsCache.Get(hash); ok { return sidecars } - number := rawdb.ReadHeaderNumber(bc.db, hash) + number := rawdb.ReadHeaderNumber(bc.db.BlockStore(), hash) if number == nil { return nil } diff --git a/core/chain_indexer.go b/core/chain_indexer.go index 6ccca69e52..f5fce72588 100644 --- a/core/chain_indexer.go +++ b/core/chain_indexer.go @@ -227,8 +227,8 @@ func (c *ChainIndexer) eventLoop(currentHeader *types.Header, events chan ChainH // Reorg to the common ancestor if needed (might not exist in light sync mode, skip reorg then) // TODO(karalabe, zsfelfoldi): This seems a bit brittle, can we detect this case explicitly? - if rawdb.ReadCanonicalHash(c.chainDb.BlockStore(), prevHeader.Number.Uint64()) != prevHash { - if h := rawdb.FindCommonAncestor(c.chainDb.BlockStore(), prevHeader, header); h != nil { + if rawdb.ReadCanonicalHash(c.chainDb, prevHeader.Number.Uint64()) != prevHash { + if h := rawdb.FindCommonAncestor(c.chainDb, prevHeader, header); h != nil { c.newHead(h.Number.Uint64(), true) } } diff --git a/core/headerchain.go b/core/headerchain.go index f09ab4347c..4f333f1f16 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -691,7 +691,7 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat // we don't end up with dangling daps in the database var nums []uint64 if origin { - for n := num + 1; len(rawdb.ReadAllHashes(hc.chainDb, n)) > 0; n++ { + for n := num + 1; len(rawdb.ReadAllHashes(hc.chainDb.BlockStore(), n)) > 0; n++ { nums = append([]uint64{n}, nums...) // suboptimal, but we don't really expect this path } origin = false @@ -701,7 +701,7 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat // Remove the related data from the database on all sidechains for _, num := range nums { // Gather all the side fork hashes - hashes := rawdb.ReadAllHashes(hc.chainDb, num) + hashes := rawdb.ReadAllHashes(hc.chainDb.BlockStore(), num) if len(hashes) == 0 { // No hashes in the database whatsoever, probably frozen already hashes = append(hashes, hdr.Hash()) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index a96376d344..4915aede5a 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -468,7 +468,7 @@ func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue { // Block is not in ancients, read from leveldb by hash and number. // Note: ReadCanonicalHash cannot be used here because it also // calls ReadAncients internally. - hash, _ := db.Get(headerHashKey(number)) + hash, _ := db.BlockStoreReader().Get(headerHashKey(number)) data, _ = db.BlockStoreReader().Get(blockBodyKey(number, common.BytesToHash(hash))) return nil }) @@ -516,6 +516,13 @@ func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *t WriteBodyRLP(db, hash, number, data) } +// DeleteBody removes all block body data associated with a hash. +func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { + if err := db.Delete(blockBodyKey(number, hash)); err != nil { + log.Crit("Failed to delete block body", "err", err) + } +} + func WriteDiffLayer(db ethdb.KeyValueWriter, hash common.Hash, layer *types.DiffLayer) { data, err := rlp.EncodeToBytes(layer) if err != nil { @@ -554,13 +561,6 @@ func DeleteDiffLayer(db ethdb.KeyValueWriter, blockHash common.Hash) { } } -// DeleteBody removes all block body data associated with a hash. -func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - if err := db.Delete(blockBodyKey(number, hash)); err != nil { - log.Crit("Failed to delete block body", "err", err) - } -} - // ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding. func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { var data []byte @@ -884,7 +884,7 @@ func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts // ReadBlobSidecarsRLP retrieves all the transaction blobs belonging to a block in RLP encoding. func ReadBlobSidecarsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { var data []byte - db.ReadAncients(func(reader ethdb.AncientReaderOp) error { + db.BlockStoreReader().ReadAncients(func(reader ethdb.AncientReaderOp) error { // Check if the data is in ancients if isCanon(reader, number, hash) { data, _ = reader.Ancient(ChainFreezerBlobSidecarTable, number) diff --git a/core/rawdb/chain_iterator.go b/core/rawdb/chain_iterator.go index 3870401085..c6926950c7 100644 --- a/core/rawdb/chain_iterator.go +++ b/core/rawdb/chain_iterator.go @@ -40,7 +40,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) { return } var ( - batch = db.NewBatch() + batch = db.BlockStore().NewBatch() start = time.Now() logged = start.Add(-7 * time.Second) // Unindex during import is fast, don't double log hash common.Hash @@ -122,7 +122,7 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool } defer close(rlpCh) for n != end { - data := ReadCanonicalBodyRLP(db.BlockStore(), n) + data := ReadCanonicalBodyRLP(db, n) // Feed the block to the aggregator, or abort on interrupt select { case rlpCh <- &numberRlp{n, data}: diff --git a/core/rawdb/database.go b/core/rawdb/database.go index ad4e3f81c0..92cc9d3b7c 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -61,8 +61,10 @@ func (frdb *freezerdb) BlockStoreReader() ethdb.Reader { } func (frdb *freezerdb) BlockStoreWriter() ethdb.Writer { - // TODO implement me - panic("implement me") + if frdb.blockStore == nil { + return frdb + } + return frdb.blockStore } // AncientDatadir returns the path of root ancient directory. From 3a87ab95899763418ab1c0057a3090868eb1cd11 Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Thu, 11 Jul 2024 16:39:45 +0800 Subject: [PATCH 02/18] fix: some api for multi database ancient --- cmd/geth/chaincmd.go | 1 - cmd/geth/dbcmd.go | 2 +- cmd/utils/flags.go | 1 + core/blockchain.go | 16 ++++++++-------- core/blockchain_reader.go | 2 +- core/rawdb/chain_iterator.go | 10 +++++----- core/state/pruner/pruner.go | 2 +- internal/ethapi/dbapi.go | 4 ++-- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 0ae4d53b34..27bc72e4d3 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -64,7 +64,6 @@ var ( utils.CachePreimagesFlag, utils.OverrideBohr, utils.OverrideVerkle, - utils.MultiDataBaseFlag, }, utils.DatabaseFlags), Description: ` The init command initializes a new genesis block and definition for the network. diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 0b2017eac4..c044f59451 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -1255,7 +1255,7 @@ func hbss2pbss(ctx *cli.Context) error { defer stack.Close() db := utils.MakeChainDatabase(ctx, stack, false, false) - db.Sync() + db.BlockStore().Sync() stateDiskDb := db.StateStore() defer db.Close() diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 62b3b2f397..d6c1dd3687 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1153,6 +1153,7 @@ var ( DBEngineFlag, StateSchemeFlag, HttpHeaderFlag, + MultiDataBaseFlag, } ) diff --git a/core/blockchain.go b/core/blockchain.go index fd5af92e30..6ef6628134 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -462,8 +462,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis } } // Ensure that a previous crash in SetHead doesn't leave extra ancients - if frozen, err := bc.db.ItemAmountInAncient(); err == nil && frozen > 0 { - frozen, err = bc.db.Ancients() + if frozen, err := bc.db.BlockStore().ItemAmountInAncient(); err == nil && frozen > 0 { + frozen, err = bc.db.BlockStore().Ancients() if err != nil { return nil, err } @@ -1100,7 +1100,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha // intent afterwards is full block importing, delete the chain segment // between the stateful-block and the sethead target. var wipe bool - frozen, _ := bc.db.Ancients() + frozen, _ := bc.db.BlockStore().Ancients() if headNumber+1 < frozen { wipe = pivot == nil || headNumber >= *pivot } @@ -1109,11 +1109,11 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha // Rewind the header chain, deleting all block bodies until then delFn := func(db ethdb.KeyValueWriter, hash common.Hash, num uint64) { // Ignore the error here since light client won't hit this path - frozen, _ := bc.db.Ancients() + frozen, _ := bc.db.BlockStore().Ancients() if num+1 <= frozen { // Truncate all relative data(header, total difficulty, body, receipt // and canonical hash) from ancient store. - if _, err := bc.db.TruncateHead(num); err != nil { + if _, err := bc.db.BlockStore().TruncateHead(num); err != nil { log.Crit("Failed to truncate ancient data", "number", num, "err", err) } // Remove the hash <-> number mapping from the active store. @@ -1556,7 +1556,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ // Ensure genesis is in ancients. if first.NumberU64() == 1 { - if frozen, _ := bc.db.Ancients(); frozen == 0 { + if frozen, _ := bc.db.BlockStore().Ancients(); frozen == 0 { td := bc.genesisBlock.Difficulty() writeSize, err := rawdb.WriteAncientBlocks(bc.db.BlockStore(), []*types.Block{bc.genesisBlock}, []types.Receipts{nil}, td) if err != nil { @@ -1584,7 +1584,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ size += writeSize // Sync the ancient store explicitly to ensure all data has been flushed to disk. - if err := bc.db.Sync(); err != nil { + if err := bc.db.BlockStore().Sync(); err != nil { return 0, err } // Update the current snap block because all block data is now present in DB. @@ -1592,7 +1592,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ if !updateHead(blockChain[len(blockChain)-1]) { // We end up here if the header chain has reorg'ed, and the blocks/receipts // don't match the canonical chain. - if _, err := bc.db.TruncateHead(previousSnapBlock + 1); err != nil { + if _, err := bc.db.BlockStore().TruncateHead(previousSnapBlock + 1); err != nil { log.Error("Can't truncate ancient store after failed insert", "err", err) } return 0, errSideChainReceipts diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index 95cbc5d33e..d565c00672 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -514,7 +514,7 @@ func (bc *BlockChain) SubscribeFinalizedHeaderEvent(ch chan<- FinalizedHeaderEve // AncientTail retrieves the tail the ancients blocks func (bc *BlockChain) AncientTail() (uint64, error) { - tail, err := bc.db.Tail() + tail, err := bc.db.BlockStore().Tail() if err != nil { return 0, err } diff --git a/core/rawdb/chain_iterator.go b/core/rawdb/chain_iterator.go index c6926950c7..6f8bf69e7c 100644 --- a/core/rawdb/chain_iterator.go +++ b/core/rawdb/chain_iterator.go @@ -35,7 +35,7 @@ import ( // injects into the database the block hash->number mappings. func InitDatabaseFromFreezer(db ethdb.Database) { // If we can't access the freezer or it's empty, abort - frozen, err := db.ItemAmountInAncient() + frozen, err := db.BlockStore().ItemAmountInAncient() if err != nil || frozen == 0 { return } @@ -44,7 +44,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) { start = time.Now() logged = start.Add(-7 * time.Second) // Unindex during import is fast, don't double log hash common.Hash - offset = db.AncientOffSet() + offset = db.BlockStore().AncientOffSet() ) for i := uint64(0) + offset; i < frozen+offset; i++ { // We read 100K hashes at a time, for a total of 3.2M @@ -100,7 +100,7 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool number uint64 rlp rlp.RawValue } - if offset := db.AncientOffSet(); offset > from { + if offset := db.BlockStore().AncientOffSet(); offset > from { from = offset } if to <= from { @@ -187,7 +187,7 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool // signal received. func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) { // short circuit for invalid range - if offset := db.AncientOffSet(); offset > from { + if offset := db.BlockStore().AncientOffSet(); offset > from { from = offset } if from >= to { @@ -286,7 +286,7 @@ func indexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, inte // signal received. func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) { // short circuit for invalid range - if offset := db.AncientOffSet(); offset > from { + if offset := db.BlockStore().AncientOffSet(); offset > from { from = offset } if from >= to { diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go index f4820c06b2..2f90af3d4e 100644 --- a/core/state/pruner/pruner.go +++ b/core/state/pruner/pruner.go @@ -457,7 +457,7 @@ func (p *BlockPruner) backUpOldDb(name string, cache, handles int, namespace str blobs := rawdb.ReadBlobSidecars(chainDb, blockHash, blockNumber) block = block.WithSidecars(blobs) // Write into new ancient_back db. - if _, err := rawdb.WriteAncientBlocksWithBlobs(frdbBack, []*types.Block{block}, []types.Receipts{receipts}, td); err != nil { + if _, err := rawdb.WriteAncientBlocksWithBlobs(chainDb.BlockStore(), []*types.Block{block}, []types.Receipts{receipts}, td); err != nil { log.Error("failed to write new ancient", "error", err) return err } diff --git a/internal/ethapi/dbapi.go b/internal/ethapi/dbapi.go index 33fda936dc..b891091b94 100644 --- a/internal/ethapi/dbapi.go +++ b/internal/ethapi/dbapi.go @@ -33,11 +33,11 @@ func (api *DebugAPI) DbGet(key string) (hexutil.Bytes, error) { // DbAncient retrieves an ancient binary blob from the append-only immutable files. // It is a mapping to the `AncientReaderOp.Ancient` method func (api *DebugAPI) DbAncient(kind string, number uint64) (hexutil.Bytes, error) { - return api.b.ChainDb().Ancient(kind, number) + return api.b.ChainDb().BlockStore().Ancient(kind, number) } // DbAncients returns the ancient item numbers in the ancient store. // It is a mapping to the `AncientReaderOp.Ancients` method func (api *DebugAPI) DbAncients() (uint64, error) { - return api.b.ChainDb().Ancients() + return api.b.ChainDb().BlockStore().Ancients() } From 11454edee49516512233f096ee041b2b50ba96f3 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Wed, 10 Jul 2024 19:02:52 +0800 Subject: [PATCH 03/18] fix: fix snap sync with multidatabase --- core/rawdb/database.go | 15 ++++++++ core/rawdb/table.go | 4 +++ core/state/sync_test.go | 10 +++--- eth/downloader/downloader.go | 1 - eth/protocols/snap/sync.go | 69 +++++++++++++++++++++++++++--------- ethdb/database.go | 1 + ethdb/remotedb/remotedb.go | 4 +++ trie/sync.go | 14 +++++--- trie/sync_test.go | 16 ++++----- 9 files changed, 99 insertions(+), 35 deletions(-) diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 92cc9d3b7c..ad835e6eb5 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -118,6 +118,13 @@ func (frdb *freezerdb) StateStore() ethdb.Database { return frdb.stateStore } +func (frdb *freezerdb) GetStateStore() ethdb.Database { + if frdb.stateStore != nil { + return frdb.stateStore + } + return frdb +} + func (frdb *freezerdb) SetStateStore(state ethdb.Database) { if frdb.stateStore != nil { frdb.stateStore.Close() @@ -256,6 +263,13 @@ func (db *nofreezedb) SetStateStore(state ethdb.Database) { db.stateStore = state } +func (db *nofreezedb) GetStateStore() ethdb.Database { + if db.stateStore != nil { + return db.stateStore + } + return db +} + func (db *nofreezedb) StateStoreReader() ethdb.Reader { if db.stateStore != nil { return db.stateStore @@ -405,6 +419,7 @@ func (db *emptyfreezedb) Sync() error { func (db *emptyfreezedb) DiffStore() ethdb.KeyValueStore { return db } func (db *emptyfreezedb) SetDiffStore(diff ethdb.KeyValueStore) {} func (db *emptyfreezedb) StateStore() ethdb.Database { return db } +func (db *emptyfreezedb) GetStateStore() ethdb.Database { return db } func (db *emptyfreezedb) SetStateStore(state ethdb.Database) {} func (db *emptyfreezedb) StateStoreReader() ethdb.Reader { return db } func (db *emptyfreezedb) BlockStore() ethdb.Database { return db } diff --git a/core/rawdb/table.go b/core/rawdb/table.go index c4a029bcad..7fc182b7c5 100644 --- a/core/rawdb/table.go +++ b/core/rawdb/table.go @@ -251,6 +251,10 @@ func (t *table) SetStateStore(state ethdb.Database) { panic("not implement") } +func (t *table) GetStateStore() ethdb.Database { + return nil +} + func (t *table) StateStoreReader() ethdb.Reader { return nil } diff --git a/core/state/sync_test.go b/core/state/sync_test.go index adb3ff9495..211b0be9f6 100644 --- a/core/state/sync_test.go +++ b/core/state/sync_test.go @@ -268,7 +268,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool, s } } batch := dstDb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -369,7 +369,7 @@ func testIterativeDelayedStateSync(t *testing.T, scheme string) { nodeProcessed = len(nodeResults) } batch := dstDb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -469,7 +469,7 @@ func testIterativeRandomStateSync(t *testing.T, count int, scheme string) { } } batch := dstDb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -575,7 +575,7 @@ func testIterativeRandomDelayedStateSync(t *testing.T, scheme string) { } } batch := dstDb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -688,7 +688,7 @@ func testIncompleteStateSync(t *testing.T, scheme string) { } } batch := dstDb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 664f775052..3d5ddb985e 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -101,7 +101,6 @@ type Downloader struct { peers *peerSet // Set of active peers from which download can proceed stateDB ethdb.Database // Database to state sync into (and deduplicate via) - // Statistics syncStatsChainOrigin uint64 // Origin block number where syncing started at syncStatsChainHeight uint64 // Highest block number known when syncing started diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go index 988a632e5a..4b6062059e 100644 --- a/eth/protocols/snap/sync.go +++ b/eth/protocols/snap/sync.go @@ -409,8 +409,8 @@ type SyncPeer interface { // - The peer delivers a stale response after a previous timeout // - The peer delivers a refusal to serve the requested state type Syncer struct { - db ethdb.KeyValueStore // Database to store the trie nodes into (and dedup) - scheme string // Node scheme used in node database + db ethdb.Database // Database to store the trie nodes into (and dedup) + scheme string // Node scheme used in node database root common.Hash // Current state trie root being synced tasks []*accountTask // Current account task set being synced @@ -478,7 +478,7 @@ type Syncer struct { // NewSyncer creates a new snapshot syncer to download the Ethereum state over the // snap protocol. -func NewSyncer(db ethdb.KeyValueStore, scheme string) *Syncer { +func NewSyncer(db ethdb.Database, scheme string) *Syncer { return &Syncer{ db: db, scheme: scheme, @@ -719,11 +719,11 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error { // cleanPath is used to remove the dangling nodes in the stackTrie. func (s *Syncer) cleanPath(batch ethdb.Batch, owner common.Hash, path []byte) { - if owner == (common.Hash{}) && rawdb.ExistsAccountTrieNode(s.db, path) { + if owner == (common.Hash{}) && rawdb.ExistsAccountTrieNode(s.db.StateStoreReader(), path) { rawdb.DeleteAccountTrieNode(batch, path) deletionGauge.Inc(1) } - if owner != (common.Hash{}) && rawdb.ExistsStorageTrieNode(s.db, owner, path) { + if owner != (common.Hash{}) && rawdb.ExistsStorageTrieNode(s.db.StateStoreReader(), owner, path) { rawdb.DeleteStorageTrieNode(batch, owner, path) deletionGauge.Inc(1) } @@ -735,6 +735,7 @@ func (s *Syncer) cleanPath(batch ethdb.Batch, owner common.Hash, path []byte) { func (s *Syncer) loadSyncStatus() { var progress SyncProgress + stateDiskDB := s.db.GetStateStore() if status := rawdb.ReadSnapshotSyncStatus(s.db); status != nil { if err := json.Unmarshal(status, &progress); err != nil { log.Error("Failed to decode snap sync status", "err", err) @@ -747,7 +748,7 @@ func (s *Syncer) loadSyncStatus() { task := task // closure for task.genBatch in the stacktrie writer callback task.genBatch = ethdb.HookedBatch{ - Batch: s.db.NewBatch(), + Batch: stateDiskDB.NewBatch(), OnPut: func(key []byte, value []byte) { s.accountBytes += common.StorageSize(len(key) + len(value)) }, @@ -773,7 +774,7 @@ func (s *Syncer) loadSyncStatus() { subtask := subtask // closure for subtask.genBatch in the stacktrie writer callback subtask.genBatch = ethdb.HookedBatch{ - Batch: s.db.NewBatch(), + Batch: stateDiskDB.NewBatch(), OnPut: func(key []byte, value []byte) { s.storageBytes += common.StorageSize(len(key) + len(value)) }, @@ -841,7 +842,7 @@ func (s *Syncer) loadSyncStatus() { last = common.MaxHash } batch := ethdb.HookedBatch{ - Batch: s.db.NewBatch(), + Batch: stateDiskDB.NewBatch(), OnPut: func(key []byte, value []byte) { s.accountBytes += common.StorageSize(len(key) + len(value)) }, @@ -1886,7 +1887,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) { for i, account := range res.accounts { // Check if the account is a contract with an unknown code if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { - if !rawdb.HasCodeWithPrefix(s.db, common.BytesToHash(account.CodeHash)) { + if !rawdb.HasCodeWithPrefix(s.db.StateStoreReader(), common.BytesToHash(account.CodeHash)) { res.task.codeTasks[common.BytesToHash(account.CodeHash)] = struct{}{} res.task.needCode[i] = true res.task.pend++ @@ -1894,7 +1895,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) { } // Check if the account is a contract with an unknown storage trie if account.Root != types.EmptyRootHash { - if !rawdb.HasTrieNode(s.db, res.hashes[i], nil, account.Root, s.scheme) { + if !rawdb.HasTrieNode(s.db.StateStoreReader(), res.hashes[i], nil, account.Root, s.scheme) { // If there was a previous large state retrieval in progress, // don't restart it from scratch. This happens if a sync cycle // is interrupted and resumed later. However, *do* update the @@ -1986,12 +1987,25 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { if res.subTask != nil { res.subTask.req = nil } + + var usingMultDatabase bool batch := ethdb.HookedBatch{ - Batch: s.db.NewBatch(), + Batch: s.db.GetStateStore().NewBatch(), OnPut: func(key []byte, value []byte) { s.storageBytes += common.StorageSize(len(key) + len(value)) }, } + var snapBatch ethdb.HookedBatch + if s.db.StateStore() != nil { + usingMultDatabase = true + snapBatch = ethdb.HookedBatch{ + Batch: s.db.NewBatch(), + OnPut: func(key []byte, value []byte) { + s.storageBytes += common.StorageSize(len(key) + len(value)) + }, + } + } + var ( slots int oldStorageBytes = s.storageBytes @@ -2061,7 +2075,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { } // Our first task is the one that was just filled by this response. batch := ethdb.HookedBatch{ - Batch: s.db.NewBatch(), + Batch: s.db.GetStateStore().NewBatch(), OnPut: func(key []byte, value []byte) { s.storageBytes += common.StorageSize(len(key) + len(value)) }, @@ -2088,7 +2102,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { }) for r.Next() { batch := ethdb.HookedBatch{ - Batch: s.db.NewBatch(), + Batch: s.db.GetStateStore().NewBatch(), OnPut: func(key []byte, value []byte) { s.storageBytes += common.StorageSize(len(key) + len(value)) }, @@ -2184,8 +2198,11 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { // outdated during the sync, but it can be fixed later during the // snapshot generation. for j := 0; j < len(res.hashes[i]); j++ { - rawdb.WriteStorageSnapshot(batch, account, res.hashes[i][j], res.slots[i][j]) - + if usingMultDatabase { + rawdb.WriteStorageSnapshot(snapBatch, account, res.hashes[i][j], res.slots[i][j]) + } else { + rawdb.WriteStorageSnapshot(batch, account, res.hashes[i][j], res.slots[i][j]) + } // If we're storing large contracts, generate the trie nodes // on the fly to not trash the gluing points if i == len(res.hashes)-1 && res.subTask != nil { @@ -2205,7 +2222,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { // If the chunk's root is an overflown but full delivery, // clear the heal request. accountHash := res.accounts[len(res.accounts)-1] - if root == res.subTask.root && rawdb.HasStorageTrieNode(s.db, accountHash, nil, root) { + if root == res.subTask.root && rawdb.HasStorageTrieNode(s.db.StateStoreReader(), accountHash, nil, root) { for i, account := range res.mainTask.res.hashes { if account == accountHash { res.mainTask.needHeal[i] = false @@ -2225,6 +2242,11 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { if err := batch.Write(); err != nil { log.Crit("Failed to persist storage slots", "err", err) } + if usingMultDatabase { + if err := snapBatch.Write(); err != nil { + log.Crit("Failed to persist storage slots", "err", err) + } + } s.storageSynced += uint64(slots) log.Debug("Persisted set of storage slots", "accounts", len(res.hashes), "slots", slots, "bytes", s.storageBytes-oldStorageBytes) @@ -2323,12 +2345,25 @@ func (s *Syncer) commitHealer(force bool) { return } batch := s.db.NewBatch() - if err := s.healer.scheduler.Commit(batch); err != nil { + var trieBatch ethdb.Batch + var err error + if s.db.StateStore() != nil { + trieBatch = s.db.StateStore().NewBatch() + err = s.healer.scheduler.Commit(batch, trieBatch) + } else { + err = s.healer.scheduler.Commit(batch, nil) + } + if err != nil { log.Error("Failed to commit healing data", "err", err) } if err := batch.Write(); err != nil { log.Crit("Failed to persist healing data", "err", err) } + if s.db.StateStore() != nil { + if err := trieBatch.Write(); err != nil { + log.Crit("Failed to persist healing data", "err", err) + } + } log.Debug("Persisted set of healing data", "type", "trienodes", "bytes", common.StorageSize(batch.ValueSize())) } diff --git a/ethdb/database.go b/ethdb/database.go index e4bfbc95bc..f048961998 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -234,6 +234,7 @@ type DiffStore interface { type StateStore interface { StateStore() Database SetStateStore(state Database) + GetStateStore() Database } // Database contains all the methods required by the high level database to not diff --git a/ethdb/remotedb/remotedb.go b/ethdb/remotedb/remotedb.go index 2ba5807a32..f755dd16bc 100644 --- a/ethdb/remotedb/remotedb.go +++ b/ethdb/remotedb/remotedb.go @@ -122,6 +122,10 @@ func (db *Database) SetStateStore(state ethdb.Database) { panic("not supported") } +func (db *Database) GetStateStore() ethdb.Database { + panic("not supported") +} + func (db *Database) StateStoreReader() ethdb.Reader { return db } diff --git a/trie/sync.go b/trie/sync.go index 589d28364b..3c5715a4ba 100644 --- a/trie/sync.go +++ b/trie/sync.go @@ -420,19 +420,25 @@ func (s *Sync) ProcessNode(result NodeSyncResult) error { // Commit flushes the data stored in the internal membatch out to persistent // storage, returning any occurred error. The whole data set will be flushed // in an atomic database batch. -func (s *Sync) Commit(dbw ethdb.Batch) error { +func (s *Sync) Commit(dbw ethdb.Batch, stateBatch ethdb.Batch) error { // Flush the pending node writes into database batch. var ( account int storage int ) + var trieBatch ethdb.Batch + if stateBatch != nil { + trieBatch = stateBatch + } else { + trieBatch = dbw + } for _, op := range s.membatch.nodes { if op.isDelete() { // node deletion is only supported in path mode. if op.owner == (common.Hash{}) { - rawdb.DeleteAccountTrieNode(dbw, op.path) + rawdb.DeleteAccountTrieNode(trieBatch, op.path) } else { - rawdb.DeleteStorageTrieNode(dbw, op.owner, op.path) + rawdb.DeleteStorageTrieNode(trieBatch, op.owner, op.path) } deletionGauge.Inc(1) } else { @@ -441,7 +447,7 @@ func (s *Sync) Commit(dbw ethdb.Batch) error { } else { storage += 1 } - rawdb.WriteTrieNode(dbw, op.owner, op.path, op.hash, op.blob, s.scheme) + rawdb.WriteTrieNode(trieBatch, op.owner, op.path, op.hash, op.blob, s.scheme) } } accountNodeSyncedGauge.Inc(int64(account)) diff --git a/trie/sync_test.go b/trie/sync_test.go index 7bc68c041f..5728fc0e64 100644 --- a/trie/sync_test.go +++ b/trie/sync_test.go @@ -212,7 +212,7 @@ func testIterativeSync(t *testing.T, count int, bypath bool, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -278,7 +278,7 @@ func testIterativeDelayedSync(t *testing.T, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -348,7 +348,7 @@ func testIterativeRandomSync(t *testing.T, count int, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -419,7 +419,7 @@ func testIterativeRandomDelayedSync(t *testing.T, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -491,7 +491,7 @@ func testDuplicateAvoidanceSync(t *testing.T, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -563,7 +563,7 @@ func testIncompleteSync(t *testing.T, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -653,7 +653,7 @@ func testSyncOrdering(t *testing.T, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -723,7 +723,7 @@ func syncWithHookWriter(t *testing.T, root common.Hash, db ethdb.Database, srcDb } } batch := db.NewBatch() - if err := sched.Commit(batch); err != nil { + if err := sched.Commit(batch, nil); err != nil { t.Fatalf("failed to commit data: %v", err) } if hookWriter != nil { From 15adc748434cd94cd5f8d5b365538dec6b9a107a Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Thu, 11 Jul 2024 17:32:48 +0800 Subject: [PATCH 04/18] fix: ancient api for Downloader --- eth/downloader/downloader.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 3d5ddb985e..36c8c8d98d 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -557,8 +557,8 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * } else { d.ancientLimit = 0 } - frozen, _ := d.stateDB.Ancients() // Ignore the error here since light client can also hit here. - itemAmountInAncient, _ := d.stateDB.ItemAmountInAncient() + frozen, _ := d.stateDB.BlockStore().Ancients() // Ignore the error here since light client can also hit here. + itemAmountInAncient, _ := d.stateDB.BlockStore().ItemAmountInAncient() // If a part of blockchain data has already been written into active store, // disable the ancient style insertion explicitly. if origin >= frozen && itemAmountInAncient != 0 { @@ -1670,9 +1670,9 @@ func (d *Downloader) reportSnapSyncProgress(force bool) { } // Don't report anything until we have a meaningful progress var ( - headerBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerHeaderTable) - bodyBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerBodiesTable) - receiptBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerReceiptTable) + headerBytes, _ = d.stateDB.BlockStore().AncientSize(rawdb.ChainFreezerHeaderTable) + bodyBytes, _ = d.stateDB.BlockStore().AncientSize(rawdb.ChainFreezerBodiesTable) + receiptBytes, _ = d.stateDB.BlockStore().AncientSize(rawdb.ChainFreezerReceiptTable) ) syncedBytes := common.StorageSize(headerBytes + bodyBytes + receiptBytes) if syncedBytes == 0 { From 77707afe1774561b88f8a28472ee4dd14b303f28 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Thu, 11 Jul 2024 18:23:11 +0800 Subject: [PATCH 05/18] fix: fix download scheduler of multidatabase --- core/state/sync.go | 2 +- trie/sync.go | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/state/sync.go b/core/state/sync.go index 411b54eab0..2b07f1b061 100644 --- a/core/state/sync.go +++ b/core/state/sync.go @@ -25,7 +25,7 @@ import ( ) // NewStateSync creates a new state trie download scheduler. -func NewStateSync(root common.Hash, database ethdb.KeyValueReader, onLeaf func(keys [][]byte, leaf []byte) error, scheme string) *trie.Sync { +func NewStateSync(root common.Hash, database ethdb.Database, onLeaf func(keys [][]byte, leaf []byte) error, scheme string) *trie.Sync { // Register the storage slot callback if the external callback is specified. var onSlot func(keys [][]byte, path []byte, leaf []byte, parent common.Hash, parentPath []byte) error if onLeaf != nil { diff --git a/trie/sync.go b/trie/sync.go index 3c5715a4ba..db83f61da7 100644 --- a/trie/sync.go +++ b/trie/sync.go @@ -229,7 +229,7 @@ func (batch *syncMemBatch) delNode(owner common.Hash, path []byte) { // and reconstructs the trie step by step until all is done. type Sync struct { scheme string // Node scheme descriptor used in database. - database ethdb.KeyValueReader // Persistent database to check for existing entries + database ethdb.Database // Persistent database to check for existing entries membatch *syncMemBatch // Memory buffer to avoid frequent database writes nodeReqs map[string]*nodeRequest // Pending requests pertaining to a trie node path codeReqs map[common.Hash]*codeRequest // Pending requests pertaining to a code hash @@ -238,7 +238,7 @@ type Sync struct { } // NewSync creates a new trie data download scheduler. -func NewSync(root common.Hash, database ethdb.KeyValueReader, callback LeafCallback, scheme string) *Sync { +func NewSync(root common.Hash, database ethdb.Database, callback LeafCallback, scheme string) *Sync { ts := &Sync{ scheme: scheme, database: database, @@ -552,9 +552,9 @@ func (s *Sync) children(req *nodeRequest, object node) ([]*nodeRequest, error) { // the performance impact negligible. var exists bool if owner == (common.Hash{}) { - exists = rawdb.ExistsAccountTrieNode(s.database, append(inner, key[:i]...)) + exists = rawdb.ExistsAccountTrieNode(s.database.StateStoreReader(), append(inner, key[:i]...)) } else { - exists = rawdb.ExistsStorageTrieNode(s.database, owner, append(inner, key[:i]...)) + exists = rawdb.ExistsStorageTrieNode(s.database.StateStoreReader(), owner, append(inner, key[:i]...)) } if exists { s.membatch.delNode(owner, append(inner, key[:i]...)) @@ -693,15 +693,15 @@ func (s *Sync) commitCodeRequest(req *codeRequest) error { func (s *Sync) hasNode(owner common.Hash, path []byte, hash common.Hash) (exists bool, inconsistent bool) { // If node is running with hash scheme, check the presence with node hash. if s.scheme == rawdb.HashScheme { - return rawdb.HasLegacyTrieNode(s.database, hash), false + return rawdb.HasLegacyTrieNode(s.database.StateStoreReader(), hash), false } // If node is running with path scheme, check the presence with node path. var blob []byte var dbHash common.Hash if owner == (common.Hash{}) { - blob, dbHash = rawdb.ReadAccountTrieNode(s.database, path) + blob, dbHash = rawdb.ReadAccountTrieNode(s.database.StateStoreReader(), path) } else { - blob, dbHash = rawdb.ReadStorageTrieNode(s.database, owner, path) + blob, dbHash = rawdb.ReadStorageTrieNode(s.database.StateStoreReader(), owner, path) } exists = hash == dbHash inconsistent = !exists && len(blob) != 0 From b21b7c9250e85948f328c4f80f277c5f5dd3b404 Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Fri, 12 Jul 2024 16:35:04 +0800 Subject: [PATCH 06/18] fix: fix some code --- ethdb/database.go | 12 ++++++------ node/node.go | 37 +++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/ethdb/database.go b/ethdb/database.go index f048961998..215adc4f45 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -180,12 +180,6 @@ type StateStoreReader interface { StateStoreReader() Reader } -type BlockStore interface { - BlockStore() Database - SetBlockStore(block Database) - HasSeparateBlockStore() bool -} - type BlockStoreReader interface { BlockStoreReader() Reader } @@ -237,6 +231,12 @@ type StateStore interface { GetStateStore() Database } +type BlockStore interface { + BlockStore() Database + SetBlockStore(block Database) + HasSeparateBlockStore() bool +} + // Database contains all the methods required by the high level database to not // only access the key-value data store but also the chain freezer. type Database interface { diff --git a/node/node.go b/node/node.go index 7d07e576df..62bbc07490 100644 --- a/node/node.go +++ b/node/node.go @@ -791,14 +791,15 @@ func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, r func (n *Node) OpenAndMergeDatabase(name string, namespace string, readonly bool, config *ethconfig.Config) (ethdb.Database, error) { var ( - err error - stateDiskDb ethdb.Database - blockDb ethdb.Database - disableChainDbFreeze = false - blockDbHandlesSize int - diffStoreHandles int - chainDataHandles = config.DatabaseHandles - chainDbCache = config.DatabaseCache + err error + stateDiskDb ethdb.Database + blockDb ethdb.Database + disableChainDbFreeze = false + blockDbHandlesSize int + diffStoreHandles int + chainDataHandles = config.DatabaseHandles + chainDbCache = config.DatabaseCache + stateDbCache, stateDbHandles int ) if config.PersistDiff { @@ -818,10 +819,17 @@ func (n *Node) OpenAndMergeDatabase(name string, namespace string, readonly bool } else { blockDbHandlesSize = blockDbHandlesMinSize } - stateDbCache := config.DatabaseCache - chainDbCache - blockDbCacheSize - stateDbHandles := config.DatabaseHandles - chainDataHandles - blockDbHandlesSize + stateDbCache = config.DatabaseCache - chainDbCache - blockDbCacheSize + stateDbHandles = config.DatabaseHandles - chainDataHandles - blockDbHandlesSize disableChainDbFreeze = true + } + + chainDB, err := n.OpenDatabaseWithFreezer(name, chainDbCache, chainDataHandles, config.DatabaseFreezer, namespace, readonly, disableChainDbFreeze, false, config.PruneAncientData) + if err != nil { + return nil, err + } + if isMultiDatabase { // Allocate half of the handles and chainDbCache to this separate state data database stateDiskDb, err = n.OpenDatabaseWithFreezer(name+"/state", stateDbCache, stateDbHandles, "", "eth/db/statedata/", readonly, true, false, config.PruneAncientData) if err != nil { @@ -832,15 +840,8 @@ func (n *Node) OpenAndMergeDatabase(name string, namespace string, readonly bool if err != nil { return nil, err } - log.Warn("Multi-database is an experimental feature") - } - - chainDB, err := n.OpenDatabaseWithFreezer(name, chainDbCache, chainDataHandles, config.DatabaseFreezer, namespace, readonly, disableChainDbFreeze, false, config.PruneAncientData) - if err != nil { - return nil, err - } - if isMultiDatabase { + log.Warn("Multi-database is an experimental feature") chainDB.SetStateStore(stateDiskDb) chainDB.SetBlockStore(blockDb) } From 685fce66473080051a1379e1accfa4d7531ac563 Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Fri, 12 Jul 2024 17:05:23 +0800 Subject: [PATCH 07/18] fix: some ut tests --- trie/sync_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/trie/sync_test.go b/trie/sync_test.go index 5728fc0e64..df2c1f59f1 100644 --- a/trie/sync_test.go +++ b/trie/sync_test.go @@ -27,7 +27,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/trie/trienode" ) @@ -143,7 +142,7 @@ func TestEmptySync(t *testing.T) { emptyD, _ := New(TrieID(types.EmptyRootHash), dbD) for i, trie := range []*Trie{emptyA, emptyB, emptyC, emptyD} { - sync := NewSync(trie.Hash(), memorydb.New(), nil, []*testDb{dbA, dbB, dbC, dbD}[i].Scheme()) + sync := NewSync(trie.Hash(), rawdb.NewMemoryDatabase(), nil, []*testDb{dbA, dbB, dbC, dbD}[i].Scheme()) if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 { t.Errorf("test %d: content requested for empty trie: %v, %v, %v", i, paths, nodes, codes) } From 8b03bf0fae59cd448ce1566644e78e33d2707d3f Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Mon, 15 Jul 2024 12:13:03 +0800 Subject: [PATCH 08/18] fix: add MultiDatabaseReader for some metadata stored in blockdb --- cmd/geth/chaincmd.go | 2 +- cmd/geth/dbcmd.go | 8 +-- core/blockchain.go | 8 +-- core/blockchain_reader.go | 4 +- core/headerchain.go | 4 +- core/rawdb/accessors_chain.go | 30 ++++----- core/rawdb/accessors_indexes.go | 2 +- core/rawdb/chain_freezer.go | 6 +- core/state/pruner/pruner.go | 2 +- ethdb/database.go | 10 +++ ethdb/leveldb/leveldb.go | 53 +++++++++++++++ ethdb/memorydb/memorydb.go | 112 ++++++++++++++++++++++++++++++++ ethdb/pebble/pebble.go | 10 +++ 13 files changed, 218 insertions(+), 33 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 27bc72e4d3..56df4726ad 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -759,7 +759,7 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth arg := ctx.Args().First() if hashish(arg) { hash := common.HexToHash(arg) - if number := rawdb.ReadHeaderNumber(db.BlockStore(), hash); number != nil { + if number := rawdb.ReadHeaderNumber(db, hash); number != nil { header = rawdb.ReadHeader(db, hash, *number) } else { return nil, nil, common.Hash{}, fmt.Errorf("block %x not found", hash) diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index c044f59451..63609be946 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -397,8 +397,8 @@ func inspectTrie(ctx *cli.Context) error { var headerBlockHash common.Hash if ctx.NArg() >= 1 { if ctx.Args().Get(0) == "latest" { - headerHash := rawdb.ReadHeadHeaderHash(db.BlockStore()) - blockNumber = *(rawdb.ReadHeaderNumber(db.BlockStore(), headerHash)) + headerHash := rawdb.ReadHeadHeaderHash(db) + blockNumber = *(rawdb.ReadHeaderNumber(db, headerHash)) } else if ctx.Args().Get(0) == "snapshot" { trieRootHash = rawdb.ReadSnapshotRoot(db) blockNumber = math.MaxUint64 @@ -1273,8 +1273,8 @@ func hbss2pbss(ctx *cli.Context) error { log.Info("hbss2pbss triedb", "scheme", triedb.Scheme()) defer triedb.Close() - headerHash := rawdb.ReadHeadHeaderHash(db.BlockStore()) - blockNumber := rawdb.ReadHeaderNumber(db.BlockStore(), headerHash) + headerHash := rawdb.ReadHeadHeaderHash(db) + blockNumber := rawdb.ReadHeaderNumber(db, headerHash) if blockNumber == nil { log.Error("read header number failed.") return fmt.Errorf("read header number failed") diff --git a/core/blockchain.go b/core/blockchain.go index 6ef6628134..eeded05190 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -663,7 +663,7 @@ func (bc *BlockChain) cacheDiffLayer(diffLayer *types.DiffLayer, diffLayerCh cha // into node seamlessly. func (bc *BlockChain) empty() bool { genesis := bc.genesisBlock.Hash() - for _, hash := range []common.Hash{rawdb.ReadHeadBlockHash(bc.db.BlockStore()), rawdb.ReadHeadHeaderHash(bc.db.BlockStore()), rawdb.ReadHeadFastBlockHash(bc.db.BlockStore())} { + for _, hash := range []common.Hash{rawdb.ReadHeadBlockHash(bc.db), rawdb.ReadHeadHeaderHash(bc.db), rawdb.ReadHeadFastBlockHash(bc.db)} { if hash != genesis { return false } @@ -699,7 +699,7 @@ func (bc *BlockChain) getFinalizedNumber(header *types.Header) uint64 { // assumes that the chain manager mutex is held. func (bc *BlockChain) loadLastState() error { // Restore the last known head block - head := rawdb.ReadHeadBlockHash(bc.db.BlockStore()) + head := rawdb.ReadHeadBlockHash(bc.db) if head == (common.Hash{}) { // Corrupt or empty database, init from scratch log.Warn("Empty database, resetting chain") @@ -721,7 +721,7 @@ func (bc *BlockChain) loadLastState() error { // Restore the last known head header headHeader := headBlock.Header() - if head := rawdb.ReadHeadHeaderHash(bc.db.BlockStore()); head != (common.Hash{}) { + if head := rawdb.ReadHeadHeaderHash(bc.db); head != (common.Hash{}) { if header := bc.GetHeaderByHash(head); header != nil { headHeader = header } @@ -732,7 +732,7 @@ func (bc *BlockChain) loadLastState() error { bc.currentSnapBlock.Store(headBlock.Header()) headFastBlockGauge.Update(int64(headBlock.NumberU64())) - if head := rawdb.ReadHeadFastBlockHash(bc.db.BlockStore()); head != (common.Hash{}) { + if head := rawdb.ReadHeadFastBlockHash(bc.db); head != (common.Hash{}) { if block := bc.GetBlockByHash(head); block != nil { bc.currentSnapBlock.Store(block.Header()) headFastBlockGauge.Update(int64(block.NumberU64())) diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index d565c00672..84bbbc25f2 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -231,7 +231,7 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { if receipts, ok := bc.receiptsCache.Get(hash); ok { return receipts } - number := rawdb.ReadHeaderNumber(bc.db.BlockStore(), hash) + number := rawdb.ReadHeaderNumber(bc.db, hash) if number == nil { return nil } @@ -252,7 +252,7 @@ func (bc *BlockChain) GetSidecarsByHash(hash common.Hash) types.BlobSidecars { if sidecars, ok := bc.sidecarsCache.Get(hash); ok { return sidecars } - number := rawdb.ReadHeaderNumber(bc.db.BlockStore(), hash) + number := rawdb.ReadHeaderNumber(bc.db, hash) if number == nil { return nil } diff --git a/core/headerchain.go b/core/headerchain.go index 4f333f1f16..f2cc0b6986 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -97,7 +97,7 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c return nil, ErrNoGenesis } hc.currentHeader.Store(hc.genesisHeader) - if head := rawdb.ReadHeadBlockHash(chainDb.BlockStore()); head != (common.Hash{}) { + if head := rawdb.ReadHeadBlockHash(chainDb); head != (common.Hash{}) { if chead := hc.GetHeaderByHash(head); chead != nil { hc.currentHeader.Store(chead) } @@ -144,7 +144,7 @@ func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 { if cached, ok := hc.numberCache.Get(hash); ok { return &cached } - number := rawdb.ReadHeaderNumber(hc.chainDb.BlockStore(), hash) + number := rawdb.ReadHeaderNumber(hc.chainDb, hash) if number != nil { hc.numberCache.Add(hash, *number) } diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 4915aede5a..d127ef74da 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -144,8 +144,8 @@ func ReadAllCanonicalHashes(db ethdb.Iteratee, from uint64, to uint64, limit int } // ReadHeaderNumber returns the header number assigned to a hash. -func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) *uint64 { - data, _ := db.Get(headerNumberKey(hash)) +func ReadHeaderNumber(db ethdb.MultiDatabaseReader, hash common.Hash) *uint64 { + data, _ := db.BlockStoreReader().Get(headerNumberKey(hash)) if len(data) != 8 { return nil } @@ -170,8 +170,8 @@ func DeleteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash) { } // ReadHeadHeaderHash retrieves the hash of the current canonical head header. -func ReadHeadHeaderHash(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(headHeaderKey) +func ReadHeadHeaderHash(db ethdb.MultiDatabaseReader) common.Hash { + data, _ := db.BlockStoreReader().Get(headHeaderKey) if len(data) == 0 { return common.Hash{} } @@ -186,8 +186,8 @@ func WriteHeadHeaderHash(db ethdb.KeyValueWriter, hash common.Hash) { } // ReadHeadBlockHash retrieves the hash of the current canonical head block. -func ReadHeadBlockHash(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(headBlockKey) +func ReadHeadBlockHash(db ethdb.MultiDatabaseReader) common.Hash { + data, _ := db.BlockStoreReader().Get(headBlockKey) if len(data) == 0 { return common.Hash{} } @@ -202,8 +202,8 @@ func WriteHeadBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { } // ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block. -func ReadHeadFastBlockHash(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(headFastBlockKey) +func ReadHeadFastBlockHash(db ethdb.MultiDatabaseReader) common.Hash { + data, _ := db.BlockStoreReader().Get(headFastBlockKey) if len(data) == 0 { return common.Hash{} } @@ -218,8 +218,8 @@ func WriteHeadFastBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { } // ReadFinalizedBlockHash retrieves the hash of the finalized block. -func ReadFinalizedBlockHash(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(headFinalizedBlockKey) +func ReadFinalizedBlockHash(db ethdb.MultiDatabaseReader) common.Hash { + data, _ := db.BlockStoreReader().Get(headFinalizedBlockKey) if len(data) == 0 { return common.Hash{} } @@ -1093,24 +1093,24 @@ func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header { // ReadHeadHeader returns the current canonical head header. func ReadHeadHeader(db ethdb.Reader) *types.Header { - headHeaderHash := ReadHeadHeaderHash(db.BlockStoreReader()) + headHeaderHash := ReadHeadHeaderHash(db) if headHeaderHash == (common.Hash{}) { return nil } - headHeaderNumber := ReadHeaderNumber(db.BlockStoreReader(), headHeaderHash) + headHeaderNumber := ReadHeaderNumber(db, headHeaderHash) if headHeaderNumber == nil { return nil } - return ReadHeader(db.BlockStoreReader(), headHeaderHash, *headHeaderNumber) + return ReadHeader(db, headHeaderHash, *headHeaderNumber) } // ReadHeadBlock returns the current canonical head block. func ReadHeadBlock(db ethdb.Reader) *types.Block { - headBlockHash := ReadHeadBlockHash(db.BlockStoreReader()) + headBlockHash := ReadHeadBlockHash(db) if headBlockHash == (common.Hash{}) { return nil } - headBlockNumber := ReadHeaderNumber(db.BlockStoreReader(), headBlockHash) + headBlockNumber := ReadHeaderNumber(db, headBlockHash) if headBlockNumber == nil { return nil } diff --git a/core/rawdb/accessors_indexes.go b/core/rawdb/accessors_indexes.go index 95fc1d7806..4f2ef0a880 100644 --- a/core/rawdb/accessors_indexes.go +++ b/core/rawdb/accessors_indexes.go @@ -42,7 +42,7 @@ func ReadTxLookupEntry(db ethdb.Reader, hash common.Hash) *uint64 { } // Database v4-v5 tx lookup format just stores the hash if len(data) == common.HashLength { - return ReadHeaderNumber(db.BlockStoreReader(), common.BytesToHash(data)) + return ReadHeaderNumber(db, common.BytesToHash(data)) } // Finally try database v3 tx lookup format var entry LegacyTxLookupEntry diff --git a/core/rawdb/chain_freezer.go b/core/rawdb/chain_freezer.go index 31dd80c320..a6e496f092 100644 --- a/core/rawdb/chain_freezer.go +++ b/core/rawdb/chain_freezer.go @@ -91,7 +91,7 @@ func (f *chainFreezer) Close() error { // readHeadNumber returns the number of chain head block. 0 is returned if the // block is unknown or not available yet. -func (f *chainFreezer) readHeadNumber(db ethdb.KeyValueReader) uint64 { +func (f *chainFreezer) readHeadNumber(db ethdb.Reader) uint64 { hash := ReadHeadBlockHash(db) if hash == (common.Hash{}) { log.Error("Head block is not reachable") @@ -107,7 +107,7 @@ func (f *chainFreezer) readHeadNumber(db ethdb.KeyValueReader) uint64 { // readFinalizedNumber returns the number of finalized block. 0 is returned // if the block is unknown or not available yet. -func (f *chainFreezer) readFinalizedNumber(db ethdb.KeyValueReader) uint64 { +func (f *chainFreezer) readFinalizedNumber(db ethdb.Reader) uint64 { hash := ReadFinalizedBlockHash(db) if hash == (common.Hash{}) { return 0 @@ -122,7 +122,7 @@ func (f *chainFreezer) readFinalizedNumber(db ethdb.KeyValueReader) uint64 { // freezeThreshold returns the threshold for chain freezing. It's determined // by formula: max(finality, HEAD-params.FullImmutabilityThreshold). -func (f *chainFreezer) freezeThreshold(db ethdb.KeyValueReader) (uint64, error) { +func (f *chainFreezer) freezeThreshold(db ethdb.Reader) (uint64, error) { var ( head = f.readHeadNumber(db) final = f.readFinalizedNumber(db) diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go index 2f90af3d4e..f4820c06b2 100644 --- a/core/state/pruner/pruner.go +++ b/core/state/pruner/pruner.go @@ -457,7 +457,7 @@ func (p *BlockPruner) backUpOldDb(name string, cache, handles int, namespace str blobs := rawdb.ReadBlobSidecars(chainDb, blockHash, blockNumber) block = block.WithSidecars(blobs) // Write into new ancient_back db. - if _, err := rawdb.WriteAncientBlocksWithBlobs(chainDb.BlockStore(), []*types.Block{block}, []types.Receipts{receipts}, td); err != nil { + if _, err := rawdb.WriteAncientBlocksWithBlobs(frdbBack, []*types.Block{block}, []types.Receipts{receipts}, td); err != nil { log.Error("failed to write new ancient", "error", err) return err } diff --git a/ethdb/database.go b/ethdb/database.go index 215adc4f45..84541d0126 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -65,6 +65,8 @@ type KeyValueStore interface { KeyValueReader KeyValueWriter KeyValueStater + StateStoreReader + BlockStoreReader Batcher Iteratee Compacter @@ -188,6 +190,14 @@ type BlockStoreWriter interface { BlockStoreWriter() Writer } +// MultiDatabaseReader contains the methods required to read data from both key-value as well as +// blockStore or stateStore. +type MultiDatabaseReader interface { + KeyValueReader + StateStoreReader + BlockStoreReader +} + // Reader contains the methods required to read data from both key-value as well as // immutable ancient data. type Reader interface { diff --git a/ethdb/leveldb/leveldb.go b/ethdb/leveldb/leveldb.go index e58efbddbe..819e20c97a 100644 --- a/ethdb/leveldb/leveldb.go +++ b/ethdb/leveldb/leveldb.go @@ -84,6 +84,59 @@ type Database struct { log log.Logger // Contextual logger tracking the database path } +func (db *Database) HasAncient(kind string, number uint64) (bool, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) Ancient(kind string, number uint64) ([]byte, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) Ancients() (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) Tail() (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) AncientSize(kind string) (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) ItemAmountInAncient() (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) AncientOffSet() uint64 { + //TODO implement me + panic("implement me") +} + +func (db *Database) ReadAncients(fn func(ethdb.AncientReaderOp) error) (err error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) StateStoreReader() ethdb.Reader { + return db +} + +func (db *Database) BlockStoreReader() ethdb.Reader { + return db +} + // New returns a wrapped LevelDB object. The namespace is the prefix that the // metrics reporting should use for surfacing internal stats. func New(file string, cache int, handles int, namespace string, readonly bool) (*Database, error) { diff --git a/ethdb/memorydb/memorydb.go b/ethdb/memorydb/memorydb.go index 2a939f9a18..fa2456e3ee 100644 --- a/ethdb/memorydb/memorydb.go +++ b/ethdb/memorydb/memorydb.go @@ -39,6 +39,9 @@ var ( // errSnapshotReleased is returned if callers want to retrieve data from a // released snapshot. errSnapshotReleased = errors.New("snapshot released") + + // errNotSupported is returned if the database doesn't support the required operation. + errNotSupported = errors.New("this operation is not supported") ) // Database is an ephemeral key-value store. Apart from basic data storage @@ -47,6 +50,84 @@ var ( type Database struct { db map[string][]byte lock sync.RWMutex + + stateStore ethdb.Database + blockStore ethdb.Database +} + +func (db *Database) ModifyAncients(f func(ethdb.AncientWriteOp) error) (int64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) TruncateHead(n uint64) (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) TruncateTail(n uint64) (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) Sync() error { + //TODO implement me + panic("implement me") +} + +func (db *Database) TruncateTableTail(kind string, tail uint64) (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) ResetTable(kind string, startAt uint64, onlyEmpty bool) error { + //TODO implement me + panic("implement me") +} + +func (db *Database) HasAncient(kind string, number uint64) (bool, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) Ancient(kind string, number uint64) ([]byte, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) Ancients() (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) Tail() (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) AncientSize(kind string) (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) ItemAmountInAncient() (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (db *Database) AncientOffSet() uint64 { + //TODO implement me + panic("implement me") +} + +func (db *Database) ReadAncients(fn func(ethdb.AncientReaderOp) error) (err error) { + //TODO implement me + panic("implement me") } // New returns a wrapped map with all the required database interface methods @@ -204,6 +285,37 @@ func (db *Database) Len() int { return len(db.db) } +func (db *Database) StateStoreReader() ethdb.Reader { + if db.stateStore == nil { + return db + } + return db.stateStore +} + +func (db *Database) BlockStoreReader() ethdb.Reader { + if db.blockStore == nil { + return db + } + return db.blockStore +} + +func (db *Database) BlockStoreWriter() ethdb.Writer { + if db.blockStore == nil { + return db + } + return db.blockStore +} + +// convertLegacyFn takes a raw freezer entry in an older format and +// returns it in the new format. +type convertLegacyFn = func([]byte) ([]byte, error) + +// MigrateTable processes the entries in a given table in sequence +// converting them to a new format if they're of an old format. +func (db *Database) MigrateTable(kind string, convert convertLegacyFn) error { + return errNotSupported +} + // keyvalue is a key-value tuple tagged with a deletion field to allow creating // memory-database write batches. type keyvalue struct { diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go index aa339bf2d6..b9b5e8b6e7 100644 --- a/ethdb/pebble/pebble.go +++ b/ethdb/pebble/pebble.go @@ -96,6 +96,16 @@ type Database struct { writeOptions *pebble.WriteOptions } +func (d *Database) StateStoreReader() ethdb.Reader { + //TODO implement me + panic("implement me") +} + +func (d *Database) BlockStoreReader() ethdb.Reader { + //TODO implement me + panic("implement me") +} + func (d *Database) onCompactionBegin(info pebble.CompactionInfo) { if d.activeComp == 0 { d.compStartTime = time.Now() From 8bd1e15988070bb7578542d621f74c11d6a6867d Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Mon, 15 Jul 2024 12:14:11 +0800 Subject: [PATCH 09/18] fix: add MultiDatabaseReader for some metadata stored in blockdb --- trie/trie_test.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/trie/trie_test.go b/trie/trie_test.go index 73a72222f4..81afb76a41 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -814,6 +814,59 @@ type spongeDb struct { values map[string]string } +func (s *spongeDb) HasAncient(kind string, number uint64) (bool, error) { + //TODO implement me + panic("implement me") +} + +func (s *spongeDb) Ancient(kind string, number uint64) ([]byte, error) { + //TODO implement me + panic("implement me") +} + +func (s *spongeDb) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { + //TODO implement me + panic("implement me") +} + +func (s *spongeDb) Ancients() (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (s *spongeDb) Tail() (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (s *spongeDb) AncientSize(kind string) (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (s *spongeDb) ItemAmountInAncient() (uint64, error) { + //TODO implement me + panic("implement me") +} + +func (s *spongeDb) AncientOffSet() uint64 { + //TODO implement me + panic("implement me") +} + +func (s *spongeDb) ReadAncients(fn func(ethdb.AncientReaderOp) error) (err error) { + //TODO implement me + panic("implement me") +} + +func (s *spongeDb) StateStoreReader() ethdb.Reader { + return s +} + +func (s *spongeDb) BlockStoreReader() ethdb.Reader { + return s +} + func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement me") } func (s *spongeDb) Get(key []byte) ([]byte, error) { return nil, errors.New("no such elem") } func (s *spongeDb) Delete(key []byte) error { panic("implement me") } From b9cce0141ede6a73104479e7d6fb45d1e5b8fc2d Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Mon, 15 Jul 2024 14:03:09 +0800 Subject: [PATCH 10/18] fix: remove some redundant interfaces --- cmd/geth/dbcmd.go | 2 +- core/rawdb/database.go | 47 ++++++++++++----------------------- ethdb/database.go | 2 -- ethdb/leveldb/leveldb.go | 53 ---------------------------------------- ethdb/pebble/pebble.go | 10 -------- trie/trie_test.go | 53 ---------------------------------------- 6 files changed, 16 insertions(+), 151 deletions(-) diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 63609be946..282f035bb4 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -1212,7 +1212,7 @@ func showMetaData(ctx *cli.Context) error { if err != nil { fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err) } - data := rawdb.ReadChainMetadataFromMultiDatabase(db) + data := rawdb.ReadChainMetadata(db) data = append(data, []string{"frozen", fmt.Sprintf("%d items", ancients)}) data = append(data, []string{"snapshotGenerator", snapshot.ParseGeneratorStatus(rawdb.ReadSnapshotGenerator(db))}) if b := rawdb.ReadHeadBlock(db); b != nil { diff --git a/core/rawdb/database.go b/core/rawdb/database.go index ad835e6eb5..ac6dafa64c 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -535,8 +535,14 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st // Create the idle freezer instance frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly, offset, multiDatabase) + freezerDb := &freezerdb{ + ancientRoot: ancient, + KeyValueStore: db, + AncientStore: frdb, + AncientFreezer: frdb, + } if err != nil { - printChainMetadata(db) + printChainMetadata(freezerDb) return nil, err } @@ -572,10 +578,10 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st // the freezer and the key-value store. frgenesis, err := frdb.Ancient(ChainFreezerHashTable, 0) if err != nil { - printChainMetadata(db) + printChainMetadata(freezerDb) return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err) } else if !bytes.Equal(kvgenesis, frgenesis) { - printChainMetadata(db) + printChainMetadata(freezerDb) return nil, fmt.Errorf("genesis mismatch: %#x (leveldb) != %#x (ancients)", kvgenesis, frgenesis) } // Key-value store and freezer belong to the same network. Ensure that they @@ -583,7 +589,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st if kvhash, _ := db.Get(headerHashKey(frozen)); len(kvhash) == 0 { // Subsequent header after the freezer limit is missing from the database. // Reject startup if the database has a more recent head. - if head := *ReadHeaderNumber(db, ReadHeadHeaderHash(db)); head > frozen-1 { + if head := *ReadHeaderNumber(freezerDb, ReadHeadHeaderHash(freezerDb)); head > frozen-1 { // Find the smallest block stored in the key-value store // in range of [frozen, head] var number uint64 @@ -593,7 +599,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st } } // We are about to exit on error. Print database metadata before exiting - printChainMetadata(db) + printChainMetadata(freezerDb) return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ", frozen-1, number, head) } @@ -608,11 +614,11 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st // store, otherwise we'll end up missing data. We check block #1 to decide // if we froze anything previously or not, but do take care of databases with // only the genesis block. - if ReadHeadHeaderHash(db) != common.BytesToHash(kvgenesis) { + if ReadHeadHeaderHash(freezerDb) != common.BytesToHash(kvgenesis) { // Key-value store contains more data than the genesis block, make sure we // didn't freeze anything yet. if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 { - printChainMetadata(db) + printChainMetadata(freezerDb) return nil, errors.New("ancient chain segments already extracted, please set --datadir.ancient to the correct path") } // Block #1 is still in the database, we're allowed to init a new freezer @@ -1255,7 +1261,7 @@ func DeleteTrieState(db ethdb.Database) error { } // printChainMetadata prints out chain metadata to stderr. -func printChainMetadata(db ethdb.KeyValueStore) { +func printChainMetadata(db ethdb.Reader) { fmt.Fprintf(os.Stderr, "Chain metadata\n") for _, v := range ReadChainMetadata(db) { fmt.Fprintf(os.Stderr, " %s\n", strings.Join(v, ": ")) @@ -1266,7 +1272,7 @@ func printChainMetadata(db ethdb.KeyValueStore) { // ReadChainMetadata returns a set of key/value pairs that contains information // about the database chain status. This can be used for diagnostic purposes // when investigating the state of the node. -func ReadChainMetadata(db ethdb.KeyValueStore) [][]string { +func ReadChainMetadata(db ethdb.Reader) [][]string { pp := func(val *uint64) string { if val == nil { return "" @@ -1288,26 +1294,3 @@ func ReadChainMetadata(db ethdb.KeyValueStore) [][]string { } return data } - -func ReadChainMetadataFromMultiDatabase(db ethdb.Database) [][]string { - pp := func(val *uint64) string { - if val == nil { - return "" - } - return fmt.Sprintf("%d (%#x)", *val, *val) - } - data := [][]string{ - {"databaseVersion", pp(ReadDatabaseVersion(db))}, - {"headBlockHash", fmt.Sprintf("%v", ReadHeadBlockHash(db.BlockStore()))}, - {"headFastBlockHash", fmt.Sprintf("%v", ReadHeadFastBlockHash(db.BlockStore()))}, - {"headHeaderHash", fmt.Sprintf("%v", ReadHeadHeaderHash(db.BlockStore()))}, - {"lastPivotNumber", pp(ReadLastPivotNumber(db))}, - {"len(snapshotSyncStatus)", fmt.Sprintf("%d bytes", len(ReadSnapshotSyncStatus(db)))}, - {"snapshotDisabled", fmt.Sprintf("%v", ReadSnapshotDisabled(db))}, - {"snapshotJournal", fmt.Sprintf("%d bytes", len(ReadSnapshotJournal(db)))}, - {"snapshotRecoveryNumber", pp(ReadSnapshotRecoveryNumber(db))}, - {"snapshotRoot", fmt.Sprintf("%v", ReadSnapshotRoot(db))}, - {"txIndexTail", pp(ReadTxIndexTail(db))}, - } - return data -} diff --git a/ethdb/database.go b/ethdb/database.go index 84541d0126..5d7d54353c 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -65,8 +65,6 @@ type KeyValueStore interface { KeyValueReader KeyValueWriter KeyValueStater - StateStoreReader - BlockStoreReader Batcher Iteratee Compacter diff --git a/ethdb/leveldb/leveldb.go b/ethdb/leveldb/leveldb.go index 819e20c97a..e58efbddbe 100644 --- a/ethdb/leveldb/leveldb.go +++ b/ethdb/leveldb/leveldb.go @@ -84,59 +84,6 @@ type Database struct { log log.Logger // Contextual logger tracking the database path } -func (db *Database) HasAncient(kind string, number uint64) (bool, error) { - //TODO implement me - panic("implement me") -} - -func (db *Database) Ancient(kind string, number uint64) ([]byte, error) { - //TODO implement me - panic("implement me") -} - -func (db *Database) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { - //TODO implement me - panic("implement me") -} - -func (db *Database) Ancients() (uint64, error) { - //TODO implement me - panic("implement me") -} - -func (db *Database) Tail() (uint64, error) { - //TODO implement me - panic("implement me") -} - -func (db *Database) AncientSize(kind string) (uint64, error) { - //TODO implement me - panic("implement me") -} - -func (db *Database) ItemAmountInAncient() (uint64, error) { - //TODO implement me - panic("implement me") -} - -func (db *Database) AncientOffSet() uint64 { - //TODO implement me - panic("implement me") -} - -func (db *Database) ReadAncients(fn func(ethdb.AncientReaderOp) error) (err error) { - //TODO implement me - panic("implement me") -} - -func (db *Database) StateStoreReader() ethdb.Reader { - return db -} - -func (db *Database) BlockStoreReader() ethdb.Reader { - return db -} - // New returns a wrapped LevelDB object. The namespace is the prefix that the // metrics reporting should use for surfacing internal stats. func New(file string, cache int, handles int, namespace string, readonly bool) (*Database, error) { diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go index b9b5e8b6e7..aa339bf2d6 100644 --- a/ethdb/pebble/pebble.go +++ b/ethdb/pebble/pebble.go @@ -96,16 +96,6 @@ type Database struct { writeOptions *pebble.WriteOptions } -func (d *Database) StateStoreReader() ethdb.Reader { - //TODO implement me - panic("implement me") -} - -func (d *Database) BlockStoreReader() ethdb.Reader { - //TODO implement me - panic("implement me") -} - func (d *Database) onCompactionBegin(info pebble.CompactionInfo) { if d.activeComp == 0 { d.compStartTime = time.Now() diff --git a/trie/trie_test.go b/trie/trie_test.go index 81afb76a41..73a72222f4 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -814,59 +814,6 @@ type spongeDb struct { values map[string]string } -func (s *spongeDb) HasAncient(kind string, number uint64) (bool, error) { - //TODO implement me - panic("implement me") -} - -func (s *spongeDb) Ancient(kind string, number uint64) ([]byte, error) { - //TODO implement me - panic("implement me") -} - -func (s *spongeDb) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { - //TODO implement me - panic("implement me") -} - -func (s *spongeDb) Ancients() (uint64, error) { - //TODO implement me - panic("implement me") -} - -func (s *spongeDb) Tail() (uint64, error) { - //TODO implement me - panic("implement me") -} - -func (s *spongeDb) AncientSize(kind string) (uint64, error) { - //TODO implement me - panic("implement me") -} - -func (s *spongeDb) ItemAmountInAncient() (uint64, error) { - //TODO implement me - panic("implement me") -} - -func (s *spongeDb) AncientOffSet() uint64 { - //TODO implement me - panic("implement me") -} - -func (s *spongeDb) ReadAncients(fn func(ethdb.AncientReaderOp) error) (err error) { - //TODO implement me - panic("implement me") -} - -func (s *spongeDb) StateStoreReader() ethdb.Reader { - return s -} - -func (s *spongeDb) BlockStoreReader() ethdb.Reader { - return s -} - func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement me") } func (s *spongeDb) Get(key []byte) ([]byte, error) { return nil, errors.New("no such elem") } func (s *spongeDb) Delete(key []byte) error { panic("implement me") } From d8940bbf508c6149db0930e78454494524f28540 Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Mon, 15 Jul 2024 14:30:33 +0800 Subject: [PATCH 11/18] fix: add more comment --- core/rawdb/accessors_chain.go | 9 +++++++++ core/rawdb/database.go | 10 ++++------ eth/downloader/downloader.go | 1 + node/node.go | 1 - 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index d127ef74da..a0acf92101 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -34,6 +34,15 @@ import ( "golang.org/x/exp/slices" ) +// In BEP-365: Support Multi-Database Based on Data Pattern, the Chaindata will be divided into three stores: BlockStore, TrieStore, and Others, +// according to data schema and read/write behavior. When using the following data interfaces, you should take note of the following: +// +// 1) Block-Related Data: For CanonicalHash, Header, Body, Td, Receipts, and BlobSidecars, the Write, Delete, and Iterator +// operations should carefully ensure that the database being used is BlockStore. +// 2) Meta-Related Data: For HeaderNumber, HeadHeaderHash, HeadBlockHash, HeadFastBlockHash, and FinalizedBlockHash, the +// Write and Delete operations should carefully ensure that the database being used is BlockStore. +// 3) Ancient Data: When using a multi-database, Ancient data will use the BlockStore. + // ReadCanonicalHash retrieves the hash assigned to a canonical block number. func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash { var data []byte diff --git a/core/rawdb/database.go b/core/rawdb/database.go index ac6dafa64c..5049ade332 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -535,6 +535,9 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st // Create the idle freezer instance frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly, offset, multiDatabase) + + // We are creating the freezerdb here because the validation logic for db and freezer below requires certain interfaces + // that need a database type. Therefore, we are pre-creating it for subsequent use. freezerDb := &freezerdb{ ancientRoot: ancient, KeyValueStore: db, @@ -640,12 +643,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st frdb.wg.Done() }() } - return &freezerdb{ - ancientRoot: ancient, - KeyValueStore: db, - AncientStore: frdb, - AncientFreezer: frdb, - }, nil + return freezerDb, nil } // NewMemoryDatabase creates an ephemeral in-memory key-value database without a diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 36c8c8d98d..09925d7d66 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -101,6 +101,7 @@ type Downloader struct { peers *peerSet // Set of active peers from which download can proceed stateDB ethdb.Database // Database to state sync into (and deduplicate via) + // Statistics syncStatsChainOrigin uint64 // Origin block number where syncing started at syncStatsChainHeight uint64 // Highest block number known when syncing started diff --git a/node/node.go b/node/node.go index 62bbc07490..1954017ce9 100644 --- a/node/node.go +++ b/node/node.go @@ -840,7 +840,6 @@ func (n *Node) OpenAndMergeDatabase(name string, namespace string, readonly bool if err != nil { return nil, err } - log.Warn("Multi-database is an experimental feature") chainDB.SetStateStore(stateDiskDb) chainDB.SetBlockStore(blockDb) From f6819ed658a74f3955aa359d319fb1643bd02d37 Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Mon, 15 Jul 2024 17:04:16 +0800 Subject: [PATCH 12/18] fix: multidatabase flag is now only used by the init command --- cmd/geth/chaincmd.go | 1 + cmd/geth/main.go | 1 + cmd/utils/flags.go | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 56df4726ad..afcb474848 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -64,6 +64,7 @@ var ( utils.CachePreimagesFlag, utils.OverrideBohr, utils.OverrideVerkle, + utils.MultiDataBaseFlag, }, utils.DatabaseFlags), Description: ` The init command initializes a new genesis block and definition for the network. diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 47ba3c680e..a79ef422f1 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -125,6 +125,7 @@ var ( utils.CacheSnapshotFlag, // utils.CacheNoPrefetchFlag, utils.CachePreimagesFlag, + utils.MultiDataBaseFlag, utils.PersistDiffFlag, utils.DiffBlockFlag, utils.PruneAncientDataFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index d6c1dd3687..62b3b2f397 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1153,7 +1153,6 @@ var ( DBEngineFlag, StateSchemeFlag, HttpHeaderFlag, - MultiDataBaseFlag, } ) From df438df72df39f9af128204599763b565da935f1 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Mon, 15 Jul 2024 18:03:39 +0800 Subject: [PATCH 13/18] fix: fix code db --- eth/protocols/snap/sync.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go index 4b6062059e..dcf0fa4cb0 100644 --- a/eth/protocols/snap/sync.go +++ b/eth/protocols/snap/sync.go @@ -1887,7 +1887,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) { for i, account := range res.accounts { // Check if the account is a contract with an unknown code if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { - if !rawdb.HasCodeWithPrefix(s.db.StateStoreReader(), common.BytesToHash(account.CodeHash)) { + if !rawdb.HasCodeWithPrefix(s.db, common.BytesToHash(account.CodeHash)) { res.task.codeTasks[common.BytesToHash(account.CodeHash)] = struct{}{} res.task.needCode[i] = true res.task.pend++ From 44decdf32a9edccd04b9a3d703fee1a34fd3a537 Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Tue, 16 Jul 2024 15:36:38 +0800 Subject: [PATCH 14/18] fix: fix some comment --- core/rawdb/accessors_chain.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index a0acf92101..43190bcd8a 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -34,7 +34,7 @@ import ( "golang.org/x/exp/slices" ) -// In BEP-365: Support Multi-Database Based on Data Pattern, the Chaindata will be divided into three stores: BlockStore, TrieStore, and Others, +// Support Multi-Database Based on Data Pattern, the Chaindata will be divided into three stores: BlockStore, TrieStore, and Others, // according to data schema and read/write behavior. When using the following data interfaces, you should take note of the following: // // 1) Block-Related Data: For CanonicalHash, Header, Body, Td, Receipts, and BlobSidecars, the Write, Delete, and Iterator From c476d15a6486b79d7883445c9731bbec743b4a20 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Tue, 16 Jul 2024 16:05:09 +0800 Subject: [PATCH 15/18] fix: fix the healer commit --- eth/protocols/snap/sync.go | 8 ++++---- trie/sync.go | 24 +++++++++++++++--------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go index dcf0fa4cb0..56d48649dd 100644 --- a/eth/protocols/snap/sync.go +++ b/eth/protocols/snap/sync.go @@ -2345,11 +2345,11 @@ func (s *Syncer) commitHealer(force bool) { return } batch := s.db.NewBatch() - var trieBatch ethdb.Batch + var stateBatch ethdb.Batch var err error if s.db.StateStore() != nil { - trieBatch = s.db.StateStore().NewBatch() - err = s.healer.scheduler.Commit(batch, trieBatch) + stateBatch = s.db.StateStore().NewBatch() + err = s.healer.scheduler.Commit(batch, stateBatch) } else { err = s.healer.scheduler.Commit(batch, nil) } @@ -2360,7 +2360,7 @@ func (s *Syncer) commitHealer(force bool) { log.Crit("Failed to persist healing data", "err", err) } if s.db.StateStore() != nil { - if err := trieBatch.Write(); err != nil { + if err := stateBatch.Write(); err != nil { log.Crit("Failed to persist healing data", "err", err) } } diff --git a/trie/sync.go b/trie/sync.go index db83f61da7..5c74dfcc03 100644 --- a/trie/sync.go +++ b/trie/sync.go @@ -426,19 +426,21 @@ func (s *Sync) Commit(dbw ethdb.Batch, stateBatch ethdb.Batch) error { account int storage int ) - var trieBatch ethdb.Batch - if stateBatch != nil { - trieBatch = stateBatch - } else { - trieBatch = dbw - } for _, op := range s.membatch.nodes { if op.isDelete() { // node deletion is only supported in path mode. if op.owner == (common.Hash{}) { - rawdb.DeleteAccountTrieNode(trieBatch, op.path) + if stateBatch != nil { + rawdb.DeleteAccountTrieNode(stateBatch, op.path) + } else { + rawdb.DeleteAccountTrieNode(dbw, op.path) + } } else { - rawdb.DeleteStorageTrieNode(trieBatch, op.owner, op.path) + if stateBatch != nil { + rawdb.DeleteStorageTrieNode(stateBatch, op.owner, op.path) + } else { + rawdb.DeleteStorageTrieNode(dbw, op.owner, op.path) + } } deletionGauge.Inc(1) } else { @@ -447,7 +449,11 @@ func (s *Sync) Commit(dbw ethdb.Batch, stateBatch ethdb.Batch) error { } else { storage += 1 } - rawdb.WriteTrieNode(trieBatch, op.owner, op.path, op.hash, op.blob, s.scheme) + if stateBatch != nil { + rawdb.WriteTrieNode(stateBatch, op.owner, op.path, op.hash, op.blob, s.scheme) + } else { + rawdb.WriteTrieNode(dbw, op.owner, op.path, op.hash, op.blob, s.scheme) + } } } accountNodeSyncedGauge.Inc(int64(account)) From 6dd6db9637da8b930e2f9e1c0bcbd1a6686dd5c8 Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Tue, 16 Jul 2024 16:13:34 +0800 Subject: [PATCH 16/18] fix: fix comment --- core/rawdb/accessors_chain.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 43190bcd8a..56aa51718b 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -34,7 +34,7 @@ import ( "golang.org/x/exp/slices" ) -// Support Multi-Database Based on Data Pattern, the Chaindata will be divided into three stores: BlockStore, TrieStore, and Others, +// Support Multi-Database Based on Data Pattern, the Chaindata will be divided into three stores: BlockStore, StateStore, and ChainStore, // according to data schema and read/write behavior. When using the following data interfaces, you should take note of the following: // // 1) Block-Related Data: For CanonicalHash, Header, Body, Td, Receipts, and BlobSidecars, the Write, Delete, and Iterator From e0daf67a3fa5a3af41dcae0f6004c69baeabfdb5 Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Tue, 16 Jul 2024 16:36:43 +0800 Subject: [PATCH 17/18] fix: fix handles for chaindb --- node/node.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/node/node.go b/node/node.go index 1954017ce9..069269de0c 100644 --- a/node/node.go +++ b/node/node.go @@ -74,11 +74,11 @@ const ( initializingState = iota runningState closedState - blockDbCacheSize = 256 - blockDbHandlesMinSize = 1000 - blockDbHandlesMaxSize = 2000 - chainDbMemoryPercentage = 50 - chainDbHandlesPercentage + blockDbCacheSize = 256 + blockDbHandlesMinSize = 1000 + blockDbHandlesMaxSize = 2000 + chainDbMemoryPercentage = 50 + chainDbHandlesPercentage = 50 diffStoreHandlesPercentage = 20 ) From dc3d4258a07a44570880882d5eaea9c8f1e3080b Mon Sep 17 00:00:00 2001 From: Chris Li <271678682li@gmail.com> Date: Tue, 16 Jul 2024 21:41:28 +0800 Subject: [PATCH 18/18] fix: fix some ancient api --- core/rawdb/accessors_chain.go | 4 ++-- core/rawdb/chain_iterator.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 56aa51718b..af3cb01cee 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -306,7 +306,7 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu // It's ok to request block 0, 1 item count = number + 1 } - limit, _ := db.Ancients() + limit, _ := db.BlockStoreReader().Ancients() // First read live blocks if i >= limit { // If we need to read live blocks, we need to figure out the hash first @@ -326,7 +326,7 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu return rlpHeaders } // read remaining from ancients, cap at 2M - data, err := db.AncientRange(ChainFreezerHeaderTable, i+1-count, count, 2*1024*1024) + data, err := db.BlockStoreReader().AncientRange(ChainFreezerHeaderTable, i+1-count, count, 2*1024*1024) if err != nil { log.Error("Failed to read headers from freezer", "err", err) return rlpHeaders diff --git a/core/rawdb/chain_iterator.go b/core/rawdb/chain_iterator.go index 6f8bf69e7c..f82df9d969 100644 --- a/core/rawdb/chain_iterator.go +++ b/core/rawdb/chain_iterator.go @@ -52,7 +52,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) { if i+count > frozen+offset { count = frozen + offset - i } - data, err := db.AncientRange(ChainFreezerHashTable, i, count, 32*count) + data, err := db.BlockStore().AncientRange(ChainFreezerHashTable, i, count, 32*count) if err != nil { log.Crit("Failed to init database from freezer", "err", err) }