@@ -50,6 +50,10 @@ type StateDB struct {
5050 trie Trie
5151 logger * tracing.Hooks
5252
53+ // originalRoot is the pre-state root, before any changes were made.
54+ // It will be updated when the Commit is called.
55+ originalRoot common.Hash
56+
5357 // This map holds 'live' objects, which will get modified while processing a state transition.
5458 stateObjects map [common.Address ]* stateObject
5559 stateObjectsPending map [common.Address ]struct {} // State objects finalized but not yet written to the trie
@@ -96,6 +100,7 @@ type StateDB struct {
96100 StorageHashes time.Duration
97101 StorageUpdates time.Duration
98102 StorageCommits time.Duration
103+ TrieDBCommits time.Duration
99104
100105 AccountUpdated int
101106 StorageUpdated int
@@ -120,6 +125,7 @@ func New(root common.Hash, db Database) (*StateDB, error) {
120125 return & StateDB {
121126 db : db ,
122127 trie : tr ,
128+ originalRoot : root ,
123129 stateObjects : make (map [common.Address ]* stateObject ),
124130 stateObjectsPending : make (map [common.Address ]struct {}),
125131 stateObjectsDirty : make (map [common.Address ]struct {}),
@@ -665,6 +671,7 @@ func (s *StateDB) Copy() *StateDB {
665671 state := & StateDB {
666672 db : s .db ,
667673 trie : s .db .CopyTrie (s .trie ),
674+ originalRoot : s .originalRoot ,
668675 stateObjects : make (map [common.Address ]* stateObject , len (s .journal .dirties )),
669676 stateObjectsPending : make (map [common.Address ]struct {}, len (s .stateObjectsPending )),
670677 stateObjectsDirty : make (map [common.Address ]struct {}, len (s .journal .dirties )),
@@ -852,9 +859,11 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
852859 }
853860 // Commit objects to the trie, measuring the elapsed time
854861 var (
855- accountTrieNodes int
856- storageTrieNodes int
857- nodes = trie .NewMergedNodeSet ()
862+ accountTrieNodesUpdated int
863+ accountTrieNodesDeleted int
864+ storageTrieNodesUpdated int
865+ storageTrieNodesDeleted int
866+ nodes = trie .NewMergedNodeSet ()
858867 )
859868 codeWriter := s .db .DiskDB ().NewBatch ()
860869 for addr := range s .stateObjectsDirty {
@@ -874,7 +883,9 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
874883 if err := nodes .Merge (set ); err != nil {
875884 return common.Hash {}, err
876885 }
877- storageTrieNodes += set .Len ()
886+ updates , deleted := set .Size ()
887+ storageTrieNodesUpdated += updates
888+ storageTrieNodesDeleted += deleted
878889 }
879890 }
880891 // If the contract is destructed, the storage is still left in the
@@ -904,7 +915,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
904915 if err := nodes .Merge (set ); err != nil {
905916 return common.Hash {}, err
906917 }
907- accountTrieNodes = set .Len ()
918+ accountTrieNodesUpdated , accountTrieNodesDeleted = set .Size ()
908919 }
909920 // Report the commit metrics
910921 s .AccountCommits += time .Since (start )
@@ -913,18 +924,32 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
913924 storageUpdatedMeter .Mark (int64 (s .StorageUpdated ))
914925 accountDeletedMeter .Mark (int64 (s .AccountDeleted ))
915926 storageDeletedMeter .Mark (int64 (s .StorageDeleted ))
916- accountTrieCommittedMeter .Mark (int64 (accountTrieNodes ))
917- storageTriesCommittedMeter .Mark (int64 (storageTrieNodes ))
927+ accountTrieUpdatedMeter .Mark (int64 (accountTrieNodesUpdated ))
928+ accountTrieDeletedMeter .Mark (int64 (accountTrieNodesDeleted ))
929+ storageTriesUpdatedMeter .Mark (int64 (storageTrieNodesUpdated ))
930+ storageTriesDeletedMeter .Mark (int64 (storageTrieNodesDeleted ))
918931 s .AccountUpdated , s .AccountDeleted = 0 , 0
919932 s .StorageUpdated , s .StorageDeleted = 0 , 0
920933
921934 if len (s .stateObjectsDestruct ) > 0 {
922935 s .stateObjectsDestruct = make (map [common.Address ]struct {})
923936 }
924- if err := s .db .TrieDB ().Update (nodes ); err != nil {
925- return common.Hash {}, err
937+ if root == (common.Hash {}) {
938+ root = types .EmptyRootHash
939+ }
940+ origin := s .originalRoot
941+ if origin == (common.Hash {}) {
942+ origin = types .EmptyRootHash
943+ }
944+ if root != origin {
945+ start := time .Now ()
946+ if err := s .db .TrieDB ().Update (nodes ); err != nil {
947+ return common.Hash {}, err
948+ }
949+ s .originalRoot = root
950+ s .TrieDBCommits += time .Since (start )
926951 }
927- return root , err
952+ return root , nil
928953}
929954
930955// Prepare handles the preparatory steps for executing a state transition with.
0 commit comments