github.com/ethereum/go-ethereum@v1.16.1/triedb/pathdb/database.go (about) 1 // Copyright 2022 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package pathdb 18 19 import ( 20 "encoding/binary" 21 "errors" 22 "fmt" 23 "io" 24 "sync" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/core/rawdb" 29 "github.com/ethereum/go-ethereum/core/types" 30 "github.com/ethereum/go-ethereum/crypto" 31 "github.com/ethereum/go-ethereum/ethdb" 32 "github.com/ethereum/go-ethereum/log" 33 "github.com/ethereum/go-ethereum/params" 34 "github.com/ethereum/go-ethereum/trie/trienode" 35 "github.com/ethereum/go-verkle" 36 ) 37 38 const ( 39 // defaultTrieCleanSize is the default memory allowance of clean trie cache. 40 defaultTrieCleanSize = 16 * 1024 * 1024 41 42 // defaultStateCleanSize is the default memory allowance of clean state cache. 43 defaultStateCleanSize = 16 * 1024 * 1024 44 45 // maxBufferSize is the maximum memory allowance of node buffer. 46 // Too large buffer will cause the system to pause for a long 47 // time when write happens. Also, the largest batch that pebble can 48 // support is 4GB, node will panic if batch size exceeds this limit. 49 maxBufferSize = 256 * 1024 * 1024 50 51 // defaultBufferSize is the default memory allowance of node buffer 52 // that aggregates the writes from above until it's flushed into the 53 // disk. It's meant to be used once the initial sync is finished. 54 // Do not increase the buffer size arbitrarily, otherwise the system 55 // pause time will increase when the database writes happen. 56 defaultBufferSize = 64 * 1024 * 1024 57 ) 58 59 var ( 60 // maxDiffLayers is the maximum diff layers allowed in the layer tree. 61 maxDiffLayers = 128 62 ) 63 64 // layer is the interface implemented by all state layers which includes some 65 // public methods and some additional methods for internal usage. 66 type layer interface { 67 // node retrieves the trie node with the node info. An error will be returned 68 // if the read operation exits abnormally. Specifically, if the layer is 69 // already stale. 70 // 71 // Note: 72 // - the returned node is not a copy, please don't modify it. 73 // - no error will be returned if the requested node is not found in database. 74 node(owner common.Hash, path []byte, depth int) ([]byte, common.Hash, *nodeLoc, error) 75 76 // account directly retrieves the account RLP associated with a particular 77 // hash in the slim data format. An error will be returned if the read 78 // operation exits abnormally. Specifically, if the layer is already stale. 79 // 80 // Note: 81 // - the returned account is not a copy, please don't modify it. 82 // - no error will be returned if the requested account is not found in database. 83 account(hash common.Hash, depth int) ([]byte, error) 84 85 // storage directly retrieves the storage data associated with a particular hash, 86 // within a particular account. An error will be returned if the read operation 87 // exits abnormally. Specifically, if the layer is already stale. 88 // 89 // Note: 90 // - the returned storage data is not a copy, please don't modify it. 91 // - no error will be returned if the requested slot is not found in database. 92 storage(accountHash, storageHash common.Hash, depth int) ([]byte, error) 93 94 // rootHash returns the root hash for which this layer was made. 95 rootHash() common.Hash 96 97 // stateID returns the associated state id of layer. 98 stateID() uint64 99 100 // parentLayer returns the subsequent layer of it, or nil if the disk was reached. 101 parentLayer() layer 102 103 // update creates a new layer on top of the existing layer diff tree with 104 // the provided dirty trie nodes along with the state change set. 105 // 106 // Note, the maps are retained by the method to avoid copying everything. 107 update(root common.Hash, id uint64, block uint64, nodes *nodeSet, states *StateSetWithOrigin) *diffLayer 108 109 // journal commits an entire diff hierarchy to disk into a single journal entry. 110 // This is meant to be used during shutdown to persist the layer without 111 // flattening everything down (bad for reorgs). 112 journal(w io.Writer) error 113 } 114 115 // Config contains the settings for database. 116 type Config struct { 117 StateHistory uint64 // Number of recent blocks to maintain state history for 118 EnableStateIndexing bool // Whether to enable state history indexing for external state access 119 TrieCleanSize int // Maximum memory allowance (in bytes) for caching clean trie nodes 120 StateCleanSize int // Maximum memory allowance (in bytes) for caching clean state data 121 WriteBufferSize int // Maximum memory allowance (in bytes) for write buffer 122 ReadOnly bool // Flag whether the database is opened in read only mode 123 124 // Testing configurations 125 SnapshotNoBuild bool // Flag Whether the state generation is allowed 126 NoAsyncFlush bool // Flag whether the background buffer flushing is allowed 127 NoAsyncGeneration bool // Flag whether the background generation is allowed 128 } 129 130 // sanitize checks the provided user configurations and changes anything that's 131 // unreasonable or unworkable. 132 func (c *Config) sanitize() *Config { 133 conf := *c 134 if conf.WriteBufferSize > maxBufferSize { 135 log.Warn("Sanitizing invalid node buffer size", "provided", common.StorageSize(conf.WriteBufferSize), "updated", common.StorageSize(maxBufferSize)) 136 conf.WriteBufferSize = maxBufferSize 137 } 138 return &conf 139 } 140 141 // fields returns a list of attributes of config for printing. 142 func (c *Config) fields() []interface{} { 143 var list []interface{} 144 if c.ReadOnly { 145 list = append(list, "readonly", true) 146 } 147 if c.SnapshotNoBuild { 148 list = append(list, "snapshot", false) 149 } 150 list = append(list, "triecache", common.StorageSize(c.TrieCleanSize)) 151 list = append(list, "statecache", common.StorageSize(c.StateCleanSize)) 152 list = append(list, "buffer", common.StorageSize(c.WriteBufferSize)) 153 154 if c.StateHistory == 0 { 155 list = append(list, "history", "entire chain") 156 } else { 157 list = append(list, "history", fmt.Sprintf("last %d blocks", c.StateHistory)) 158 } 159 return list 160 } 161 162 // Defaults contains default settings for Ethereum mainnet. 163 var Defaults = &Config{ 164 StateHistory: params.FullImmutabilityThreshold, 165 TrieCleanSize: defaultTrieCleanSize, 166 StateCleanSize: defaultStateCleanSize, 167 WriteBufferSize: defaultBufferSize, 168 } 169 170 // ReadOnly is the config in order to open database in read only mode. 171 var ReadOnly = &Config{ReadOnly: true} 172 173 // nodeHasher is the function to compute the hash of supplied node blob. 174 type nodeHasher func([]byte) (common.Hash, error) 175 176 // merkleNodeHasher computes the hash of the given merkle node. 177 func merkleNodeHasher(blob []byte) (common.Hash, error) { 178 if len(blob) == 0 { 179 return types.EmptyRootHash, nil 180 } 181 return crypto.Keccak256Hash(blob), nil 182 } 183 184 // verkleNodeHasher computes the hash of the given verkle node. 185 func verkleNodeHasher(blob []byte) (common.Hash, error) { 186 if len(blob) == 0 { 187 return types.EmptyVerkleHash, nil 188 } 189 n, err := verkle.ParseNode(blob, 0) 190 if err != nil { 191 return common.Hash{}, err 192 } 193 return n.Commit().Bytes(), nil 194 } 195 196 // Database is a multiple-layered structure for maintaining in-memory states 197 // along with its dirty trie nodes. It consists of one persistent base layer 198 // backed by a key-value store, on top of which arbitrarily many in-memory diff 199 // layers are stacked. The memory diffs can form a tree with branching, but the 200 // disk layer is singleton and common to all. If a reorg goes deeper than the 201 // disk layer, a batch of reverse diffs can be applied to rollback. The deepest 202 // reorg that can be handled depends on the amount of state histories tracked 203 // in the disk. 204 // 205 // At most one readable and writable database can be opened at the same time in 206 // the whole system which ensures that only one database writer can operate the 207 // persistent state. Unexpected open operations can cause the system to panic. 208 type Database struct { 209 // readOnly is the flag whether the mutation is allowed to be applied. 210 // It will be set automatically when the database is journaled during 211 // the shutdown to reject all following unexpected mutations. 212 readOnly bool // Flag if database is opened in read only mode 213 waitSync bool // Flag if database is deactivated due to initial state sync 214 isVerkle bool // Flag if database is used for verkle tree 215 hasher nodeHasher // Trie node hasher 216 217 config *Config // Configuration for database 218 diskdb ethdb.Database // Persistent storage for matured trie nodes 219 tree *layerTree // The group for all known layers 220 freezer ethdb.ResettableAncientStore // Freezer for storing trie histories, nil possible in tests 221 lock sync.RWMutex // Lock to prevent mutations from happening at the same time 222 indexer *historyIndexer // History indexer 223 } 224 225 // New attempts to load an already existing layer from a persistent key-value 226 // store (with a number of memory layers from a journal). If the journal is not 227 // matched with the base persistent layer, all the recorded diff layers are discarded. 228 func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database { 229 if config == nil { 230 config = Defaults 231 } 232 config = config.sanitize() 233 234 db := &Database{ 235 readOnly: config.ReadOnly, 236 isVerkle: isVerkle, 237 config: config, 238 diskdb: diskdb, 239 hasher: merkleNodeHasher, 240 } 241 // Establish a dedicated database namespace tailored for verkle-specific 242 // data, ensuring the isolation of both verkle and merkle tree data. It's 243 // important to note that the introduction of a prefix won't lead to 244 // substantial storage overhead, as the underlying database will efficiently 245 // compress the shared key prefix. 246 if isVerkle { 247 db.diskdb = rawdb.NewTable(diskdb, string(rawdb.VerklePrefix)) 248 db.hasher = verkleNodeHasher 249 } 250 // Construct the layer tree by resolving the in-disk singleton state 251 // and in-memory layer journal. 252 db.tree = newLayerTree(db.loadLayers()) 253 254 // Repair the state history, which might not be aligned with the state 255 // in the key-value store due to an unclean shutdown. 256 if err := db.repairHistory(); err != nil { 257 log.Crit("Failed to repair state history", "err", err) 258 } 259 // Disable database in case node is still in the initial state sync stage. 260 if rawdb.ReadSnapSyncStatusFlag(diskdb) == rawdb.StateSyncRunning && !db.readOnly { 261 if err := db.Disable(); err != nil { 262 log.Crit("Failed to disable database", "err", err) // impossible to happen 263 } 264 } 265 // Resolving the state snapshot generation progress from the database is 266 // mandatory. This ensures that uncovered flat states are not accessed, 267 // even if background generation is not allowed. If permitted, the generation 268 // might be scheduled. 269 if err := db.setStateGenerator(); err != nil { 270 log.Crit("Failed to setup the generator", "err", err) 271 } 272 // TODO (rjl493456442) disable the background indexing in read-only mode 273 if db.freezer != nil && db.config.EnableStateIndexing { 274 db.indexer = newHistoryIndexer(db.diskdb, db.freezer, db.tree.bottom().stateID()) 275 log.Info("Enabled state history indexing") 276 } 277 fields := config.fields() 278 if db.isVerkle { 279 fields = append(fields, "verkle", true) 280 } 281 log.Info("Initialized path database", fields...) 282 return db 283 } 284 285 // repairHistory truncates leftover state history objects, which may occur due 286 // to an unclean shutdown or other unexpected reasons. 287 func (db *Database) repairHistory() error { 288 // Open the freezer for state history. This mechanism ensures that 289 // only one database instance can be opened at a time to prevent 290 // accidental mutation. 291 ancient, err := db.diskdb.AncientDatadir() 292 if err != nil { 293 // TODO error out if ancient store is disabled. A tons of unit tests 294 // disable the ancient store thus the error here will immediately fail 295 // all of them. Fix the tests first. 296 return nil 297 } 298 freezer, err := rawdb.NewStateFreezer(ancient, db.isVerkle, db.readOnly) 299 if err != nil { 300 log.Crit("Failed to open state history freezer", "err", err) 301 } 302 db.freezer = freezer 303 304 // Reset the entire state histories if the trie database is not initialized 305 // yet. This action is necessary because these state histories are not 306 // expected to exist without an initialized trie database. 307 id := db.tree.bottom().stateID() 308 if id == 0 { 309 frozen, err := db.freezer.Ancients() 310 if err != nil { 311 log.Crit("Failed to retrieve head of state history", "err", err) 312 } 313 if frozen != 0 { 314 // TODO(rjl493456442) would be better to group them into a batch. 315 // 316 // Purge all state history indexing data first 317 rawdb.DeleteStateHistoryIndexMetadata(db.diskdb) 318 rawdb.DeleteStateHistoryIndex(db.diskdb) 319 err := db.freezer.Reset() 320 if err != nil { 321 log.Crit("Failed to reset state histories", "err", err) 322 } 323 log.Info("Truncated extraneous state history") 324 } 325 return nil 326 } 327 // Truncate the extra state histories above in freezer in case it's not 328 // aligned with the disk layer. It might happen after a unclean shutdown. 329 pruned, err := truncateFromHead(db.diskdb, db.freezer, id) 330 if err != nil { 331 log.Crit("Failed to truncate extra state histories", "err", err) 332 } 333 if pruned != 0 { 334 log.Warn("Truncated extra state histories", "number", pruned) 335 } 336 return nil 337 } 338 339 // setStateGenerator loads the state generation progress marker and potentially 340 // resume the state generation if it's permitted. 341 func (db *Database) setStateGenerator() error { 342 // Load the state snapshot generation progress marker to prevent access 343 // to uncovered states. 344 generator, root, err := loadGenerator(db.diskdb, db.hasher) 345 if err != nil { 346 return err 347 } 348 if generator == nil { 349 // Initialize an empty generator to rebuild the state snapshot from scratch 350 generator = &journalGenerator{ 351 Marker: []byte{}, 352 } 353 } 354 // Short circuit if the whole state snapshot has already been fully generated. 355 // The generator will be left as nil in disk layer for representing the whole 356 // state snapshot is available for accessing. 357 if generator.Done { 358 return nil 359 } 360 var origin uint64 361 if len(generator.Marker) >= 8 { 362 origin = binary.BigEndian.Uint64(generator.Marker) 363 } 364 stats := &generatorStats{ 365 origin: origin, 366 start: time.Now(), 367 accounts: generator.Accounts, 368 slots: generator.Slots, 369 storage: common.StorageSize(generator.Storage), 370 } 371 dl := db.tree.bottom() 372 373 // Disable the background snapshot building in these circumstances: 374 // - the database is opened in read only mode 375 // - the snapshot build is explicitly disabled 376 // - the database is opened in verkle tree mode 377 noBuild := db.readOnly || db.config.SnapshotNoBuild || db.isVerkle 378 379 // Construct the generator and link it to the disk layer, ensuring that the 380 // generation progress is resolved to prevent accessing uncovered states 381 // regardless of whether background state snapshot generation is allowed. 382 dl.setGenerator(newGenerator(db.diskdb, noBuild, generator.Marker, stats)) 383 384 // Short circuit if the background generation is not permitted 385 if noBuild || db.waitSync { 386 return nil 387 } 388 stats.log("Starting snapshot generation", root, generator.Marker) 389 dl.generator.run(root) 390 391 // Block until the generation completes. It's the feature used in 392 // unit tests. 393 if db.config.NoAsyncGeneration { 394 <-dl.generator.done 395 } 396 return nil 397 } 398 399 // Update adds a new layer into the tree, if that can be linked to an existing 400 // old parent. It is disallowed to insert a disk layer (the origin of all). Apart 401 // from that this function will flatten the extra diff layers at bottom into disk 402 // to only keep 128 diff layers in memory by default. 403 // 404 // The passed in maps(nodes, states) will be retained to avoid copying everything. 405 // Therefore, these maps must not be changed afterwards. 406 // 407 // The supplied parentRoot and root must be a valid trie hash value. 408 func (db *Database) Update(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *StateSetWithOrigin) error { 409 // Hold the lock to prevent concurrent mutations. 410 db.lock.Lock() 411 defer db.lock.Unlock() 412 413 // Short circuit if the mutation is not allowed. 414 if err := db.modifyAllowed(); err != nil { 415 return err 416 } 417 if err := db.tree.add(root, parentRoot, block, nodes, states); err != nil { 418 return err 419 } 420 // Keep 128 diff layers in the memory, persistent layer is 129th. 421 // - head layer is paired with HEAD state 422 // - head-1 layer is paired with HEAD-1 state 423 // - head-127 layer(bottom-most diff layer) is paired with HEAD-127 state 424 // - head-128 layer(disk layer) is paired with HEAD-128 state 425 return db.tree.cap(root, maxDiffLayers) 426 } 427 428 // Commit traverses downwards the layer tree from a specified layer with the 429 // provided state root and all the layers below are flattened downwards. It 430 // can be used alone and mostly for test purposes. 431 func (db *Database) Commit(root common.Hash, report bool) error { 432 // Hold the lock to prevent concurrent mutations. 433 db.lock.Lock() 434 defer db.lock.Unlock() 435 436 // Short circuit if the mutation is not allowed. 437 if err := db.modifyAllowed(); err != nil { 438 return err 439 } 440 return db.tree.cap(root, 0) 441 } 442 443 // Disable deactivates the database and invalidates all available state layers 444 // as stale to prevent access to the persistent state, which is in the syncing 445 // stage. 446 func (db *Database) Disable() error { 447 db.lock.Lock() 448 defer db.lock.Unlock() 449 450 // Short circuit if the database is in read only mode. 451 if db.readOnly { 452 return errDatabaseReadOnly 453 } 454 // Prevent duplicated disable operation. 455 if db.waitSync { 456 log.Error("Reject duplicated disable operation") 457 return nil 458 } 459 db.waitSync = true 460 461 // Terminate the state generator if it's active and mark the disk layer 462 // as stale to prevent access to persistent state. 463 disk := db.tree.bottom() 464 if err := disk.terminate(); err != nil { 465 return err 466 } 467 disk.markStale() 468 469 // Write the initial sync flag to persist it across restarts. 470 rawdb.WriteSnapSyncStatusFlag(db.diskdb, rawdb.StateSyncRunning) 471 log.Info("Disabled trie database due to state sync") 472 return nil 473 } 474 475 // Enable activates database and resets the state tree with the provided persistent 476 // state root once the state sync is finished. 477 func (db *Database) Enable(root common.Hash) error { 478 db.lock.Lock() 479 defer db.lock.Unlock() 480 481 // Short circuit if the database is in read only mode. 482 if db.readOnly { 483 return errDatabaseReadOnly 484 } 485 // Ensure the provided state root matches the stored one. 486 stored, err := db.hasher(rawdb.ReadAccountTrieNode(db.diskdb, nil)) 487 if err != nil { 488 return err 489 } 490 if stored != root { 491 return fmt.Errorf("state root mismatch: stored %x, synced %x", stored, root) 492 } 493 // Drop the stale state journal in persistent database and 494 // reset the persistent state id back to zero. 495 batch := db.diskdb.NewBatch() 496 rawdb.DeleteTrieJournal(batch) 497 rawdb.DeleteSnapshotRoot(batch) 498 rawdb.WritePersistentStateID(batch, 0) 499 if err := batch.Write(); err != nil { 500 return err 501 } 502 // Clean up all state histories in freezer. Theoretically 503 // all root->id mappings should be removed as well. Since 504 // mappings can be huge and might take a while to clear 505 // them, just leave them in disk and wait for overwriting. 506 if db.freezer != nil { 507 // TODO(rjl493456442) would be better to group them into a batch. 508 // 509 // Purge all state history indexing data first 510 rawdb.DeleteStateHistoryIndexMetadata(db.diskdb) 511 rawdb.DeleteStateHistoryIndex(db.diskdb) 512 if err := db.freezer.Reset(); err != nil { 513 return err 514 } 515 } 516 // Re-enable the database as the final step. 517 db.waitSync = false 518 rawdb.WriteSnapSyncStatusFlag(db.diskdb, rawdb.StateSyncFinished) 519 520 // Re-construct a new disk layer backed by persistent state 521 // and schedule the state snapshot generation if it's permitted. 522 db.tree.init(generateSnapshot(db, root, db.isVerkle || db.config.SnapshotNoBuild)) 523 524 // After snap sync, the state of the database may have changed completely. 525 // To ensure the history indexer always matches the current state, we must: 526 // 1. Close any existing indexer 527 // 2. Re-initialize the indexer so it starts indexing from the new state root. 528 if db.indexer != nil && db.freezer != nil && db.config.EnableStateIndexing { 529 db.indexer.close() 530 db.indexer = newHistoryIndexer(db.diskdb, db.freezer, db.tree.bottom().stateID()) 531 log.Info("Re-enabled state history indexing") 532 } 533 log.Info("Rebuilt trie database", "root", root) 534 return nil 535 } 536 537 // Recover rollbacks the database to a specified historical point. 538 // The state is supported as the rollback destination only if it's 539 // canonical state and the corresponding trie histories are existent. 540 // 541 // The supplied root must be a valid trie hash value. 542 func (db *Database) Recover(root common.Hash) error { 543 db.lock.Lock() 544 defer db.lock.Unlock() 545 546 // Short circuit if rollback operation is not supported 547 if err := db.modifyAllowed(); err != nil { 548 return err 549 } 550 if db.freezer == nil { 551 return errors.New("state rollback is non-supported") 552 } 553 // Short circuit if the target state is not recoverable 554 if !db.Recoverable(root) { 555 return errStateUnrecoverable 556 } 557 // Apply the state histories upon the disk layer in order 558 var ( 559 start = time.Now() 560 dl = db.tree.bottom() 561 ) 562 for dl.rootHash() != root { 563 h, err := readHistory(db.freezer, dl.stateID()) 564 if err != nil { 565 return err 566 } 567 dl, err = dl.revert(h) 568 if err != nil { 569 return err 570 } 571 // reset layer with newly created disk layer. It must be 572 // done after each revert operation, otherwise the new 573 // disk layer won't be accessible from outside. 574 db.tree.init(dl) 575 } 576 rawdb.DeleteTrieJournal(db.diskdb) 577 578 // Explicitly sync the key-value store to ensure all recent writes are 579 // flushed to disk. This step is crucial to prevent a scenario where 580 // recent key-value writes are lost due to an application panic, while 581 // the associated state histories have already been removed, resulting 582 // in the inability to perform a state rollback. 583 if err := db.diskdb.SyncKeyValue(); err != nil { 584 return err 585 } 586 _, err := truncateFromHead(db.diskdb, db.freezer, dl.stateID()) 587 if err != nil { 588 return err 589 } 590 log.Debug("Recovered state", "root", root, "elapsed", common.PrettyDuration(time.Since(start))) 591 return nil 592 } 593 594 // Recoverable returns the indicator if the specified state is recoverable. 595 // 596 // The supplied root must be a valid trie hash value. 597 func (db *Database) Recoverable(root common.Hash) bool { 598 // Ensure the requested state is a known state. 599 id := rawdb.ReadStateID(db.diskdb, root) 600 if id == nil { 601 return false 602 } 603 // Recoverable state must be below the disk layer. The recoverable 604 // state only refers to the state that is currently not available, 605 // but can be restored by applying state history. 606 dl := db.tree.bottom() 607 if *id >= dl.stateID() { 608 return false 609 } 610 // This is a temporary workaround for the unavailability of the freezer in 611 // dev mode. As a consequence, the Pathdb loses the ability for deep reorg 612 // in certain cases. 613 // TODO(rjl493456442): Implement the in-memory ancient store. 614 if db.freezer == nil { 615 return false 616 } 617 // Ensure the requested state is a canonical state and all state 618 // histories in range [id+1, disklayer.ID] are present and complete. 619 return checkHistories(db.freezer, *id+1, dl.stateID()-*id, func(m *meta) error { 620 if m.parent != root { 621 return errors.New("unexpected state history") 622 } 623 root = m.root 624 return nil 625 }) == nil 626 } 627 628 // Close closes the trie database and the held freezer. 629 func (db *Database) Close() error { 630 db.lock.Lock() 631 defer db.lock.Unlock() 632 633 // Set the database to read-only mode to prevent all 634 // following mutations. 635 db.readOnly = true 636 637 // Block until the background flushing is finished. It must 638 // be done before terminating the potential background snapshot 639 // generator. 640 dl := db.tree.bottom() 641 if err := dl.terminate(); err != nil { 642 return err 643 } 644 dl.resetCache() // release the memory held by clean cache 645 646 // Terminate the background state history indexer 647 if db.indexer != nil { 648 db.indexer.close() 649 } 650 // Close the attached state history freezer. 651 if db.freezer == nil { 652 return nil 653 } 654 return db.freezer.Close() 655 } 656 657 // Size returns the current storage size of the memory cache in front of the 658 // persistent database layer. 659 func (db *Database) Size() (diffs common.StorageSize, nodes common.StorageSize) { 660 db.tree.forEach(func(layer layer) { 661 if diff, ok := layer.(*diffLayer); ok { 662 diffs += common.StorageSize(diff.size()) 663 } 664 if disk, ok := layer.(*diskLayer); ok { 665 nodes += disk.size() 666 } 667 }) 668 return diffs, nodes 669 } 670 671 // modifyAllowed returns the indicator if mutation is allowed. This function 672 // assumes the db.lock is already held. 673 func (db *Database) modifyAllowed() error { 674 if db.readOnly { 675 return errDatabaseReadOnly 676 } 677 if db.waitSync { 678 return errDatabaseWaitSync 679 } 680 return nil 681 } 682 683 // AccountHistory inspects the account history within the specified range. 684 // 685 // Start: State ID of the first history object for the query. 0 implies the first 686 // available object is selected as the starting point. 687 // 688 // End: State ID of the last history for the query. 0 implies the last available 689 // object is selected as the ending point. Note end is included in the query. 690 func (db *Database) AccountHistory(address common.Address, start, end uint64) (*HistoryStats, error) { 691 return accountHistory(db.freezer, address, start, end) 692 } 693 694 // StorageHistory inspects the storage history within the specified range. 695 // 696 // Start: State ID of the first history object for the query. 0 implies the first 697 // available object is selected as the starting point. 698 // 699 // End: State ID of the last history for the query. 0 implies the last available 700 // object is selected as the ending point. Note end is included in the query. 701 // 702 // Note, slot refers to the hash of the raw slot key. 703 func (db *Database) StorageHistory(address common.Address, slot common.Hash, start uint64, end uint64) (*HistoryStats, error) { 704 return storageHistory(db.freezer, address, slot, start, end) 705 } 706 707 // HistoryRange returns the block numbers associated with earliest and latest 708 // state history in the local store. 709 func (db *Database) HistoryRange() (uint64, uint64, error) { 710 return historyRange(db.freezer) 711 } 712 713 // IndexProgress returns the indexing progress made so far. It provides the 714 // number of states that remain unindexed. 715 func (db *Database) IndexProgress() (uint64, error) { 716 if db.indexer == nil { 717 return 0, nil 718 } 719 return db.indexer.progress() 720 } 721 722 // AccountIterator creates a new account iterator for the specified root hash and 723 // seeks to a starting account hash. 724 func (db *Database) AccountIterator(root common.Hash, seek common.Hash) (AccountIterator, error) { 725 db.lock.RLock() 726 wait := db.waitSync 727 db.lock.RUnlock() 728 if wait { 729 return nil, errDatabaseWaitSync 730 } 731 if !db.tree.bottom().genComplete() { 732 return nil, errNotConstructed 733 } 734 return newFastAccountIterator(db, root, seek) 735 } 736 737 // StorageIterator creates a new storage iterator for the specified root hash and 738 // account. The iterator will be moved to the specific start position. 739 func (db *Database) StorageIterator(root common.Hash, account common.Hash, seek common.Hash) (StorageIterator, error) { 740 db.lock.RLock() 741 wait := db.waitSync 742 db.lock.RUnlock() 743 if wait { 744 return nil, errDatabaseWaitSync 745 } 746 if !db.tree.bottom().genComplete() { 747 return nil, errNotConstructed 748 } 749 return newFastStorageIterator(db, root, account, seek) 750 }