mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
cmd, trie: remove cmd/gc and hide some types in trie
This commit is contained in:
parent
91cbe818ea
commit
7198179c2a
9 changed files with 210 additions and 480 deletions
270
cmd/gc/main.go
270
cmd/gc/main.go
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
72
trie/node.go
72
trie/node.go
|
|
@ -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 © }
|
||||
func (n *ShortNode) copy() *ShortNode { copy := *n; return © }
|
||||
func (n *fullNode) copy() *fullNode { copy := *n; return © }
|
||||
func (n *shortNode) copy() *shortNode { copy := *n; return © }
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
12
trie/sync.go
12
trie/sync.go
|
|
@ -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) {
|
||||
|
|
|
|||
100
trie/trie.go
100
trie/trie.go
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue