trie: separate hashes and committer, collapse on commit
* trie: make db insert use size instead of full data * core/state: minor optimization in state onleaf allocation * trie: implement dedicated committer and hasher * trie: use dedicated committer/hasher * trie: linter nitpicks * core/state, trie: avoid unnecessary storage trie load+commit * trie: review feedback, mainly docs + minor changes * trie: start deprecating old hasher * trie: fix misspell+lint * trie: deprecate hasher.go, make proof framework use new hasher * trie: rename pure_committer/hasher to committer/hasher * trie, core/state: fix review concerns * trie: more review concerns * trie: make commit collapse into hashnode, don't touch dirtyness * trie: goimports fixes * trie: remove panics
This commit is contained in:
committed by
GitHub
parent
4cc89a5a32
commit
5a9c96454e
44
trie/trie.go
44
trie/trie.go
@ -20,6 +20,7 @@ package trie
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
@ -415,19 +416,52 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
|
||||
if t.db == nil {
|
||||
panic("commit called on trie with nil database")
|
||||
}
|
||||
hash, cached, err := t.hashRoot(t.db, onleaf)
|
||||
if t.root == nil {
|
||||
return emptyRoot, nil
|
||||
}
|
||||
rootHash := t.Hash()
|
||||
h := newCommitter()
|
||||
defer returnCommitterToPool(h)
|
||||
// Do a quick check if we really need to commit, before we spin
|
||||
// up goroutines. This can happen e.g. if we load a trie for reading storage
|
||||
// values, but don't write to it.
|
||||
if !h.commitNeeded(t.root) {
|
||||
return rootHash, nil
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
if onleaf != nil {
|
||||
h.onleaf = onleaf
|
||||
h.leafCh = make(chan *leaf, leafChanSize)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
h.commitLoop(t.db)
|
||||
}()
|
||||
}
|
||||
var newRoot hashNode
|
||||
newRoot, err = h.Commit(t.root, t.db)
|
||||
if onleaf != nil {
|
||||
// The leafch is created in newCommitter if there was an onleaf callback
|
||||
// provided. The commitLoop only _reads_ from it, and the commit
|
||||
// operation was the sole writer. Therefore, it's safe to close this
|
||||
// channel here.
|
||||
close(h.leafCh)
|
||||
wg.Wait()
|
||||
}
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
t.root = cached
|
||||
return common.BytesToHash(hash.(hashNode)), nil
|
||||
t.root = newRoot
|
||||
return rootHash, nil
|
||||
}
|
||||
|
||||
// hashRoot calculates the root hash of the given trie
|
||||
func (t *Trie) hashRoot(db *Database, onleaf LeafCallback) (node, node, error) {
|
||||
if t.root == nil {
|
||||
return hashNode(emptyRoot.Bytes()), nil, nil
|
||||
}
|
||||
h := newHasher(onleaf)
|
||||
h := newHasher()
|
||||
defer returnHasherToPool(h)
|
||||
return h.hash(t.root, db, true)
|
||||
hashed, cached := h.hash(t.root, true)
|
||||
return hashed, cached, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user