mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
trie: review feedback, mainly docs + minor changes
This commit is contained in:
parent
d76431b8df
commit
b809acc9b0
3 changed files with 31 additions and 26 deletions
|
|
@ -26,6 +26,10 @@ import (
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// LeafChanSize is the size of the leafCh. It's a pretty arbitrary number, to allow
|
||||||
|
// some paralellism but not incur too much memory overhead.
|
||||||
|
const LeafChanSize = 200
|
||||||
|
|
||||||
// Leaf represents a trie leaf value
|
// Leaf represents a trie leaf value
|
||||||
type Leaf struct {
|
type Leaf struct {
|
||||||
size int // size of the rlp data (estimate)
|
size int // size of the rlp data (estimate)
|
||||||
|
|
@ -34,6 +38,12 @@ type Leaf struct {
|
||||||
vnodes bool // set to true if the node (possibly) contains a valueNode
|
vnodes bool // set to true if the node (possibly) contains a valueNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// committer is a type used for the trie Commit operation. A committer has some
|
||||||
|
// internal preallocated temp space, and also a callback that is invoked when
|
||||||
|
// leaves are committed. The leafs are passed through the `leafCh`, to allow
|
||||||
|
// some level of paralellism.
|
||||||
|
// By 'some level' of paralellism, it's still the case that all leaves will be
|
||||||
|
// processed sequentially - onleaf will never be called in paralell or out of order.
|
||||||
type committer struct {
|
type committer struct {
|
||||||
tmp sliceBuffer
|
tmp sliceBuffer
|
||||||
sha keccakState
|
sha keccakState
|
||||||
|
|
@ -52,11 +62,17 @@ var committerPool = sync.Pool{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newCommitter creates a new committer or picks one from the pool, and
|
||||||
|
// initializes the leafCh, if needed.
|
||||||
|
// In case no onleaf-callback is provided, the committer does not
|
||||||
|
// use a channel-based commit, but inlined.
|
||||||
|
// Typically, the account trie is committed with a channel-based leaf-commit,
|
||||||
|
// whereas storage tries are committed 'inline'.
|
||||||
func newCommitter(onleaf LeafCallback) *committer {
|
func newCommitter(onleaf LeafCallback) *committer {
|
||||||
h := committerPool.Get().(*committer)
|
h := committerPool.Get().(*committer)
|
||||||
h.onleaf = onleaf
|
h.onleaf = onleaf
|
||||||
if onleaf != nil {
|
if onleaf != nil {
|
||||||
h.leafCh = make(chan *Leaf, 200) // arbitrary number
|
h.leafCh = make(chan *Leaf, LeafChanSize)
|
||||||
}
|
}
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
@ -200,8 +216,7 @@ func (h *committer) store(n node, db *Database, force bool, hasVnodeChildren boo
|
||||||
}
|
}
|
||||||
|
|
||||||
// commitLoop does the actual insert + leaf callback for nodes
|
// commitLoop does the actual insert + leaf callback for nodes
|
||||||
func (h *committer) commitLoop(db *Database, wg *sync.WaitGroup) {
|
func (h *committer) commitLoop(db *Database) {
|
||||||
defer wg.Done()
|
|
||||||
for item := range h.leafCh {
|
for item := range h.leafCh {
|
||||||
var (
|
var (
|
||||||
hash = item.hash
|
hash = item.hash
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ import (
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// pureHasher is a type used for the trie Hash operation. A pureHasher has some
|
||||||
|
// internal preallocated temp space
|
||||||
type pureHasher struct {
|
type pureHasher struct {
|
||||||
sha keccakState
|
sha keccakState
|
||||||
|
|
||||||
|
|
@ -30,7 +32,7 @@ type pureHasher struct {
|
||||||
tmpKey []byte
|
tmpKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashers live in a global db.
|
// pureHasherPool holds pureHashers
|
||||||
var pureHasherPool = sync.Pool{
|
var pureHasherPool = sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() interface{} {
|
||||||
return &pureHasher{
|
return &pureHasher{
|
||||||
|
|
@ -139,7 +141,7 @@ func (h *pureHasher) shortnodeToHash(n *shortNode, force bool) node {
|
||||||
func (h *pureHasher) fullnodeToHash(n *fullNode, force bool) node {
|
func (h *pureHasher) fullnodeToHash(n *fullNode, force bool) node {
|
||||||
h.tmp.Reset()
|
h.tmp.Reset()
|
||||||
// Generate the RLP encoding of the node
|
// Generate the RLP encoding of the node
|
||||||
if err := rlp.Encode(&h.tmp, n); err != nil {
|
if err := n.EncodeRLP(&h.tmp); err != nil {
|
||||||
panic("encode error: " + err.Error())
|
panic("encode error: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
30
trie/trie.go
30
trie/trie.go
|
|
@ -410,27 +410,8 @@ func (t *Trie) Hash() common.Hash {
|
||||||
return common.BytesToHash(hash.(hashNode))
|
return common.BytesToHash(hash.(hashNode))
|
||||||
}
|
}
|
||||||
|
|
||||||
// oldCommit is the old implementation of Commit, which uses the
|
// Commit writes all nodes to the trie's memory database, tracking the internal
|
||||||
// regular hasher.
|
|
||||||
// It writes all nodes to the trie's memory database, tracking the internal
|
|
||||||
// and external (for account tries) references.
|
// and external (for account tries) references.
|
||||||
func (t *Trie) oldCommit(onleaf LeafCallback) (root common.Hash, err error) {
|
|
||||||
if t.db == nil {
|
|
||||||
panic("commit called on trie with nil database")
|
|
||||||
}
|
|
||||||
if t.root == nil {
|
|
||||||
return emptyRoot, nil
|
|
||||||
}
|
|
||||||
h := newHasher(onleaf)
|
|
||||||
defer returnHasherToPool(h)
|
|
||||||
hash, cached, err := h.hash(t.root, t.db, true)
|
|
||||||
if err != nil {
|
|
||||||
return common.Hash{}, err
|
|
||||||
}
|
|
||||||
t.root = cached
|
|
||||||
return common.BytesToHash(hash.(hashNode)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
|
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")
|
||||||
|
|
@ -450,10 +431,17 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
if onleaf != nil {
|
if onleaf != nil {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go h.commitLoop(t.db, &wg)
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
h.commitLoop(t.db)
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
_, err = h.commit(t.root, t.db, true)
|
_, err = h.commit(t.root, t.db, true)
|
||||||
if onleaf != nil {
|
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)
|
close(h.leafCh)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue