core/state: skip redundant trie Commit for Verkle in stateObject.commit

In Verkle mode, all state objects share a single unified trie
(OpenStorageTrie returns self). During stateDB.commit(), the main
account trie is committed via s.trie.Commit(true), which calls
CollectNodes to traverse and serialize the entire tree. However, each
dirty account's obj.commit() also calls s.trie.Commit(false) on the
same trie object, redundantly traversing the full tree once per dirty
account (N+1 traversals instead of 1).

This also fixes a latent data race where N+1 goroutines concurrently
call CollectNodes on the same BinaryTrie/InternalNode objects.
This commit is contained in:
CPerezz 2026-03-16 23:55:47 +01:00
parent 98b13f342f
commit 567b0eb5ac
No known key found for this signature in database
GPG key ID: 62045F34B97177DD

View file

@ -474,6 +474,14 @@ func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) {
s.origin = s.data.Copy()
return op, nil, nil
}
// In Verkle/binary trie mode, all state objects share one unified trie.
// The main account trie commit in stateDB.commit() already calls
// CollectNodes on this trie, so calling Commit here again would
// redundantly traverse and serialize the entire tree per dirty account.
if s.db.db.TrieDB().IsVerkle() {
s.origin = s.data.Copy()
return op, nil, nil
}
root, nodes := s.trie.Commit(false)
s.data.Root = root
s.origin = s.data.Copy()