cmd, trie: remove cmd/gc and hide some types in trie

This commit is contained in:
Daniel Liu 2025-03-25 20:23:33 +08:00 committed by Daniel Liu
parent 91cbe818ea
commit 7198179c2a
9 changed files with 210 additions and 480 deletions

View file

@ -1,270 +0,0 @@
package main
import (
"flag"
"fmt"
"os"
"os/signal"
"runtime"
"sync"
"sync/atomic"
"time"
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/lru"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/state"
"github.com/XinFinOrg/XDPoSChain/eth/ethconfig"
"github.com/XinFinOrg/XDPoSChain/ethdb"
"github.com/XinFinOrg/XDPoSChain/ethdb/leveldb"
"github.com/XinFinOrg/XDPoSChain/rlp"
"github.com/XinFinOrg/XDPoSChain/trie"
)
var (
dir = flag.String("dir", "", "directory to XDPoSChain chaindata")
cacheSize = flag.Int("size", 1000000, "LRU cache size")
sercureKey = []byte("secure-key-")
nWorker = runtime.NumCPU() / 2
cleanAddress = []common.Address{common.BlockSignersBinary}
cache *lru.Cache[common.Hash, struct{}]
finish = int32(0)
running = true
stateRoots = make(chan TrieRoot)
)
type TrieRoot struct {
trie *trie.SecureTrie
number uint64
}
type StateNode struct {
node trie.Node
path []byte
}
type ResultProcessNode struct {
index int
number int
newNodes [17]*StateNode
keys [17]*[]byte
}
func main() {
flag.Parse()
db, _ := leveldb.New(*dir, ethconfig.Defaults.DatabaseCache, utils.MakeDatabaseHandles(0), "", false)
lddb := rawdb.NewDatabase(db)
head := rawdb.ReadHeadBlockHash(lddb)
currentHeader := rawdb.ReadHeader(lddb, head, *rawdb.ReadHeaderNumber(lddb, head))
tridb := trie.NewDatabase(lddb)
catchEventInterupt(db)
cache = lru.NewCache[common.Hash, struct{}](*cacheSize)
go func() {
for i := uint64(1); i <= currentHeader.Number.Uint64(); i++ {
hash := rawdb.ReadCanonicalHash(lddb, i)
root := rawdb.ReadHeader(lddb, hash, i).Root
trieRoot, err := trie.NewSecure(root, tridb)
if err != nil {
continue
}
if running {
stateRoots <- TrieRoot{trieRoot, i}
} else {
break
}
}
if running {
close(stateRoots)
}
}()
for trieRoot := range stateRoots {
atomic.StoreInt32(&finish, 1)
if running {
for _, address := range cleanAddress {
enc := trieRoot.trie.Get(address.Bytes())
var data state.Account
rlp.DecodeBytes(enc, &data)
fmt.Println(time.Now().Format(time.RFC3339), "Start clean state address ", address.Hex(), " at block ", trieRoot.number)
signerRoot, err := resolveHash(data.Root[:], db)
if err != nil {
fmt.Println(time.Now().Format(time.RFC3339), "Not found clean state address ", address.Hex(), " at block ", trieRoot.number)
continue
}
batch := db.NewBatch()
count := 1
list := []*StateNode{{node: signerRoot}}
for len(list) > 0 {
newList, total := findNewNodes(list, db, batch)
count = count + 17*len(newList)
list = removeNodesNil(newList, total)
}
fmt.Println(time.Now().Format(time.RFC3339), "Finish clean state address ", address.Hex(), " at block ", trieRoot.number, " keys ", count)
err = batch.Write()
if err != nil {
fmt.Println(time.Now().Format(time.RFC3339), "Write batch leveldb error", err)
os.Exit(1)
}
}
} else {
break
}
atomic.StoreInt32(&finish, 0)
}
fmt.Println(time.Now(), "compact")
lddb.Compact(nil, nil)
lddb.Close()
fmt.Println(time.Now(), "end")
}
func removeNodesNil(list [][17]*StateNode, length int) []*StateNode {
results := make([]*StateNode, length)
index := 0
for _, nodes := range list {
for _, node := range nodes {
if node != nil {
results[index] = node
index++
}
}
}
return results
}
func catchEventInterupt(db *leveldb.Database) {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for sig := range c {
fmt.Println("catch event interrupt ", sig, running, finish)
running = false
if atomic.LoadInt32(&finish) == 0 {
close(stateRoots)
db.Close()
os.Exit(1)
}
}
}()
}
func resolveHash(n trie.HashNode, db *leveldb.Database) (trie.Node, error) {
if cache.Contains(common.BytesToHash(n)) {
return nil, &trie.MissingNodeError{}
}
enc, err := db.Get(n)
if err != nil || enc == nil {
return nil, &trie.MissingNodeError{}
}
return trie.MustDecodeNode(n, enc), nil
}
func getAllChilds(n StateNode, db *leveldb.Database) ([17]*StateNode, error) {
childs := [17]*StateNode{}
switch node := n.node.(type) {
case *trie.FullNode:
// Full Node, move to the first non-nil child.
for i := 0; i < len(node.Children); i++ {
child := node.Children[i]
if child != nil {
childNode := child
var err error = nil
if _, ok := child.(trie.HashNode); ok {
childNode, err = resolveHash(child.(trie.HashNode), db)
}
if err == nil {
childs[i] = &StateNode{node: childNode, path: append(n.path, byte(i))}
} else {
_, ok := err.(*trie.MissingNodeError)
if !ok {
return childs, err
}
}
}
}
case *trie.ShortNode:
// Short Node, return the pointer singleton child
childNode := node.Val
var err error = nil
if _, ok := node.Val.(trie.HashNode); ok {
childNode, err = resolveHash(node.Val.(trie.HashNode), db)
}
if err == nil {
childs[0] = &StateNode{node: childNode, path: append(n.path, node.Key...)}
} else {
_, ok := err.(*trie.MissingNodeError)
if !ok {
return childs, err
}
}
}
return childs, nil
}
func processNodes(node StateNode, db *leveldb.Database) ([17]*StateNode, [17]*[]byte, int) {
hash, _ := node.node.Cache()
commonHash := common.BytesToHash(hash)
newNodes := [17]*StateNode{}
keys := [17]*[]byte{}
number := 0
if !cache.Contains(commonHash) {
childNodes, err := getAllChilds(node, db)
if err != nil {
fmt.Println("Error when get all childs node : ", common.Bytes2Hex(node.path), err)
os.Exit(1)
}
for i, child := range childNodes {
if child != nil {
if _, ok := child.node.(trie.ValueNode); ok {
buf := append(sercureKey, child.path...)
keys[i] = &buf
} else {
hash, _ := child.node.Cache()
var bytes []byte = hash
keys[i] = &bytes
newNodes[i] = child
number++
}
}
}
cache.Add(commonHash, struct{}{})
}
return newNodes, keys, number
}
func findNewNodes(nodes []*StateNode, db *leveldb.Database, batchlvdb ethdb.Batch) ([][17]*StateNode, int) {
length := len(nodes)
chunkSize := length / nWorker
if len(nodes)%nWorker != 0 {
chunkSize++
}
childNodes := make([][17]*StateNode, length)
results := make(chan ResultProcessNode)
wg := sync.WaitGroup{}
wg.Add(length)
for i := 0; i < nWorker; i++ {
from := i * chunkSize
to := from + chunkSize
if to > length {
to = length
}
go func(from int, to int) {
for j := from; j < to; j++ {
childs, keys, number := processNodes(*nodes[j], db)
go func(result ResultProcessNode) {
results <- result
}(ResultProcessNode{j, number, childs, keys})
}
}(from, to)
}
total := 0
go func() {
for result := range results {
childNodes[result.index] = result.newNodes
total = total + result.number
for _, key := range result.keys {
if key != nil {
batchlvdb.Delete(*key)
}
}
wg.Done()
}
}()
wg.Wait()
close(results)
return childNodes, total
}

View file

@ -35,7 +35,7 @@ const leafChanSize = 200
type leaf struct {
size int // size of the rlp data (estimate)
hash common.Hash // hash of rlp data
node Node // the Node to commit
node node // the Node to commit
vnodes bool // set to true if the Node (possibly) contains a ValueNode
}
@ -75,13 +75,13 @@ func returnCommitterToPool(h *committer) {
}
// commitNeeded returns 'false' if the given Node is already in sync with Db
func (c *committer) commitNeeded(n Node) bool {
hash, dirty := n.Cache()
func (c *committer) commitNeeded(n node) bool {
hash, dirty := n.cache()
return hash == nil || dirty
}
// commit collapses a Node down into a hash Node and inserts it into the database
func (c *committer) Commit(n Node, db *Database) (HashNode, error) {
func (c *committer) Commit(n node, db *Database) (hashNode, error) {
if db == nil {
return nil, errors.New("no Db provided")
}
@ -89,22 +89,22 @@ func (c *committer) Commit(n Node, db *Database) (HashNode, error) {
if err != nil {
return nil, err
}
return h.(HashNode), nil
return h.(hashNode), nil
}
// commit collapses a Node down into a hash Node and inserts it into the database
func (c *committer) commit(n Node, db *Database, force bool) (Node, error) {
func (c *committer) commit(n node, db *Database, force bool) (node, error) {
// if this path is clean, use available cached data
hash, dirty := n.Cache()
hash, dirty := n.cache()
if hash != nil && !dirty {
return hash, nil
}
// Commit children, then parent, and remove remove the dirty flag.
switch cn := n.(type) {
case *ShortNode:
case *shortNode:
// Commit child
collapsed := cn.copy()
if _, ok := cn.Val.(ValueNode); !ok {
if _, ok := cn.Val.(valueNode); !ok {
if childV, err := c.commit(cn.Val, db, false); err != nil {
return nil, err
} else {
@ -114,12 +114,12 @@ func (c *committer) commit(n Node, db *Database, force bool) (Node, error) {
// The key needs to be copied, since we're delivering it to database
collapsed.Key = hexToCompact(cn.Key)
hashedNode := c.store(collapsed, db, force, true)
if hn, ok := hashedNode.(HashNode); ok {
if hn, ok := hashedNode.(hashNode); ok {
return hn, nil
} else {
return collapsed, nil
}
case *FullNode:
case *fullNode:
hashedKids, hasVnodes, err := c.commitChildren(cn, db, force)
if err != nil {
return nil, err
@ -128,23 +128,23 @@ func (c *committer) commit(n Node, db *Database, force bool) (Node, error) {
collapsed.Children = hashedKids
hashedNode := c.store(collapsed, db, force, hasVnodes)
if hn, ok := hashedNode.(HashNode); ok {
if hn, ok := hashedNode.(hashNode); ok {
return hn, nil
} else {
return collapsed, nil
}
case ValueNode:
case valueNode:
return c.store(cn, db, force, false), nil
// hashnodes aren't stored
case HashNode:
case hashNode:
return cn, nil
}
return hash, nil
}
// commitChildren commits the children of the given fullnode
func (c *committer) commitChildren(n *FullNode, db *Database, force bool) ([17]Node, bool, error) {
var children [17]Node
func (c *committer) commitChildren(n *fullNode, db *Database, force bool) ([17]node, bool, error) {
var children [17]node
var hasValueNodeChildren = false
for i, child := range n.Children {
if child == nil {
@ -155,7 +155,7 @@ func (c *committer) commitChildren(n *FullNode, db *Database, force bool) ([17]N
return children, false, err
}
children[i] = hnode
if _, ok := hnode.(ValueNode); ok {
if _, ok := hnode.(valueNode); ok {
hasValueNodeChildren = true
}
}
@ -165,14 +165,14 @@ func (c *committer) commitChildren(n *FullNode, db *Database, force bool) ([17]N
// store hashes the Node n and if we have a storage layer specified, it writes
// the key/value pair to it and tracks any Node->child references as well as any
// Node->external trie references.
func (c *committer) store(n Node, db *Database, force bool, hasVnodeChildren bool) Node {
func (c *committer) store(n node, db *Database, force bool, hasVnodeChildren bool) node {
// Larger nodes are replaced by their hash and stored in the database.
var (
hash, _ = n.Cache()
hash, _ = n.cache()
size int
)
if hash == nil {
if vn, ok := n.(ValueNode); ok {
if vn, ok := n.(valueNode); ok {
c.tmp.Reset()
if err := rlp.Encode(&c.tmp, vn); err != nil {
panic("encode error: " + err.Error())
@ -226,13 +226,13 @@ func (c *committer) commitLoop(db *Database) {
db.Lock.Unlock()
if c.onleaf != nil && hasVnodes {
switch n := n.(type) {
case *ShortNode:
if child, ok := n.Val.(ValueNode); ok {
case *shortNode:
if child, ok := n.Val.(valueNode); ok {
c.onleaf(child, hash)
}
case *FullNode:
case *fullNode:
for i := 0; i < 16; i++ {
if child, ok := n.Children[i].(ValueNode); ok {
if child, ok := n.Children[i].(valueNode); ok {
c.onleaf(child, hash)
}
}
@ -241,8 +241,8 @@ func (c *committer) commitLoop(db *Database) {
}
}
func (c *committer) makeHashNode(data []byte) HashNode {
n := make(HashNode, c.sha.Size())
func (c *committer) makeHashNode(data []byte) hashNode {
n := make(hashNode, c.sha.Size())
c.sha.Reset()
c.sha.Write(data)
c.sha.Read(n)
@ -253,12 +253,12 @@ func (c *committer) makeHashNode(data []byte) HashNode {
// rlp-encoding it (zero allocs). This method has been experimentally tried, and with a trie
// with 1000 leafs, the only errors above 1% are on small shortnodes, where this
// method overestimates by 2 or 3 bytes (e.g. 37 instead of 35)
func estimateSize(n Node) int {
func estimateSize(n node) int {
switch n := n.(type) {
case *ShortNode:
case *shortNode:
// A short Node contains a compacted key, and a value.
return 3 + len(n.Key) + estimateSize(n.Val)
case *FullNode:
case *fullNode:
// A full Node contains up to 16 hashes (some nils), and a key
s := 3
for i := 0; i < 16; i++ {
@ -269,9 +269,9 @@ func estimateSize(n Node) int {
}
}
return s
case ValueNode:
case valueNode:
return 1 + len(n)
case HashNode:
case hashNode:
return 1 + len(n)
default:
panic(fmt.Sprintf("Node type %T", n))

View file

@ -95,19 +95,19 @@ type Database struct {
// in the same Cache fields).
type rawNode []byte
func (n rawNode) Cache() (HashNode, bool) { panic("this should never end up in a live trie") }
func (n rawNode) cache() (hashNode, bool) { panic("this should never end up in a live trie") }
func (n rawNode) fstring(ind string) string { panic("this should never end up in a live trie") }
// rawFullNode represents only the useful data content of a full Node, with the
// caches and flags stripped out to minimize its data storage. This type honors
// the same RLP encoding as the original parent.
type rawFullNode [17]Node
type rawFullNode [17]node
func (n rawFullNode) Cache() (HashNode, bool) { panic("this should never end up in a live trie") }
func (n rawFullNode) cache() (hashNode, bool) { panic("this should never end up in a live trie") }
func (n rawFullNode) fstring(ind string) string { panic("this should never end up in a live trie") }
func (n rawFullNode) EncodeRLP(w io.Writer) error {
var nodes [17]Node
var nodes [17]node
for i, child := range n {
if child != nil {
@ -124,16 +124,16 @@ func (n rawFullNode) EncodeRLP(w io.Writer) error {
// the same RLP encoding as the original parent.
type rawShortNode struct {
Key []byte
Val Node
Val node
}
func (n rawShortNode) Cache() (HashNode, bool) { panic("this should never end up in a live trie") }
func (n rawShortNode) cache() (hashNode, bool) { panic("this should never end up in a live trie") }
func (n rawShortNode) fstring(ind string) string { panic("this should never end up in a live trie") }
// cachedNode is all the information we know about a single cached trie node
// in the memory database write layer.
type cachedNode struct {
node Node // Cached collapsed trie Node, or raw rlp data
node node // Cached collapsed trie Node, or raw rlp data
size uint16 // Byte size of the useful cached data
parents uint32 // Number of live nodes referencing this one
@ -167,7 +167,7 @@ func (n *cachedNode) rlp() []byte {
// obj returns the decoded and expanded trie Node, either directly from the Cache,
// or by regenerating it from the rlp encoded blob.
func (n *cachedNode) obj(hash common.Hash) Node {
func (n *cachedNode) obj(hash common.Hash) node {
if node, ok := n.node.(rawNode); ok {
return MustDecodeNode(hash[:], node)
}
@ -188,7 +188,7 @@ func (n *cachedNode) forChilds(onChild func(hash common.Hash)) {
// forGatherChildren traverses the Node hierarchy of a collapsed storage Node and
// invokes the callback for all the hashnode children.
func forGatherChildren(n Node, onChild func(hash common.Hash)) {
func forGatherChildren(n node, onChild func(hash common.Hash)) {
switch n := n.(type) {
case *rawShortNode:
forGatherChildren(n.Val, onChild)
@ -196,9 +196,9 @@ func forGatherChildren(n Node, onChild func(hash common.Hash)) {
for i := 0; i < 16; i++ {
forGatherChildren(n[i], onChild)
}
case HashNode:
case hashNode:
onChild(common.BytesToHash(n))
case ValueNode, nil:
case valueNode, nil:
default:
panic(fmt.Sprintf("unknown Node type: %T", n))
}
@ -206,13 +206,13 @@ func forGatherChildren(n Node, onChild func(hash common.Hash)) {
// simplifyNode traverses the hierarchy of an expanded memory Node and discards
// all the internal caches, returning a Node that only contains the raw data.
func simplifyNode(n Node) Node {
func simplifyNode(n node) node {
switch n := n.(type) {
case *ShortNode:
case *shortNode:
// Short nodes discard the flags and cascade
return &rawShortNode{Key: n.Key, Val: simplifyNode(n.Val)}
case *FullNode:
case *fullNode:
// Full nodes discard the flags and cascade
node := rawFullNode(n.Children)
for i := 0; i < len(node); i++ {
@ -222,7 +222,7 @@ func simplifyNode(n Node) Node {
}
return node
case ValueNode, HashNode, rawNode:
case valueNode, hashNode, rawNode:
return n
default:
@ -232,11 +232,11 @@ func simplifyNode(n Node) Node {
// expandNode traverses the Node hierarchy of a collapsed storage Node and converts
// all fields and keys into expanded memory form.
func expandNode(hash HashNode, n Node) Node {
func expandNode(hash hashNode, n node) node {
switch n := n.(type) {
case *rawShortNode:
// Short nodes need key and child expansion
return &ShortNode{
return &shortNode{
Key: compactToHex(n.Key),
Val: expandNode(nil, n.Val),
flags: NodeFlag{
@ -246,7 +246,7 @@ func expandNode(hash HashNode, n Node) Node {
case rawFullNode:
// Full nodes need child expansion
node := &FullNode{
node := &fullNode{
flags: NodeFlag{
hash: hash,
},
@ -258,7 +258,7 @@ func expandNode(hash HashNode, n Node) Node {
}
return node
case ValueNode, HashNode:
case valueNode, hashNode:
return n
default:
@ -300,7 +300,7 @@ func (db *Database) DiskDB() ethdb.KeyValueStore {
// The blob size must be specified to allow proper size tracking.
// All nodes inserted by this function will be reference tracked
// and in theory should only used for **trie nodes** insertion.
func (db *Database) insert(hash common.Hash, size int, node Node) {
func (db *Database) insert(hash common.Hash, size int, node node) {
// If the Node's already cached, skip
if _, ok := db.dirties[hash]; ok {
return
@ -343,7 +343,7 @@ func (db *Database) InsertPreimage(hash common.Hash, preimage []byte) {
// Node retrieves a cached trie Node from memory, or returns nil if none can be
// found in the memory Cache.
func (db *Database) node(hash common.Hash) Node {
func (db *Database) node(hash common.Hash) node {
// Retrieve the Node from the clean Cache if available
if db.cleans != nil {
if enc := db.cleans.Get(nil, hash[:]); enc != nil {

View file

@ -65,28 +65,28 @@ func returnHasherToPool(h *hasher) {
// hash collapses a Node down into a hash Node, also returning a copy of the
// original Node initialized with the computed hash to replace the original one.
func (h *hasher) hash(n Node, force bool) (hashed Node, cached Node) {
func (h *hasher) hash(n node, force bool) (hashed node, cached node) {
// We're not storing the Node, just hashing, use available cached data
if hash, _ := n.Cache(); hash != nil {
if hash, _ := n.cache(); hash != nil {
return hash, n
}
// Trie not processed yet or needs storage, walk the children
switch n := n.(type) {
case *ShortNode:
case *shortNode:
collapsed, cached := h.hashShortNodeChildren(n)
hashed := h.shortnodeToHash(collapsed, force)
// We need to retain the possibly _not_ hashed Node, in case it was too
// small to be hashed
if hn, ok := hashed.(HashNode); ok {
if hn, ok := hashed.(hashNode); ok {
cached.flags.hash = hn
} else {
cached.flags.hash = nil
}
return hashed, cached
case *FullNode:
case *fullNode:
collapsed, cached := h.hashFullNodeChildren(n)
hashed = h.fullnodeToHash(collapsed, force)
if hn, ok := hashed.(HashNode); ok {
if hn, ok := hashed.(hashNode); ok {
cached.flags.hash = hn
} else {
cached.flags.hash = nil
@ -101,7 +101,7 @@ func (h *hasher) hash(n Node, force bool) (hashed Node, cached Node) {
// hashShortNodeChildren collapses the short Node. The returned collapsed Node
// holds a live reference to the Key, and must not be modified.
// The cached
func (h *hasher) hashShortNodeChildren(n *ShortNode) (collapsed, cached *ShortNode) {
func (h *hasher) hashShortNodeChildren(n *shortNode) (collapsed, cached *shortNode) {
// Hash the short Node's child, caching the newly hashed subtree
collapsed, cached = n.copy(), n.copy()
// Previously, we did copy this one. We don't seem to need to actually
@ -110,13 +110,13 @@ func (h *hasher) hashShortNodeChildren(n *ShortNode) (collapsed, cached *ShortNo
collapsed.Key = hexToCompact(n.Key)
// Unless the child is a valuenode or hashnode, hash it
switch n.Val.(type) {
case *FullNode, *ShortNode:
case *fullNode, *shortNode:
collapsed.Val, cached.Val = h.hash(n.Val, false)
}
return collapsed, cached
}
func (h *hasher) hashFullNodeChildren(n *FullNode) (collapsed *FullNode, cached *FullNode) {
func (h *hasher) hashFullNodeChildren(n *fullNode) (collapsed *fullNode, cached *fullNode) {
// Hash the full Node's children, caching the newly hashed subtrees
cached = n.copy()
collapsed = n.copy()
@ -152,7 +152,7 @@ func (h *hasher) hashFullNodeChildren(n *FullNode) (collapsed *FullNode, cached
// should have hex-type Key, which will be converted (without modification)
// into compact form for RLP encoding.
// If the rlp data is smaller than 32 bytes, `nil` is returned.
func (h *hasher) shortnodeToHash(n *ShortNode, force bool) Node {
func (h *hasher) shortnodeToHash(n *shortNode, force bool) node {
h.tmp.Reset()
if err := rlp.Encode(&h.tmp, n); err != nil {
panic("encode error: " + err.Error())
@ -166,7 +166,7 @@ func (h *hasher) shortnodeToHash(n *ShortNode, force bool) Node {
// shortnodeToHash is used to creates a HashNode from a set of hashNodes, (which
// may contain nil values)
func (h *hasher) fullnodeToHash(n *FullNode, force bool) Node {
func (h *hasher) fullnodeToHash(n *fullNode, force bool) node {
h.tmp.Reset()
// Generate the RLP encoding of the Node
if err := n.EncodeRLP(&h.tmp); err != nil {
@ -180,8 +180,8 @@ func (h *hasher) fullnodeToHash(n *FullNode, force bool) Node {
}
// hashData hashes the provided data
func (h *hasher) hashData(data []byte) HashNode {
n := make(HashNode, 32)
func (h *hasher) hashData(data []byte) hashNode {
n := make(hashNode, 32)
h.sha.Reset()
h.sha.Write(data)
h.sha.Read(n)
@ -192,12 +192,12 @@ func (h *hasher) hashData(data []byte) HashNode {
// Node (for later RLP encoding) aswell as the hashed Node -- unless the
// Node is smaller than 32 bytes, in which case it will be returned as is.
// This method does not do anything on value- or hash-nodes.
func (h *hasher) proofHash(original Node) (collapsed, hashed Node) {
func (h *hasher) proofHash(original node) (collapsed, hashed node) {
switch n := original.(type) {
case *ShortNode:
case *shortNode:
sn, _ := h.hashShortNodeChildren(n)
return sn, h.shortnodeToHash(sn, false)
case *FullNode:
case *fullNode:
fn, _ := h.hashFullNodeChildren(n)
return fn, h.fullnodeToHash(fn, false)
default:

View file

@ -108,7 +108,7 @@ type NodeIterator interface {
// trie, which can be resumed at a later invocation.
type nodeIteratorState struct {
hash common.Hash // Hash of the Node being iterated (nil if not standalone)
node Node // Trie Node being iterated
node node // Trie Node being iterated
parent common.Hash // Hash of the first full ancestor Node (nil if current is the root)
index int // Child to be processed next
pathlen int // Length of the path to this Node
@ -163,7 +163,7 @@ func (it *nodeIterator) Leaf() bool {
func (it *nodeIterator) LeafKey() []byte {
if len(it.stack) > 0 {
if _, ok := it.stack[len(it.stack)-1].node.(ValueNode); ok {
if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok {
return hexToKeybytes(it.path)
}
}
@ -172,7 +172,7 @@ func (it *nodeIterator) LeafKey() []byte {
func (it *nodeIterator) LeafBlob() []byte {
if len(it.stack) > 0 {
if node, ok := it.stack[len(it.stack)-1].node.(ValueNode); ok {
if node, ok := it.stack[len(it.stack)-1].node.(valueNode); ok {
return []byte(node)
}
}
@ -181,7 +181,7 @@ func (it *nodeIterator) LeafBlob() []byte {
func (it *nodeIterator) LeafProof() [][]byte {
if len(it.stack) > 0 {
if _, ok := it.stack[len(it.stack)-1].node.(ValueNode); ok {
if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok {
hasher := newHasher(false)
defer returnHasherToPool(hasher)
proofs := make([][]byte, 0, len(it.stack))
@ -189,7 +189,7 @@ func (it *nodeIterator) LeafProof() [][]byte {
for i, item := range it.stack[:len(it.stack)-1] {
// Gather nodes that end up as hash nodes (or the root)
node, hashed := hasher.proofHash(item.node)
if _, ok := hashed.(HashNode); ok || i == 0 {
if _, ok := hashed.(hashNode); ok || i == 0 {
enc, _ := rlp.EncodeToBytes(node)
proofs = append(proofs, enc)
}
@ -293,7 +293,7 @@ func (it *nodeIterator) peek(descend bool) (*nodeIteratorState, *int, []byte, er
}
func (st *nodeIteratorState) resolve(tr *Trie, path []byte) error {
if hash, ok := st.node.(HashNode); ok {
if hash, ok := st.node.(hashNode); ok {
resolved, err := tr.resolveHash(hash, path)
if err != nil {
return err
@ -306,12 +306,12 @@ func (st *nodeIteratorState) resolve(tr *Trie, path []byte) error {
func (it *nodeIterator) nextChild(parent *nodeIteratorState, ancestor common.Hash) (*nodeIteratorState, []byte, bool) {
switch node := parent.node.(type) {
case *FullNode:
case *fullNode:
// Full Node, move to the first non-nil child.
for i := parent.index + 1; i < len(node.Children); i++ {
child := node.Children[i]
if child != nil {
hash, _ := child.Cache()
hash, _ := child.cache()
state := &nodeIteratorState{
hash: common.BytesToHash(hash),
node: child,
@ -324,10 +324,10 @@ func (it *nodeIterator) nextChild(parent *nodeIteratorState, ancestor common.Has
return state, path, true
}
}
case *ShortNode:
case *shortNode:
// Short Node, return the pointer singleton child
if parent.index < 0 {
hash, _ := node.Val.Cache()
hash, _ := node.Val.cache()
state := &nodeIteratorState{
hash: common.BytesToHash(hash),
node: node.Val,

View file

@ -27,32 +27,32 @@ import (
var indices = []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "[17]"}
type Node interface {
type node interface {
fstring(string) string
Cache() (HashNode, bool)
cache() (hashNode, bool)
}
type (
FullNode struct {
Children [17]Node // Actual trie Node data to encode/decode (needs custom encoder)
fullNode struct {
Children [17]node // Actual trie Node data to encode/decode (needs custom encoder)
flags NodeFlag
}
ShortNode struct {
shortNode struct {
Key []byte
Val Node
Val node
flags NodeFlag
}
HashNode []byte
ValueNode []byte
hashNode []byte
valueNode []byte
)
// nilValueNode is used when collapsing internal trie nodes for hashing, since
// unset children need to serialize correctly.
var nilValueNode = ValueNode(nil)
var nilValueNode = valueNode(nil)
// EncodeRLP encodes a full Node into the consensus RLP format.
func (n *FullNode) EncodeRLP(w io.Writer) error {
var nodes [17]Node
func (n *fullNode) EncodeRLP(w io.Writer) error {
var nodes [17]node
for i, child := range &n.Children {
if child != nil {
@ -64,27 +64,27 @@ func (n *FullNode) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, nodes)
}
func (n *FullNode) copy() *FullNode { copy := *n; return &copy }
func (n *ShortNode) copy() *ShortNode { copy := *n; return &copy }
func (n *fullNode) copy() *fullNode { copy := *n; return &copy }
func (n *shortNode) copy() *shortNode { copy := *n; return &copy }
// NodeFlag contains caching-related metadata about a Node.
type NodeFlag struct {
hash HashNode // cached hash of the Node (may be nil)
hash hashNode // cached hash of the Node (may be nil)
dirty bool // whether the Node has changes that must be written to the database
}
func (n *FullNode) Cache() (HashNode, bool) { return n.flags.hash, n.flags.dirty }
func (n *ShortNode) Cache() (HashNode, bool) { return n.flags.hash, n.flags.dirty }
func (n HashNode) Cache() (HashNode, bool) { return nil, true }
func (n ValueNode) Cache() (HashNode, bool) { return nil, true }
func (n *fullNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty }
func (n *shortNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty }
func (n hashNode) cache() (hashNode, bool) { return nil, true }
func (n valueNode) cache() (hashNode, bool) { return nil, true }
// Pretty printing.
func (n *FullNode) String() string { return n.fstring("") }
func (n *ShortNode) String() string { return n.fstring("") }
func (n HashNode) String() string { return n.fstring("") }
func (n ValueNode) String() string { return n.fstring("") }
func (n *fullNode) String() string { return n.fstring("") }
func (n *shortNode) String() string { return n.fstring("") }
func (n hashNode) String() string { return n.fstring("") }
func (n valueNode) String() string { return n.fstring("") }
func (n *FullNode) fstring(ind string) string {
func (n *fullNode) fstring(ind string) string {
resp := fmt.Sprintf("[\n%s ", ind)
for i, node := range &n.Children {
if node == nil {
@ -95,17 +95,17 @@ func (n *FullNode) fstring(ind string) string {
}
return resp + fmt.Sprintf("\n%s] ", ind)
}
func (n *ShortNode) fstring(ind string) string {
func (n *shortNode) fstring(ind string) string {
return fmt.Sprintf("{%x: %v} ", n.Key, n.Val.fstring(ind+" "))
}
func (n HashNode) fstring(ind string) string {
func (n hashNode) fstring(ind string) string {
return fmt.Sprintf("<%x> ", []byte(n))
}
func (n ValueNode) fstring(ind string) string {
func (n valueNode) fstring(ind string) string {
return fmt.Sprintf("%x ", []byte(n))
}
func MustDecodeNode(hash, buf []byte) Node {
func MustDecodeNode(hash, buf []byte) node {
n, err := decodeNode(hash, buf)
if err != nil {
panic(fmt.Sprintf("Node %x: %v", hash, err))
@ -114,7 +114,7 @@ func MustDecodeNode(hash, buf []byte) Node {
}
// decodeNode parses the RLP encoding of a trie Node.
func decodeNode(hash, buf []byte) (Node, error) {
func decodeNode(hash, buf []byte) (node, error) {
if len(buf) == 0 {
return nil, io.ErrUnexpectedEOF
}
@ -134,7 +134,7 @@ func decodeNode(hash, buf []byte) (Node, error) {
}
}
func decodeShort(hash, elems []byte) (Node, error) {
func decodeShort(hash, elems []byte) (node, error) {
kbuf, rest, err := rlp.SplitString(elems)
if err != nil {
return nil, err
@ -147,17 +147,17 @@ func decodeShort(hash, elems []byte) (Node, error) {
if err != nil {
return nil, fmt.Errorf("invalid value Node: %v", err)
}
return &ShortNode{key, append(ValueNode{}, val...), flag}, nil
return &shortNode{key, append(valueNode{}, val...), flag}, nil
}
r, _, err := decodeRef(rest)
if err != nil {
return nil, wrapError(err, "val")
}
return &ShortNode{key, r, flag}, nil
return &shortNode{key, r, flag}, nil
}
func decodeFull(hash, elems []byte) (*FullNode, error) {
n := &FullNode{flags: NodeFlag{hash: hash}}
func decodeFull(hash, elems []byte) (*fullNode, error) {
n := &fullNode{flags: NodeFlag{hash: hash}}
for i := 0; i < 16; i++ {
cld, rest, err := decodeRef(elems)
if err != nil {
@ -170,14 +170,14 @@ func decodeFull(hash, elems []byte) (*FullNode, error) {
return n, err
}
if len(val) > 0 {
n.Children[16] = append(ValueNode{}, val...)
n.Children[16] = append(valueNode{}, val...)
}
return n, nil
}
const hashLen = len(common.Hash{})
func decodeRef(buf []byte) (Node, []byte, error) {
func decodeRef(buf []byte) (node, []byte, error) {
kind, val, rest, err := rlp.Split(buf)
if err != nil {
return nil, buf, err
@ -196,7 +196,7 @@ func decodeRef(buf []byte) (Node, []byte, error) {
// empty Node
return nil, rest, nil
case kind == rlp.String && len(val) == 32:
return append(HashNode{}, val...), rest, nil
return append(hashNode{}, val...), rest, nil
default:
return nil, nil, fmt.Errorf("invalid RLP string size %d (want 0 or 32)", len(val))
}

View file

@ -38,11 +38,11 @@ import (
func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error {
// Collect all nodes on the path to key.
key = keybytesToHex(key)
var nodes []Node
var nodes []node
tn := t.root
for len(key) > 0 && tn != nil {
switch n := tn.(type) {
case *ShortNode:
case *shortNode:
if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) {
// The trie doesn't contain the key.
tn = nil
@ -51,11 +51,11 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) e
key = key[len(n.Key):]
}
nodes = append(nodes, n)
case *FullNode:
case *fullNode:
tn = n.Children[key[0]]
key = key[1:]
nodes = append(nodes, n)
case HashNode:
case hashNode:
var err error
tn, err = t.resolveHash(n, nil)
if err != nil {
@ -74,9 +74,9 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) e
fromLevel--
continue
}
var hn Node
var hn node
n, hn = hasher.proofHash(n)
if hash, ok := hn.(HashNode); ok || i == 0 {
if hash, ok := hn.(hashNode); ok || i == 0 {
// If the Node's database encoding is a hash (or is the
// root Node), it becomes a proof element.
enc, _ := rlp.EncodeToBytes(n)
@ -120,10 +120,10 @@ func VerifyProof(rootHash common.Hash, key []byte, proofDb ethdb.KeyValueReader)
case nil:
// The trie doesn't contain the key.
return nil, nil
case HashNode:
case hashNode:
key = keyrest
copy(wantHash[:], cld)
case ValueNode:
case valueNode:
return cld, nil
}
}
@ -133,9 +133,9 @@ func VerifyProof(rootHash common.Hash, key []byte, proofDb ethdb.KeyValueReader)
// The main purpose of this function is recovering a Node
// path from the merkle proof stream. All necessary nodes
// will be resolved and leave the remaining as hashnode.
func proofToPath(rootHash common.Hash, root Node, key []byte, proofDb ethdb.KeyValueReader, allowNonExistent bool) (Node, []byte, error) {
func proofToPath(rootHash common.Hash, root node, key []byte, proofDb ethdb.KeyValueReader, allowNonExistent bool) (node, []byte, error) {
// resolveNode retrieves and resolves trie Node from merkle proof stream
resolveNode := func(hash common.Hash) (Node, error) {
resolveNode := func(hash common.Hash) (node, error) {
buf, _ := proofDb.Get(hash[:])
if buf == nil {
return nil, fmt.Errorf("proof Node (hash %064x) missing", hash)
@ -157,7 +157,7 @@ func proofToPath(rootHash common.Hash, root Node, key []byte, proofDb ethdb.KeyV
}
var (
err error
child, parent Node
child, parent node
keyrest []byte
valnode []byte
)
@ -174,25 +174,25 @@ func proofToPath(rootHash common.Hash, root Node, key []byte, proofDb ethdb.KeyV
return root, nil, nil
}
return nil, nil, errors.New("the Node is not contained in trie")
case *ShortNode:
case *shortNode:
key, parent = keyrest, child // Already resolved
continue
case *FullNode:
case *fullNode:
key, parent = keyrest, child // Already resolved
continue
case HashNode:
case hashNode:
child, err = resolveNode(common.BytesToHash(cld))
if err != nil {
return nil, nil, err
}
case ValueNode:
case valueNode:
valnode = cld
}
// Link the parent and child.
switch pnode := parent.(type) {
case *ShortNode:
case *shortNode:
pnode.Val = child
case *FullNode:
case *fullNode:
pnode.Children[key[0]] = child
default:
panic(fmt.Sprintf("%T: invalid Node: %v", pnode, pnode))
@ -212,7 +212,7 @@ func proofToPath(rootHash common.Hash, root Node, key []byte, proofDb ethdb.KeyV
// since the Node content might be modified. Besides it can happen that some
// fullnodes only have one child which is disallowed. But if the proof is valid,
// the missing children will be filled, otherwise it will be thrown anyway.
func unsetInternal(n Node, left []byte, right []byte) error {
func unsetInternal(n node, left []byte, right []byte) error {
left, right = keybytesToHex(left), keybytesToHex(right)
// todo(rjl493456442) different length edge keys should be supported
@ -226,12 +226,12 @@ func unsetInternal(n Node, left []byte, right []byte) error {
// existent key or not.
var (
pos = 0
parent Node
parent node
)
findFork:
for {
switch rn := (n).(type) {
case *ShortNode:
case *shortNode:
// The right proof must point to an existent key.
if len(right)-pos < len(rn.Key) || !bytes.Equal(rn.Key, right[pos:pos+len(rn.Key)]) {
return errors.New("invalid edge path")
@ -245,7 +245,7 @@ findFork:
}
parent = n
n, pos = rn.Val, pos+len(rn.Key)
case *FullNode:
case *fullNode:
leftnode, rightnode := rn.Children[left[pos]], rn.Children[right[pos]]
// The right proof must point to an existent key.
if rightnode == nil {
@ -262,13 +262,13 @@ findFork:
}
}
switch rn := n.(type) {
case *ShortNode:
if _, ok := rn.Val.(ValueNode); ok {
parent.(*FullNode).Children[right[pos-1]] = nil
case *shortNode:
if _, ok := rn.Val.(valueNode); ok {
parent.(*fullNode).Children[right[pos-1]] = nil
return nil
}
return unset(rn, rn.Val, right[pos:], len(rn.Key), true)
case *FullNode:
case *fullNode:
for i := left[pos] + 1; i < right[pos]; i++ {
rn.Children[i] = nil
}
@ -298,9 +298,9 @@ findFork:
//
// If we try to unset all left most references, then the given path should
// be existent.
func unset(parent Node, child Node, key []byte, pos int, removeLeft bool) error {
func unset(parent node, child node, key []byte, pos int, removeLeft bool) error {
switch cld := child.(type) {
case *FullNode:
case *fullNode:
if removeLeft {
for i := 0; i < int(key[pos]); i++ {
cld.Children[i] = nil
@ -313,7 +313,7 @@ func unset(parent Node, child Node, key []byte, pos int, removeLeft bool) error
cld.flags = NodeFlag{dirty: true}
}
return unset(cld, cld.Children[key[pos]], key, pos+1, removeLeft)
case *ShortNode:
case *shortNode:
if len(key[pos:]) < len(cld.Key) || !bytes.Equal(cld.Key, key[pos:pos+len(cld.Key)]) {
// Find the fork point, it's an non-existent branch.
if removeLeft {
@ -323,7 +323,7 @@ func unset(parent Node, child Node, key []byte, pos int, removeLeft bool) error
// The key of fork shortnode is greater than the
// path(it belongs to the range), unset the entrie
// branch. The parent must be a fullnode.
fn := parent.(*FullNode)
fn := parent.(*fullNode)
fn.Children[key[pos-1]] = nil
} else {
// The key of fork shortnode is less than the
@ -332,8 +332,8 @@ func unset(parent Node, child Node, key []byte, pos int, removeLeft bool) error
}
return nil
}
if _, ok := cld.Val.(ValueNode); ok {
fn := parent.(*FullNode)
if _, ok := cld.Val.(valueNode); ok {
fn := parent.(*fullNode)
fn.Children[key[pos-1]] = nil
return nil
}
@ -355,23 +355,23 @@ func unset(parent Node, child Node, key []byte, pos int, removeLeft bool) error
// in the right side of the given path. The given path can point to an existent
// key or a non-existent one. This function has the assumption that the whole
// path should already be resolved.
func hasRightElement(node Node, key []byte) bool {
func hasRightElement(node node, key []byte) bool {
pos, key := 0, keybytesToHex(key)
for node != nil {
switch rn := node.(type) {
case *FullNode:
case *fullNode:
for i := key[pos] + 1; i < 16; i++ {
if rn.Children[i] != nil {
return true
}
}
node, pos = rn.Children[key[pos]], pos+1
case *ShortNode:
case *shortNode:
if len(key)-pos < len(rn.Key) || !bytes.Equal(rn.Key, key[pos:pos+len(rn.Key)]) {
return bytes.Compare(rn.Key, key[pos:]) > 0
}
node, pos = rn.Val, pos+len(rn.Key)
case ValueNode:
case valueNode:
return false // We have resolved the whole path
default:
panic(fmt.Sprintf("%T: invalid Node: %v", node, node)) // hashnode
@ -479,10 +479,10 @@ func VerifyRangeProof(rootHash common.Hash, firstKey []byte, keys [][]byte, valu
//
// There is an additional flag `skipResolved`. If it's set then
// all resolved nodes won't be returned.
func get(tn Node, key []byte, skipResolved bool) ([]byte, Node) {
func get(tn node, key []byte, skipResolved bool) ([]byte, node) {
for {
switch n := tn.(type) {
case *ShortNode:
case *shortNode:
if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) {
return nil, nil
}
@ -491,17 +491,17 @@ func get(tn Node, key []byte, skipResolved bool) ([]byte, Node) {
if !skipResolved {
return key, tn
}
case *FullNode:
case *fullNode:
tn = n.Children[key[0]]
key = key[1:]
if !skipResolved {
return key, tn
}
case HashNode:
case hashNode:
return key, n
case nil:
return key, nil
case ValueNode:
case valueNode:
return nil, n
default:
panic(fmt.Sprintf("%T: invalid Node: %v", tn, tn))

View file

@ -290,21 +290,21 @@ func (s *Sync) schedule(req *request) {
// children retrieves all the missing children of a state trie entry for future
// retrieval scheduling.
func (s *Sync) children(req *request, object Node) ([]*request, error) {
func (s *Sync) children(req *request, object node) ([]*request, error) {
// Gather all the children of the Node, irrelevant whether known or not
type child struct {
node Node
node node
depth int
}
var children []child
switch node := (object).(type) {
case *ShortNode:
case *shortNode:
children = []child{{
node: node.Val,
depth: req.depth + len(node.Key),
}}
case *FullNode:
case *fullNode:
for i := 0; i < 17; i++ {
if node.Children[i] != nil {
children = append(children, child{
@ -321,14 +321,14 @@ func (s *Sync) children(req *request, object Node) ([]*request, error) {
for _, child := range children {
// Notify any external watcher of a new key/value Node
if req.callback != nil {
if node, ok := (child.node).(ValueNode); ok {
if node, ok := (child.node).(valueNode); ok {
if err := req.callback(node, req.hash); err != nil {
return nil, err
}
}
}
// If the child references another Node, resolve or schedule
if node, ok := (child.node).(HashNode); ok {
if node, ok := (child.node).(hashNode); ok {
// Try to resolve the Node from the local database
hash := common.BytesToHash(node)
if s.membatch.hasNode(hash) {

View file

@ -51,7 +51,7 @@ type LeafCallback func(leaf []byte, parent common.Hash) error
// Trie is not safe for concurrent use.
type Trie struct {
Db *Database
root Node
root node
// Keep track of the number leafs which have been inserted since the last
// hashing operation. This number will not directly map to the number of
// actually unhashed nodes
@ -114,13 +114,13 @@ func (t *Trie) TryGet(key []byte) ([]byte, error) {
return value, err
}
func (t *Trie) tryGet(origNode Node, key []byte, pos int) (value []byte, newnode Node, didResolve bool, err error) {
func (t *Trie) tryGet(origNode node, key []byte, pos int) (value []byte, newnode node, didResolve bool, err error) {
switch n := (origNode).(type) {
case nil:
return nil, nil, false, nil
case ValueNode:
case valueNode:
return n, n, false, nil
case *ShortNode:
case *shortNode:
if len(key)-pos < len(n.Key) || !bytes.Equal(n.Key, key[pos:pos+len(n.Key)]) {
// key not found in trie
return nil, n, false, nil
@ -131,14 +131,14 @@ func (t *Trie) tryGet(origNode Node, key []byte, pos int) (value []byte, newnode
n.Val = newnode
}
return value, n, didResolve, err
case *FullNode:
case *fullNode:
value, newnode, didResolve, err = t.tryGet(n.Children[key[pos]], key, pos+1)
if err == nil && didResolve {
n = n.copy()
n.Children[key[pos]] = newnode
}
return value, n, didResolve, err
case HashNode:
case hashNode:
child, err := t.resolveHash(n, key[:pos])
if err != nil {
return nil, n, true, err
@ -158,13 +158,13 @@ func (t *Trie) TryGetBestLeftKeyAndValue() ([]byte, []byte, error) {
return hexToKeybytes(key), value, err
}
func (t *Trie) tryGetBestLeftKeyAndValue(origNode Node, prefix []byte) (key []byte, value []byte, newnode Node, didResolve bool, err error) {
func (t *Trie) tryGetBestLeftKeyAndValue(origNode node, prefix []byte) (key []byte, value []byte, newnode node, didResolve bool, err error) {
switch n := (origNode).(type) {
case nil:
return nil, nil, nil, false, nil
case *ShortNode:
case *shortNode:
switch v := n.Val.(type) {
case ValueNode:
case valueNode:
return append(prefix, n.Key...), v, n, false, nil
default:
}
@ -174,7 +174,7 @@ func (t *Trie) tryGetBestLeftKeyAndValue(origNode Node, prefix []byte) (key []by
n.Val = newnode
}
return key, value, n, didResolve, err
case *FullNode:
case *fullNode:
for i := 0; i < len(n.Children); i++ {
if n.Children[i] == nil {
continue
@ -186,7 +186,7 @@ func (t *Trie) tryGetBestLeftKeyAndValue(origNode Node, prefix []byte) (key []by
}
return key, value, n, didResolve, err
}
case HashNode:
case hashNode:
child, err := t.resolveHash(n, nil)
if err != nil {
return nil, nil, n, true, err
@ -213,11 +213,11 @@ func (t *Trie) TryGetAllLeftKeyAndValue(limit []byte) ([][]byte, [][]byte, error
}
return keys, values, err
}
func (t *Trie) tryGetAllLeftKeyAndValue(origNode Node, prefix []byte, limit []byte) (keys [][]byte, values [][]byte, newnode Node, didResolve bool, err error) {
func (t *Trie) tryGetAllLeftKeyAndValue(origNode node, prefix []byte, limit []byte) (keys [][]byte, values [][]byte, newnode node, didResolve bool, err error) {
switch n := (origNode).(type) {
case nil:
return nil, nil, nil, false, nil
case ValueNode:
case valueNode:
key := make([]byte, len(prefix))
copy(key, prefix)
if bytes.Compare(key, limit) < 0 {
@ -225,14 +225,14 @@ func (t *Trie) tryGetAllLeftKeyAndValue(origNode Node, prefix []byte, limit []by
values = append(values, n)
}
return keys, values, n, false, nil
case *ShortNode:
case *shortNode:
keys, values, newnode, didResolve, err := t.tryGetAllLeftKeyAndValue(n.Val, append(prefix, n.Key...), limit)
if err == nil && didResolve {
n = n.copy()
n.Val = newnode
}
return keys, values, n, didResolve, err
case *FullNode:
case *fullNode:
for i := len(n.Children) - 1; i >= 0; i-- {
if n.Children[i] == nil {
continue
@ -253,7 +253,7 @@ func (t *Trie) tryGetAllLeftKeyAndValue(origNode Node, prefix []byte, limit []by
values = append(values, allValues...)
}
return keys, values, n, didResolve, err
case HashNode:
case hashNode:
child, err := t.resolveHash(n, nil)
if err != nil {
return nil, nil, n, true, err
@ -273,13 +273,13 @@ func (t *Trie) TryGetBestRightKeyAndValue() ([]byte, []byte, error) {
return hexToKeybytes(key), value, err
}
func (t *Trie) tryGetBestRightKeyAndValue(origNode Node, prefix []byte) (key []byte, value []byte, newnode Node, didResolve bool, err error) {
func (t *Trie) tryGetBestRightKeyAndValue(origNode node, prefix []byte) (key []byte, value []byte, newnode node, didResolve bool, err error) {
switch n := (origNode).(type) {
case nil:
return nil, nil, nil, false, nil
case *ShortNode:
case *shortNode:
switch v := n.Val.(type) {
case ValueNode:
case valueNode:
return append(prefix, n.Key...), v, n, false, nil
default:
}
@ -289,7 +289,7 @@ func (t *Trie) tryGetBestRightKeyAndValue(origNode Node, prefix []byte) (key []b
n.Val = newnode
}
return key, value, n, didResolve, err
case *FullNode:
case *fullNode:
for i := len(n.Children) - 1; i >= 0; i-- {
if n.Children[i] == nil {
continue
@ -301,7 +301,7 @@ func (t *Trie) tryGetBestRightKeyAndValue(origNode Node, prefix []byte) (key []b
}
return key, value, n, didResolve, err
}
case HashNode:
case hashNode:
child, err := t.resolveHash(n, nil)
if err != nil {
return nil, nil, n, true, err
@ -338,7 +338,7 @@ func (t *Trie) TryUpdate(key, value []byte) error {
t.unhashed++
k := keybytesToHex(key)
if len(value) != 0 {
_, n, err := t.insert(t.root, nil, k, ValueNode(value))
_, n, err := t.insert(t.root, nil, k, valueNode(value))
if err != nil {
return err
}
@ -353,15 +353,15 @@ func (t *Trie) TryUpdate(key, value []byte) error {
return nil
}
func (t *Trie) insert(n Node, prefix, key []byte, value Node) (bool, Node, error) {
func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error) {
if len(key) == 0 {
if v, ok := n.(ValueNode); ok {
return !bytes.Equal(v, value.(ValueNode)), value, nil
if v, ok := n.(valueNode); ok {
return !bytes.Equal(v, value.(valueNode)), value, nil
}
return true, value, nil
}
switch n := n.(type) {
case *ShortNode:
case *shortNode:
matchlen := prefixLen(key, n.Key)
// If the whole key matches, keep this short Node as is
// and only update the value.
@ -370,10 +370,10 @@ func (t *Trie) insert(n Node, prefix, key []byte, value Node) (bool, Node, error
if !dirty || err != nil {
return false, n, err
}
return true, &ShortNode{n.Key, nn, t.newFlag()}, nil
return true, &shortNode{n.Key, nn, t.newFlag()}, nil
}
// Otherwise branch out at the index where they differ.
branch := &FullNode{flags: t.newFlag()}
branch := &fullNode{flags: t.newFlag()}
var err error
_, branch.Children[n.Key[matchlen]], err = t.insert(nil, append(prefix, n.Key[:matchlen+1]...), n.Key[matchlen+1:], n.Val)
if err != nil {
@ -388,9 +388,9 @@ func (t *Trie) insert(n Node, prefix, key []byte, value Node) (bool, Node, error
return true, branch, nil
}
// Otherwise, replace it with a short Node leading up to the branch.
return true, &ShortNode{key[:matchlen], branch, t.newFlag()}, nil
return true, &shortNode{key[:matchlen], branch, t.newFlag()}, nil
case *FullNode:
case *fullNode:
dirty, nn, err := t.insert(n.Children[key[0]], append(prefix, key[0]), key[1:], value)
if !dirty || err != nil {
return false, n, err
@ -401,9 +401,9 @@ func (t *Trie) insert(n Node, prefix, key []byte, value Node) (bool, Node, error
return true, n, nil
case nil:
return true, &ShortNode{key, value, t.newFlag()}, nil
return true, &shortNode{key, value, t.newFlag()}, nil
case HashNode:
case hashNode:
// We've hit a part of the trie that isn't loaded yet. Load
// the Node and insert into it. This leaves all child nodes on
// the path to the value in the trie.
@ -445,9 +445,9 @@ func (t *Trie) TryDelete(key []byte) error {
// delete returns the new root of the trie with key deleted.
// It reduces the trie to minimal form by simplifying
// nodes on the way up after deleting recursively.
func (t *Trie) delete(n Node, prefix, key []byte) (bool, Node, error) {
func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
switch n := n.(type) {
case *ShortNode:
case *shortNode:
matchlen := prefixLen(key, n.Key)
if matchlen < len(n.Key) {
return false, n, nil // don't replace n on mismatch
@ -464,19 +464,19 @@ func (t *Trie) delete(n Node, prefix, key []byte) (bool, Node, error) {
return false, n, err
}
switch child := child.(type) {
case *ShortNode:
case *shortNode:
// Deleting from the subtrie reduced it to another
// short Node. Merge the nodes to avoid creating a
// ShortNode{..., ShortNode{...}}. Use concat (which
// always creates a new slice) instead of append to
// avoid modifying n.Key since it might be shared with
// other nodes.
return true, &ShortNode{concat(n.Key, child.Key...), child.Val, t.newFlag()}, nil
return true, &shortNode{concat(n.Key, child.Key...), child.Val, t.newFlag()}, nil
default:
return true, &ShortNode{n.Key, child, t.newFlag()}, nil
return true, &shortNode{n.Key, child, t.newFlag()}, nil
}
case *FullNode:
case *fullNode:
dirty, nn, err := t.delete(n.Children[key[0]], append(prefix, key[0]), key[1:])
if !dirty || err != nil {
return false, n, err
@ -517,25 +517,25 @@ func (t *Trie) delete(n Node, prefix, key []byte) (bool, Node, error) {
if err != nil {
return false, nil, err
}
if cnode, ok := cnode.(*ShortNode); ok {
if cnode, ok := cnode.(*shortNode); ok {
k := append([]byte{byte(pos)}, cnode.Key...)
return true, &ShortNode{k, cnode.Val, t.newFlag()}, nil
return true, &shortNode{k, cnode.Val, t.newFlag()}, nil
}
}
// Otherwise, n is replaced by a one-nibble short Node
// containing the child.
return true, &ShortNode{[]byte{byte(pos)}, n.Children[pos], t.newFlag()}, nil
return true, &shortNode{[]byte{byte(pos)}, n.Children[pos], t.newFlag()}, nil
}
// n still contains at least two values and cannot be reduced.
return true, n, nil
case ValueNode:
case valueNode:
return true, nil, nil
case nil:
return false, nil, nil
case HashNode:
case hashNode:
// We've hit a part of the trie that isn't loaded yet. Load
// the Node and delete from it. This leaves all child nodes on
// the path to the value in the trie.
@ -561,14 +561,14 @@ func concat(s1 []byte, s2 ...byte) []byte {
return r
}
func (t *Trie) resolve(n Node, prefix []byte) (Node, error) {
if n, ok := n.(HashNode); ok {
func (t *Trie) resolve(n node, prefix []byte) (node, error) {
if n, ok := n.(hashNode); ok {
return t.resolveHash(n, prefix)
}
return n, nil
}
func (t *Trie) resolveHash(n HashNode, prefix []byte) (Node, error) {
func (t *Trie) resolveHash(n hashNode, prefix []byte) (node, error) {
hash := common.BytesToHash(n)
if node := t.Db.node(hash); node != nil {
return node, nil
@ -581,7 +581,7 @@ func (t *Trie) resolveHash(n HashNode, prefix []byte) (Node, error) {
func (t *Trie) Hash() common.Hash {
hash, cached, _ := t.hashRoot()
t.root = cached
return common.BytesToHash(hash.(HashNode))
return common.BytesToHash(hash.(hashNode))
}
// Commit writes all nodes to the trie's memory database, tracking the internal
@ -612,7 +612,7 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
h.commitLoop(t.Db)
}()
}
var newRoot HashNode
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
@ -630,9 +630,9 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
}
// hashRoot calculates the root hash of the given trie
func (t *Trie) hashRoot() (Node, Node, error) {
func (t *Trie) hashRoot() (node, node, error) {
if t.root == nil {
return HashNode(emptyRoot.Bytes()), nil, nil
return hashNode(emptyRoot.Bytes()), nil, nil
}
// If the number of changes is below 100, we let one thread handle it
h := newHasher(t.unhashed >= 100)