mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
trie: make commit use channel for insert + leaf callbacks
This commit is contained in:
parent
4a0a205589
commit
3c8ec1b569
3 changed files with 49 additions and 17 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit b5eb9900ee2147b40d3e681fe86efa4fd693959a
|
Subproject commit 25f480521dae1937841bbcb034e862c4dfd53256
|
||||||
|
|
@ -25,10 +25,17 @@ import (
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Leaf struct {
|
||||||
|
size int
|
||||||
|
hash common.Hash
|
||||||
|
node node
|
||||||
|
}
|
||||||
|
|
||||||
type hasher struct {
|
type hasher struct {
|
||||||
tmp sliceBuffer
|
tmp sliceBuffer
|
||||||
sha keccakState
|
sha keccakState
|
||||||
onleaf LeafCallback
|
onleaf LeafCallback
|
||||||
|
leafCh chan *Leaf
|
||||||
}
|
}
|
||||||
|
|
||||||
// keccakState wraps sha3.state. In addition to the usual hash methods, it also supports
|
// keccakState wraps sha3.state. In addition to the usual hash methods, it also supports
|
||||||
|
|
@ -178,16 +185,37 @@ func (h *hasher) store(n node, db *Database, force bool) (node, error) {
|
||||||
if hash == nil {
|
if hash == nil {
|
||||||
hash = h.makeHashNode(h.tmp)
|
hash = h.makeHashNode(h.tmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if db != nil {
|
if db != nil {
|
||||||
|
h.leafCh <- &Leaf{
|
||||||
|
size: len(h.tmp),
|
||||||
|
hash: common.BytesToHash(hash),
|
||||||
|
node: n,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hash, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *hasher) makeHashNode(data []byte) hashNode {
|
||||||
|
n := make(hashNode, h.sha.Size())
|
||||||
|
h.sha.Reset()
|
||||||
|
h.sha.Write(data)
|
||||||
|
h.sha.Read(n)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// commitLoop does the actual insert + leaf callback for nodes
|
||||||
|
func (h *hasher) commitLoop(db *Database, wg *sync.WaitGroup) {
|
||||||
|
defer wg.Done()
|
||||||
|
for item := range h.leafCh {
|
||||||
|
var (
|
||||||
|
hash = item.hash
|
||||||
|
size = item.size
|
||||||
|
n = item.node
|
||||||
|
)
|
||||||
// We are pooling the trie nodes into an intermediate memory cache
|
// We are pooling the trie nodes into an intermediate memory cache
|
||||||
hash := common.BytesToHash(hash)
|
|
||||||
|
|
||||||
db.lock.Lock()
|
db.lock.Lock()
|
||||||
db.insert(hash, len(h.tmp), n)
|
db.insert(hash, size, n)
|
||||||
db.lock.Unlock()
|
db.lock.Unlock()
|
||||||
|
|
||||||
// Track external references from account->storage trie
|
|
||||||
if h.onleaf != nil {
|
if h.onleaf != nil {
|
||||||
switch n := n.(type) {
|
switch n := n.(type) {
|
||||||
case *shortNode:
|
case *shortNode:
|
||||||
|
|
@ -203,13 +231,4 @@ func (h *hasher) store(n node, db *Database, force bool) (node, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hash, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *hasher) makeHashNode(data []byte) hashNode {
|
|
||||||
n := make(hashNode, h.sha.Size())
|
|
||||||
h.sha.Reset()
|
|
||||||
h.sha.Write(data)
|
|
||||||
h.sha.Read(n)
|
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
trie/trie.go
15
trie/trie.go
|
|
@ -20,6 +20,7 @@ package trie
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
@ -415,7 +416,18 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
|
||||||
if t.db == nil {
|
if t.db == nil {
|
||||||
panic("commit called on trie with nil database")
|
panic("commit called on trie with nil database")
|
||||||
}
|
}
|
||||||
hash, cached, err := t.hashRoot(t.db, onleaf)
|
if t.root == nil {
|
||||||
|
return emptyRoot, nil
|
||||||
|
}
|
||||||
|
h := newHasher(onleaf)
|
||||||
|
h.leafCh = make(chan *Leaf, 200) // arbitrary number
|
||||||
|
defer returnHasherToPool(h)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go h.commitLoop(t.db, &wg)
|
||||||
|
hash, cached, err := h.hash(t.root, t.db, true)
|
||||||
|
close(h.leafCh)
|
||||||
|
wg.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -431,3 +443,4 @@ func (t *Trie) hashRoot(db *Database, onleaf LeafCallback) (node, node, error) {
|
||||||
defer returnHasherToPool(h)
|
defer returnHasherToPool(h)
|
||||||
return h.hash(t.root, db, true)
|
return h.hash(t.root, db, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue