Skip to content

Commit bada592

Browse files
committed
core: database commit
1 parent df98ba4 commit bada592

File tree

6 files changed

+72
-70
lines changed

6 files changed

+72
-70
lines changed

core/blockchain.go

Lines changed: 8 additions & 11 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)
@@ -2191,11 +2189,10 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
21912189
}
21922190

21932191
// Update the metrics touched during block commit
2194-
stats.AccountCommits = statedb.AccountCommits // Account commits are complete, we can mark them
2195-
stats.StorageCommits = statedb.StorageCommits // Storage commits are complete, we can mark them
2196-
stats.SnapshotCommit = statedb.SnapshotCommits // Snapshot commits are complete, we can mark them
2197-
stats.TrieDBCommit = statedb.TrieDBCommits // Trie database commits are complete, we can mark them
2198-
stats.BlockWrite = time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits
2192+
stats.AccountCommits = statedb.AccountCommits // Account commits are complete, we can mark them
2193+
stats.StorageCommits = statedb.StorageCommits // Storage commits are complete, we can mark them
2194+
stats.DBCommit = statedb.DatabaseCommits // Trie database commits are complete, we can mark them
2195+
stats.BlockWrite = time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.DatabaseCommits
21992196

22002197
elapsed := time.Since(startTime) + 1 // prevent zero division
22012198
stats.TotalTime = elapsed

core/blockchain_stats.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ type ExecuteStats struct {
4848
Execution time.Duration // Time spent on the EVM execution
4949
Validation time.Duration // Time spent on the block validation
5050
CrossValidation time.Duration // Optional, time spent on the block cross validation
51-
SnapshotCommit time.Duration // Time spent on snapshot commit
52-
TrieDBCommit time.Duration // Time spent on database commit
51+
DBCommit time.Duration // Time spent on database commit
5352
BlockWrite time.Duration // Time spent on block write
5453
TotalTime time.Duration // The total time spent on block execution
5554
MgasPerSecond float64 // The million gas processed per second
@@ -80,8 +79,7 @@ func (s *ExecuteStats) reportMetrics() {
8079
blockExecutionTimer.Update(s.Execution) // The time spent on EVM processing
8180
blockValidationTimer.Update(s.Validation) // The time spent on block validation
8281
blockCrossValidationTimer.Update(s.CrossValidation) // The time spent on stateless cross validation
83-
snapshotCommitTimer.Update(s.SnapshotCommit) // Snapshot commits are complete, we can mark them
84-
triedbCommitTimer.Update(s.TrieDBCommit) // Trie database commits are complete, we can mark them
82+
databaseCommitTimer.Update(s.DBCommit) // Trie database commits are complete, we can mark them
8583
blockWriteTimer.Update(s.BlockWrite) // The time spent on block write
8684
blockInsertTimer.Update(s.TotalTime) // The total time spent on block execution
8785
chainMgaspsMeter.Update(time.Duration(s.MgasPerSecond)) // TODO(rjl493456442) generalize the ResettingTimer
@@ -127,7 +125,7 @@ Block write: %v
127125
common.PrettyDuration(s.StorageReads), s.StorageLoaded,
128126
common.PrettyDuration(s.AccountHashes+s.AccountCommits+s.AccountUpdates),
129127
common.PrettyDuration(s.StorageCommits+s.StorageUpdates),
130-
common.PrettyDuration(s.TrieDBCommit+s.SnapshotCommit), common.PrettyDuration(s.BlockWrite),
128+
common.PrettyDuration(s.DBCommit), common.PrettyDuration(s.BlockWrite),
131129
s.StateReadCacheStats)
132130
for _, line := range strings.Split(msg, "\n") {
133131
if line == "" {

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/bintrie"
3334
"github.com/ethereum/go-ethereum/trie/transitiontrie"
@@ -60,6 +61,11 @@ type Database interface {
6061

6162
// Snapshot returns the underlying state snapshot.
6263
Snapshot() *snapshot.Tree
64+
65+
// Commit flushes all pending writes and finalizes the state transition,
66+
// committing the changes to the underlying storage. It returns an error
67+
// if the commit fails.
68+
Commit(update *stateUpdate) error
6369
}
6470

6571
// Trie is a Ethereum Merkle Patricia trie.
@@ -280,6 +286,40 @@ func (db *CachingDB) Snapshot() *snapshot.Tree {
280286
return db.snap
281287
}
282288

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

3030
"github.com/ethereum/go-ethereum/common"
31-
"github.com/ethereum/go-ethereum/core/rawdb"
3231
"github.com/ethereum/go-ethereum/core/state/snapshot"
3332
"github.com/ethereum/go-ethereum/core/stateless"
3433
"github.com/ethereum/go-ethereum/core/tracing"
@@ -149,8 +148,7 @@ type StateDB struct {
149148
StorageReads time.Duration
150149
StorageUpdates time.Duration
151150
StorageCommits time.Duration
152-
SnapshotCommits time.Duration
153-
TrieDBCommits time.Duration
151+
DatabaseCommits time.Duration
154152

155153
AccountLoaded int // Number of accounts retrieved from the database during the state transition
156154
AccountUpdated int // Number of accounts updated during the state transition
@@ -1160,7 +1158,7 @@ func (s *StateDB) GetTrie() Trie {
11601158

11611159
// commit gathers the state mutations accumulated along with the associated
11621160
// trie changes, resetting all internal flags with the new state as the base.
1163-
func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNumber uint64) (*stateUpdate, error) {
1161+
func (s *StateDB) commit(deleteEmptyObjects bool, rawStorageKey bool, blockNumber uint64) (*stateUpdate, error) {
11641162
// Short circuit in case any database failure occurred earlier.
11651163
if s.dbErr != nil {
11661164
return nil, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
@@ -1214,7 +1212,7 @@ func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNum
12141212
// the same block, account deletions must be processed first. This ensures
12151213
// that the storage trie nodes deleted during destruction and recreated
12161214
// during subsequent resurrection can be combined correctly.
1217-
deletes, delNodes, err := s.handleDestruction(noStorageWiping)
1215+
deletes, delNodes, err := s.handleDestruction(rawStorageKey)
12181216
if err != nil {
12191217
return nil, err
12201218
}
@@ -1308,57 +1306,19 @@ func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNum
13081306
// Clear all internal flags and update state root at the end.
13091307
s.mutations = make(map[common.Address]*mutation)
13101308
s.stateObjectsDestruct = make(map[common.Address]*stateObject)
1309+
s.reader, _ = s.db.Reader(root)
13111310

13121311
origin := s.originalRoot
13131312
s.originalRoot = root
13141313

1315-
return newStateUpdate(noStorageWiping, origin, root, blockNumber, deletes, updates, nodes), nil
1316-
}
1314+
update := newStateUpdate(rawStorageKey, origin, root, blockNumber, deletes, updates, nodes)
13171315

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

13641324
// Commit writes the state mutations into the configured data stores.
@@ -1375,8 +1335,8 @@ func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool, noStorag
13751335
// Since self-destruction was deprecated with the Cancun fork and there are
13761336
// no empty accounts left that could be deleted by EIP-158, storage wiping
13771337
// should not occur.
1378-
func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool, noStorageWiping bool) (common.Hash, error) {
1379-
ret, err := s.commitAndFlush(block, deleteEmptyObjects, noStorageWiping)
1338+
func (s *StateDB) Commit(blockNumber uint64, deleteEmptyObjects bool, rawStorageKey bool) (common.Hash, error) {
1339+
ret, err := s.commit(deleteEmptyObjects, rawStorageKey, blockNumber)
13801340
if err != nil {
13811341
return common.Hash{}, err
13821342
}
@@ -1385,8 +1345,8 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool, noStorageWiping
13851345

13861346
// CommitWithUpdate writes the state mutations and returns both the root hash and the state update.
13871347
// This is useful for tracking state changes at the blockchain level.
1388-
func (s *StateDB) CommitWithUpdate(block uint64, deleteEmptyObjects bool, noStorageWiping bool) (common.Hash, *stateUpdate, error) {
1389-
ret, err := s.commitAndFlush(block, deleteEmptyObjects, noStorageWiping)
1348+
func (s *StateDB) CommitWithUpdate(blockNumber uint64, deleteEmptyObjects bool, rawStorageKey bool) (common.Hash, *stateUpdate, error) {
1349+
ret, err := s.commit(deleteEmptyObjects, rawStorageKey, blockNumber)
13901350
if err != nil {
13911351
return common.Hash{}, nil, err
13921352
}

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)