Skip to content

Commit 72d575a

Browse files
committed
core: database commit
1 parent d502b6b commit 72d575a

File tree

5 files changed

+67
-62
lines changed

5 files changed

+67
-62
lines changed

core/blockchain.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ var (
7373
accountUpdateTimer = metrics.NewRegisteredResettingTimer("chain/account/updates", nil)
7474
accountCommitTimer = metrics.NewRegisteredResettingTimer("chain/account/commits", nil)
7575

76-
storageReadTimer = metrics.NewRegisteredResettingTimer("chain/storage/reads", nil)
77-
storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil)
78-
storageCommitTimer = metrics.NewRegisteredResettingTimer("chain/storage/commits", nil)
76+
storageReadTimer = metrics.NewRegisteredResettingTimer("chain/storage/reads", nil)
77+
storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil)
78+
storageCommitTimer = metrics.NewRegisteredResettingTimer("chain/storage/commits", nil)
79+
databaseCommitTimer = metrics.NewRegisteredResettingTimer("chain/database/commits", nil)
7980

8081
accountCacheHitMeter = metrics.NewRegisteredMeter("chain/account/reads/cache/process/hit", nil)
8182
accountCacheMissMeter = metrics.NewRegisteredMeter("chain/account/reads/cache/process/miss", nil)
@@ -90,9 +91,6 @@ var (
9091
accountReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/account/single/reads", nil)
9192
storageReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/storage/single/reads", nil)
9293

93-
snapshotCommitTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/commits", nil)
94-
triedbCommitTimer = metrics.NewRegisteredResettingTimer("chain/triedb/commits", nil)
95-
9694
blockInsertTimer = metrics.NewRegisteredResettingTimer("chain/inserts", nil)
9795
blockValidationTimer = metrics.NewRegisteredResettingTimer("chain/validation", nil)
9896
blockCrossValidationTimer = metrics.NewRegisteredResettingTimer("chain/crossvalidation", nil)
@@ -2166,10 +2164,9 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
21662164
// Update the metrics touched during block commit
21672165
accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them
21682166
storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them
2169-
snapshotCommitTimer.Update(statedb.SnapshotCommits) // Snapshot commits are complete, we can mark them
2170-
triedbCommitTimer.Update(statedb.TrieDBCommits) // Trie database commits are complete, we can mark them
2167+
databaseCommitTimer.Update(statedb.DatabaseCommits) // Database commits are complete, we can mark them
21712168

2172-
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits)
2169+
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.DatabaseCommits)
21732170
elapsed := time.Since(startTime) + 1 // prevent zero division
21742171
blockInsertTimer.Update(elapsed)
21752172

core/state/database.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/ethereum/go-ethereum/core/types"
2929
"github.com/ethereum/go-ethereum/crypto"
3030
"github.com/ethereum/go-ethereum/ethdb"
31+
"github.com/ethereum/go-ethereum/log"
3132
"github.com/ethereum/go-ethereum/trie"
3233
"github.com/ethereum/go-ethereum/trie/trienode"
3334
"github.com/ethereum/go-ethereum/trie/utils"
@@ -58,6 +59,11 @@ type Database interface {
5859

5960
// Snapshot returns the underlying state snapshot.
6061
Snapshot() *snapshot.Tree
62+
63+
// Commit flushes all pending writes and finalizes the state transition,
64+
// committing the changes to the underlying storage. It returns an error
65+
// if the commit fails.
66+
Commit(update *stateUpdate) error
6167
}
6268

6369
// Trie is a Ethereum Merkle Patricia trie.
@@ -276,6 +282,40 @@ func (db *CachingDB) Snapshot() *snapshot.Tree {
276282
return db.snap
277283
}
278284

285+
// Commit flushes all pending writes and finalizes the state transition,
286+
// committing the changes to the underlying storage. It returns an error
287+
// if the commit fails.
288+
func (db *CachingDB) Commit(update *stateUpdate) error {
289+
// Short circuit if nothing to commit
290+
if update.empty() {
291+
return nil
292+
}
293+
// Commit dirty contract code if any exists
294+
if len(update.codes) > 0 {
295+
writer := db.codedb.Writer()
296+
for _, code := range update.codes {
297+
writer.Put(code.hash, code.blob)
298+
}
299+
if err := writer.Commit(); err != nil {
300+
return err
301+
}
302+
}
303+
// If snapshotting is enabled, update the snapshot tree with this new version
304+
if db.snap != nil && db.snap.Snapshot(update.originRoot) != nil {
305+
if err := db.snap.Update(update.root, update.originRoot, update.accounts, update.storages); err != nil {
306+
log.Warn("Failed to update snapshot tree", "from", update.originRoot, "to", update.root, "err", err)
307+
}
308+
// Keep 128 diff layers in the memory, persistent layer is 129th.
309+
// - head layer is paired with HEAD state
310+
// - head-1 layer is paired with HEAD-1 state
311+
// - head-127 layer(bottom-most diff layer) is paired with HEAD-127 state
312+
if err := db.snap.Cap(update.root, TriesInMemory); err != nil {
313+
log.Warn("Failed to cap snapshot tree", "root", update.root, "layers", TriesInMemory, "err", err)
314+
}
315+
}
316+
return db.triedb.Update(update.root, update.originRoot, update.blockNumber, update.nodes, update.stateSet())
317+
}
318+
279319
// mustCopyTrie returns a deep-copied trie.
280320
func mustCopyTrie(t Trie) Trie {
281321
switch t := t.(type) {

core/state/database_history.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,10 @@ func (db *HistoricDB) TrieDB() *triedb.Database {
148148
func (db *HistoricDB) Snapshot() *snapshot.Tree {
149149
return nil
150150
}
151+
152+
// Commit flushes all pending writes and finalizes the state transition,
153+
// committing the changes to the underlying storage. It returns an error
154+
// if the commit fails.
155+
func (db *HistoricDB) Commit(update *stateUpdate) error {
156+
return errors.New("not implemented")
157+
}

core/state/statedb.go

Lines changed: 13 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"time"
2828

2929
"github.com/ethereum/go-ethereum/common"
30-
"github.com/ethereum/go-ethereum/core/rawdb"
3130
"github.com/ethereum/go-ethereum/core/state/snapshot"
3231
"github.com/ethereum/go-ethereum/core/stateless"
3332
"github.com/ethereum/go-ethereum/core/tracing"
@@ -148,7 +147,7 @@ type StateDB struct {
148147
StorageUpdates time.Duration
149148
StorageCommits time.Duration
150149
SnapshotCommits time.Duration
151-
TrieDBCommits time.Duration
150+
DatabaseCommits time.Duration
152151

153152
AccountLoaded int // Number of accounts retrieved from the database during the state transition
154153
AccountUpdated int // Number of accounts updated during the state transition
@@ -1155,7 +1154,7 @@ func (s *StateDB) GetTrie() Trie {
11551154

11561155
// commit gathers the state mutations accumulated along with the associated
11571156
// trie changes, resetting all internal flags with the new state as the base.
1158-
func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNumber uint64) (*stateUpdate, error) {
1157+
func (s *StateDB) commit(deleteEmptyObjects bool, rawStorageKey bool, blockNumber uint64) (*stateUpdate, error) {
11591158
// Short circuit in case any database failure occurred earlier.
11601159
if s.dbErr != nil {
11611160
return nil, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
@@ -1209,7 +1208,7 @@ func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNum
12091208
// the same block, account deletions must be processed first. This ensures
12101209
// that the storage trie nodes deleted during destruction and recreated
12111210
// during subsequent resurrection can be combined correctly.
1212-
deletes, delNodes, err := s.handleDestruction(noStorageWiping)
1211+
deletes, delNodes, err := s.handleDestruction(rawStorageKey)
12131212
if err != nil {
12141213
return nil, err
12151214
}
@@ -1303,57 +1302,19 @@ func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNum
13031302
// Clear all internal flags and update state root at the end.
13041303
s.mutations = make(map[common.Address]*mutation)
13051304
s.stateObjectsDestruct = make(map[common.Address]*stateObject)
1305+
s.reader, _ = s.db.Reader(root)
13061306

13071307
origin := s.originalRoot
13081308
s.originalRoot = root
13091309

1310-
return newStateUpdate(noStorageWiping, origin, root, blockNumber, deletes, updates, nodes), nil
1311-
}
1310+
update := newStateUpdate(rawStorageKey, origin, root, blockNumber, deletes, updates, nodes)
13121311

1313-
// commitAndFlush is a wrapper of commit which also commits the state mutations
1314-
// to the configured data stores.
1315-
func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool, noStorageWiping bool) (*stateUpdate, error) {
1316-
ret, err := s.commit(deleteEmptyObjects, noStorageWiping, block)
1317-
if err != nil {
1312+
start = time.Now()
1313+
if err := s.db.Commit(update); err != nil {
13181314
return nil, err
13191315
}
1320-
// Commit dirty contract code if any exists
1321-
if db := s.db.TrieDB().Disk(); db != nil && len(ret.codes) > 0 {
1322-
batch := db.NewBatch()
1323-
for _, code := range ret.codes {
1324-
rawdb.WriteCode(batch, code.hash, code.blob)
1325-
}
1326-
if err := batch.Write(); err != nil {
1327-
return nil, err
1328-
}
1329-
}
1330-
if !ret.empty() {
1331-
// If snapshotting is enabled, update the snapshot tree with this new version
1332-
if snap := s.db.Snapshot(); snap != nil && snap.Snapshot(ret.originRoot) != nil {
1333-
start := time.Now()
1334-
if err := snap.Update(ret.root, ret.originRoot, ret.accounts, ret.storages); err != nil {
1335-
log.Warn("Failed to update snapshot tree", "from", ret.originRoot, "to", ret.root, "err", err)
1336-
}
1337-
// Keep 128 diff layers in the memory, persistent layer is 129th.
1338-
// - head layer is paired with HEAD state
1339-
// - head-1 layer is paired with HEAD-1 state
1340-
// - head-127 layer(bottom-most diff layer) is paired with HEAD-127 state
1341-
if err := snap.Cap(ret.root, TriesInMemory); err != nil {
1342-
log.Warn("Failed to cap snapshot tree", "root", ret.root, "layers", TriesInMemory, "err", err)
1343-
}
1344-
s.SnapshotCommits += time.Since(start)
1345-
}
1346-
// If trie database is enabled, commit the state update as a new layer
1347-
if db := s.db.TrieDB(); db != nil {
1348-
start := time.Now()
1349-
if err := db.Update(ret.root, ret.originRoot, block, ret.nodes, ret.stateSet()); err != nil {
1350-
return nil, err
1351-
}
1352-
s.TrieDBCommits += time.Since(start)
1353-
}
1354-
}
1355-
s.reader, _ = s.db.Reader(s.originalRoot)
1356-
return ret, err
1316+
s.DatabaseCommits = time.Since(start)
1317+
return update, nil
13571318
}
13581319

13591320
// Commit writes the state mutations into the configured data stores.
@@ -1370,8 +1331,8 @@ func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool, noStorag
13701331
// Since self-destruction was deprecated with the Cancun fork and there are
13711332
// no empty accounts left that could be deleted by EIP-158, storage wiping
13721333
// should not occur.
1373-
func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool, noStorageWiping bool) (common.Hash, error) {
1374-
ret, err := s.commitAndFlush(block, deleteEmptyObjects, noStorageWiping)
1334+
func (s *StateDB) Commit(blockNumber uint64, deleteEmptyObjects bool, rawStorageKey bool) (common.Hash, error) {
1335+
ret, err := s.commit(deleteEmptyObjects, rawStorageKey, blockNumber)
13751336
if err != nil {
13761337
return common.Hash{}, err
13771338
}
@@ -1380,8 +1341,8 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool, noStorageWiping
13801341

13811342
// CommitWithUpdate writes the state mutations and returns both the root hash and the state update.
13821343
// This is useful for tracking state changes at the blockchain level.
1383-
func (s *StateDB) CommitWithUpdate(block uint64, deleteEmptyObjects bool, noStorageWiping bool) (common.Hash, *stateUpdate, error) {
1384-
ret, err := s.commitAndFlush(block, deleteEmptyObjects, noStorageWiping)
1344+
func (s *StateDB) CommitWithUpdate(blockNumber uint64, deleteEmptyObjects bool, rawStorageKey bool) (common.Hash, *stateUpdate, error) {
1345+
ret, err := s.commit(deleteEmptyObjects, rawStorageKey, blockNumber)
13851346
if err != nil {
13861347
return common.Hash{}, nil, err
13871348
}

core/state/statedb_fuzz_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ func (test *stateTest) run() bool {
229229
} else {
230230
state.IntermediateRoot(true) // call intermediateRoot at the transaction boundary
231231
}
232-
ret, err := state.commitAndFlush(0, true, false) // call commit at the block boundary
232+
ret, err := state.commit(true, false, 0) // call commit at the block boundary
233233
if err != nil {
234234
panic(err)
235235
}

0 commit comments

Comments
 (0)