diff --git a/core/state/state_object.go b/core/state/state_object.go index 66a9e7b865..8489a18382 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -375,11 +375,11 @@ func (s *stateObject) updateRoot() { // commit obtains a set of dirty storage trie nodes and updates the account data. // The returned set can be nil if nothing to commit. This function assumes all // storage mutations have already been flushed into trie by updateRoot. -func (s *stateObject) commit() (*trienode.NodeSet, error) { +func (s *stateObject) commit() (*trienode.NodeSet, *trienode.Witness, error) { // Short circuit if trie is not even loaded, don't bother with committing anything if s.trie == nil { s.origin = s.data.Copy() - return nil, nil + return nil, nil, nil } // Track the amount of time wasted on committing the storage trie if metrics.EnabledExpensive { @@ -388,15 +388,15 @@ func (s *stateObject) commit() (*trienode.NodeSet, error) { // The trie is currently in an open state and could potentially contain // cached mutations. Call commit to acquire a set of nodes that have been // modified, the set can be nil if nothing to commit. - root, nodes, _, err := s.trie.Commit(false) + root, nodes, witness, err := s.trie.Commit(false) if err != nil { - return nil, err + return nil, nil, err } s.data.Root = root // Update original account data after commit s.origin = s.data.Copy() - return nodes, nil + return nodes, witness, nil } // AddBalance adds amount to s's balance. diff --git a/core/state/statedb.go b/core/state/statedb.go index e26ab92d7e..8781144941 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -1177,6 +1177,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er storageTrieNodesUpdated int storageTrieNodesDeleted int nodes = trienode.NewMergedNodeSet() + witnesses = trienode.NewWitnesses() codeWriter = s.db.DiskDB().NewBatch() ) // Handle all state deletions first @@ -1196,7 +1197,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er obj.dirtyCode = false } // Write any storage changes in the state object to its storage trie - set, err := obj.commit() + set, witness, err := obj.commit() if err != nil { return common.Hash{}, err } @@ -1211,6 +1212,9 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er storageTrieNodesUpdated += updates storageTrieNodesDeleted += deleted } + if witness != nil { + witnesses.Merge(witness) + } } if codeWriter.ValueSize() > 0 { if err := codeWriter.Write(); err != nil { @@ -1222,7 +1226,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er if metrics.EnabledExpensive { start = time.Now() } - root, set, _, err := s.trie.Commit(true) + root, set, witness, err := s.trie.Commit(true) if err != nil { return common.Hash{}, err } @@ -1233,6 +1237,9 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er } accountTrieNodesUpdated, accountTrieNodesDeleted = set.Size() } + if witness != nil { + witnesses.Merge(witness) + } if metrics.EnabledExpensive { s.AccountCommits += time.Since(start) diff --git a/trie/trienode/witness.go b/trie/trienode/witness.go index ba16bdc5f8..ac328a3f15 100644 --- a/trie/trienode/witness.go +++ b/trie/trienode/witness.go @@ -59,3 +59,24 @@ func (w *Witness) Copy() *Witness { } return cpy } + +// Witnesses represents a set of witness for a group of tries. +type Witnesses struct { + witness map[common.Hash]*Witness +} + +// NewWitnesses initializes an empty witness set. +func NewWitnesses() *Witnesses { + return &Witnesses{witness: make(map[common.Hash]*Witness)} +} + +// Merge merges the provided dirty nodes of a trie into the set. The assumption +// is held that no duplicated set belonging to the same trie will be merged twice. +func (set *Witnesses) Merge(other *Witness) error { + _, present := set.witness[other.Owner] + if present { + //return subset.Merge(other.Owner, other.Nodes) + } + set.witness[other.Owner] = other + return nil +}