mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
Changes added in trie
This commit is contained in:
parent
f2f6616cff
commit
2ee661d950
7 changed files with 138 additions and 138 deletions
|
|
@ -53,9 +53,9 @@ 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, db *Database, force bool) (node, node, error) {
|
||||
func (h *hasher) hash(n Node, db *Database, force bool) (Node, Node, error) {
|
||||
// If we're not storing the node, just hashing, use available cached data
|
||||
if hash, dirty := n.cache(); hash != nil {
|
||||
if hash, dirty := n.Cache(); hash != nil {
|
||||
if db == nil {
|
||||
return hash, n, nil
|
||||
}
|
||||
|
|
@ -72,23 +72,23 @@ func (h *hasher) hash(n node, db *Database, force bool) (node, node, error) {
|
|||
// Trie not processed yet or needs storage, walk the children
|
||||
collapsed, cached, err := h.hashChildren(n, db)
|
||||
if err != nil {
|
||||
return hashNode{}, n, err
|
||||
return HashNode{}, n, err
|
||||
}
|
||||
hashed, err := h.store(collapsed, db, force)
|
||||
if err != nil {
|
||||
return hashNode{}, n, err
|
||||
return HashNode{}, n, err
|
||||
}
|
||||
// Cache the hash of the node for later reuse and remove
|
||||
// the dirty flag in commit mode. It's fine to assign these values directly
|
||||
// without copying the node first because hashChildren copies it.
|
||||
cachedHash, _ := hashed.(hashNode)
|
||||
cachedHash, _ := hashed.(HashNode)
|
||||
switch cn := cached.(type) {
|
||||
case *shortNode:
|
||||
case *ShortNode:
|
||||
cn.flags.hash = cachedHash
|
||||
if db != nil {
|
||||
cn.flags.dirty = false
|
||||
}
|
||||
case *fullNode:
|
||||
case *FullNode:
|
||||
cn.flags.hash = cachedHash
|
||||
if db != nil {
|
||||
cn.flags.dirty = false
|
||||
|
|
@ -100,28 +100,28 @@ func (h *hasher) hash(n node, db *Database, force bool) (node, node, error) {
|
|||
// hashChildren replaces the children of a node with their hashes if the encoded
|
||||
// size of the child is larger than a hash, returning the collapsed node as well
|
||||
// as a replacement for the original node with the child hashes cached in.
|
||||
func (h *hasher) hashChildren(original node, db *Database) (node, node, error) {
|
||||
func (h *hasher) hashChildren(original Node, db *Database) (Node, Node, error) {
|
||||
var err error
|
||||
|
||||
switch n := original.(type) {
|
||||
case *shortNode:
|
||||
// Hash the short node's child, caching the newly hashed subtree
|
||||
case *ShortNode:
|
||||
// Hash the short Node's child, caching the newly hashed subtree
|
||||
collapsed, cached := n.copy(), n.copy()
|
||||
collapsed.Key = hexToCompact(n.Key)
|
||||
cached.Key = common.CopyBytes(n.Key)
|
||||
|
||||
if _, ok := n.Val.(valueNode); !ok {
|
||||
if _, ok := n.Val.(ValueNode); !ok {
|
||||
collapsed.Val, cached.Val, err = h.hash(n.Val, db, false)
|
||||
if err != nil {
|
||||
return original, original, err
|
||||
}
|
||||
}
|
||||
if collapsed.Val == nil {
|
||||
collapsed.Val = valueNode(nil) // Ensure that nil children are encoded as empty strings.
|
||||
collapsed.Val = ValueNode(nil) // Ensure that nil children are encoded as empty strings.
|
||||
}
|
||||
return collapsed, cached, nil
|
||||
|
||||
case *fullNode:
|
||||
case *FullNode:
|
||||
// Hash the full node's children, caching the newly hashed subtrees
|
||||
collapsed, cached := n.copy(), n.copy()
|
||||
|
||||
|
|
@ -132,12 +132,12 @@ func (h *hasher) hashChildren(original node, db *Database) (node, node, error) {
|
|||
return original, original, err
|
||||
}
|
||||
} else {
|
||||
collapsed.Children[i] = valueNode(nil) // Ensure that nil children are encoded as empty strings.
|
||||
collapsed.Children[i] = ValueNode(nil) // Ensure that nil children are encoded as empty strings.
|
||||
}
|
||||
}
|
||||
cached.Children[16] = n.Children[16]
|
||||
if collapsed.Children[16] == nil {
|
||||
collapsed.Children[16] = valueNode(nil)
|
||||
collapsed.Children[16] = ValueNode(nil)
|
||||
}
|
||||
return collapsed, cached, nil
|
||||
|
||||
|
|
@ -150,9 +150,9 @@ func (h *hasher) hashChildren(original node, db *Database) (node, node, error) {
|
|||
// 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 (h *hasher) store(n node, db *Database, force bool) (node, error) {
|
||||
func (h *hasher) store(n Node, db *Database, force bool) (Node, error) {
|
||||
// Don't store hashes or empty nodes.
|
||||
if _, isHash := n.(hashNode); n == nil || isHash {
|
||||
if _, isHash := n.(HashNode); n == nil || isHash {
|
||||
return n, nil
|
||||
}
|
||||
// Generate the RLP encoding of the node
|
||||
|
|
@ -164,11 +164,11 @@ func (h *hasher) store(n node, db *Database, force bool) (node, error) {
|
|||
return n, nil // Nodes smaller than 32 bytes are stored inside their parent
|
||||
}
|
||||
// Larger nodes are replaced by their hash and stored in the database.
|
||||
hash, _ := n.cache()
|
||||
hash, _ := n.Cache()
|
||||
if hash == nil {
|
||||
h.sha.Reset()
|
||||
h.sha.Write(h.tmp.Bytes())
|
||||
hash = hashNode(h.sha.Sum(nil))
|
||||
hash = HashNode(h.sha.Sum(nil))
|
||||
}
|
||||
if db != nil {
|
||||
// We are pooling the trie nodes into an intermediate memory cache
|
||||
|
|
@ -179,13 +179,13 @@ func (h *hasher) store(n node, db *Database, force bool) (node, error) {
|
|||
|
||||
// Track all direct parent->child node references
|
||||
switch n := n.(type) {
|
||||
case *shortNode:
|
||||
if child, ok := n.Val.(hashNode); ok {
|
||||
case *ShortNode:
|
||||
if child, ok := n.Val.(HashNode); ok {
|
||||
db.reference(common.BytesToHash(child), hash)
|
||||
}
|
||||
case *fullNode:
|
||||
case *FullNode:
|
||||
for i := 0; i < 16; i++ {
|
||||
if child, ok := n.Children[i].(hashNode); ok {
|
||||
if child, ok := n.Children[i].(HashNode); ok {
|
||||
db.reference(common.BytesToHash(child), hash)
|
||||
}
|
||||
}
|
||||
|
|
@ -195,13 +195,13 @@ func (h *hasher) store(n node, db *Database, force bool) (node, error) {
|
|||
// Track external references from account->storage trie
|
||||
if h.onleaf != nil {
|
||||
switch n := n.(type) {
|
||||
case *shortNode:
|
||||
if child, ok := n.Val.(valueNode); ok {
|
||||
case *ShortNode:
|
||||
if child, ok := n.Val.(ValueNode); ok {
|
||||
h.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 {
|
||||
h.onleaf(child, hash)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import (
|
|||
"bytes"
|
||||
"container/heap"
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
|
|
@ -60,6 +59,7 @@ type NodeIterator interface {
|
|||
// Next moves the iterator to the next node. If the parameter is false, any child
|
||||
// nodes will be skipped.
|
||||
Next(bool) bool
|
||||
|
||||
// Error returns the error status of the iterator.
|
||||
Error() error
|
||||
|
||||
|
|
@ -86,7 +86,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
|
||||
|
|
@ -112,7 +112,7 @@ func (e seekError) Error() string {
|
|||
return "seek error: " + e.err.Error()
|
||||
}
|
||||
|
||||
func newNodeIterator(trie *Trie, start []byte) NodeIterator {
|
||||
func NewNodeIterator(trie *Trie, start []byte) NodeIterator {
|
||||
if trie.Hash() == emptyState {
|
||||
return new(nodeIterator)
|
||||
}
|
||||
|
|
@ -141,7 +141,7 @@ func (it *nodeIterator) Leaf() bool {
|
|||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -150,7 +150,7 @@ func (it *nodeIterator) LeafBlob() []byte {
|
|||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -250,7 +250,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
|
||||
|
|
@ -263,12 +263,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:
|
||||
// Full node, move to the first non-nil child.
|
||||
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,
|
||||
|
|
@ -281,10 +281,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,
|
||||
|
|
|
|||
78
trie/node.go
78
trie/node.go
|
|
@ -27,63 +27,63 @@ 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)
|
||||
canUnload(cachegen, cachelimit uint16) 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
|
||||
)
|
||||
|
||||
// EncodeRLP encodes a full node into the consensus RLP format.
|
||||
func (n *fullNode) EncodeRLP(w io.Writer) error {
|
||||
func (n *FullNode) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, n.Children)
|
||||
}
|
||||
|
||||
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)
|
||||
gen uint16 // cache generation counter
|
||||
dirty bool // whether the node has changes that must be written to the database
|
||||
}
|
||||
|
||||
// canUnload tells whether a node can be unloaded.
|
||||
// canUnload tells whether a Node can be unloaded.
|
||||
func (n *nodeFlag) canUnload(cachegen, cachelimit uint16) bool {
|
||||
return !n.dirty && cachegen-n.gen >= cachelimit
|
||||
}
|
||||
|
||||
func (n *fullNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) }
|
||||
func (n *shortNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) }
|
||||
func (n hashNode) canUnload(uint16, uint16) bool { return false }
|
||||
func (n valueNode) canUnload(uint16, uint16) bool { return false }
|
||||
func (n *FullNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) }
|
||||
func (n *ShortNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) }
|
||||
func (n HashNode) canUnload(uint16, uint16) bool { return false }
|
||||
func (n ValueNode) canUnload(uint16, uint16) bool { return false }
|
||||
|
||||
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 {
|
||||
|
|
@ -94,17 +94,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, cachegen uint16) node {
|
||||
func MustDecodeNode(hash, buf []byte, cachegen uint16) Node {
|
||||
n, err := decodeNode(hash, buf, cachegen)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("node %x: %v", hash, err))
|
||||
|
|
@ -113,7 +113,7 @@ func mustDecodeNode(hash, buf []byte, cachegen uint16) node {
|
|||
}
|
||||
|
||||
// decodeNode parses the RLP encoding of a trie node.
|
||||
func decodeNode(hash, buf []byte, cachegen uint16) (node, error) {
|
||||
func decodeNode(hash, buf []byte, cachegen uint16) (Node, error) {
|
||||
if len(buf) == 0 {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
|
@ -133,7 +133,7 @@ func decodeNode(hash, buf []byte, cachegen uint16) (node, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func decodeShort(hash, buf, elems []byte, cachegen uint16) (node, error) {
|
||||
func decodeShort(hash, buf, elems []byte, cachegen uint16) (Node, error) {
|
||||
kbuf, rest, err := rlp.SplitString(elems)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -146,17 +146,17 @@ func decodeShort(hash, buf, elems []byte, cachegen uint16) (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, cachegen)
|
||||
if err != nil {
|
||||
return nil, wrapError(err, "val")
|
||||
}
|
||||
return &shortNode{key, r, flag}, nil
|
||||
return &ShortNode{key, r, flag}, nil
|
||||
}
|
||||
|
||||
func decodeFull(hash, buf, elems []byte, cachegen uint16) (*fullNode, error) {
|
||||
n := &fullNode{flags: nodeFlag{hash: hash, gen: cachegen}}
|
||||
func decodeFull(hash, buf, elems []byte, cachegen uint16) (*FullNode, error) {
|
||||
n := &FullNode{flags: nodeFlag{hash: hash, gen: cachegen}}
|
||||
for i := 0; i < 16; i++ {
|
||||
cld, rest, err := decodeRef(elems, cachegen)
|
||||
if err != nil {
|
||||
|
|
@ -169,14 +169,14 @@ func decodeFull(hash, buf, elems []byte, cachegen uint16) (*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, cachegen uint16) (node, []byte, error) {
|
||||
func decodeRef(buf []byte, cachegen uint16) (Node, []byte, error) {
|
||||
kind, val, rest, err := rlp.Split(buf)
|
||||
if err != nil {
|
||||
return nil, buf, err
|
||||
|
|
@ -195,7 +195,7 @@ func decodeRef(buf []byte, cachegen uint16) (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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,11 +37,11 @@ import (
|
|||
func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
|
||||
// Collect all nodes on the path to key.
|
||||
key = keybytesToHex(key)
|
||||
nodes := []node{}
|
||||
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
|
||||
|
|
@ -50,11 +50,11 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
|
|||
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 {
|
||||
|
|
@ -71,7 +71,7 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
|
|||
// if encoding doesn't work and we're not writing to any database.
|
||||
n, _, _ = hasher.hashChildren(n, nil)
|
||||
hn, _ := hasher.store(n, nil, false)
|
||||
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.
|
||||
if fromLevel > 0 {
|
||||
|
|
@ -119,32 +119,32 @@ func VerifyProof(rootHash common.Hash, key []byte, proofDb DatabaseReader) (valu
|
|||
case nil:
|
||||
// The trie doesn't contain the key.
|
||||
return nil, nil, i
|
||||
case hashNode:
|
||||
case HashNode:
|
||||
key = keyrest
|
||||
copy(wantHash[:], cld)
|
||||
case valueNode:
|
||||
case ValueNode:
|
||||
return cld, nil, i + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func get(tn node, key []byte) ([]byte, node) {
|
||||
func get(tn Node, key []byte) ([]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
|
||||
}
|
||||
tn = n.Val
|
||||
key = key[len(n.Key):]
|
||||
case *fullNode:
|
||||
case *FullNode:
|
||||
tn = n.Children[key[0]]
|
||||
key = key[1:]
|
||||
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
|
|
@ -248,21 +248,21 @@ func (s *TrieSync) schedule(req *request) {
|
|||
|
||||
// children retrieves all the missing children of a state trie entry for future
|
||||
// retrieval scheduling.
|
||||
func (s *TrieSync) children(req *request, object node) ([]*request, error) {
|
||||
func (s *TrieSync) 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
|
||||
}
|
||||
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{
|
||||
|
|
@ -279,14 +279,14 @@ func (s *TrieSync) 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 _, ok := s.membatch.batch[hash]; ok {
|
||||
|
|
|
|||
76
trie/trie.go
76
trie/trie.go
|
|
@ -66,7 +66,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
|
||||
originalRoot common.Hash
|
||||
|
||||
// Cache generation values.
|
||||
|
|
@ -114,7 +114,7 @@ func New(root common.Hash, db *Database) (*Trie, error) {
|
|||
// NodeIterator returns an iterator that returns nodes of the trie. Iteration starts at
|
||||
// the key after the given start key.
|
||||
func (t *Trie) NodeIterator(start []byte) NodeIterator {
|
||||
return newNodeIterator(t, start)
|
||||
return NewNodeIterator(t, start)
|
||||
}
|
||||
|
||||
// Get returns the value for key stored in the trie.
|
||||
|
|
@ -139,13 +139,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
|
||||
|
|
@ -157,7 +157,7 @@ func (t *Trie) tryGet(origNode node, key []byte, pos int) (value []byte, newnode
|
|||
n.flags.gen = t.cachegen
|
||||
}
|
||||
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()
|
||||
|
|
@ -165,7 +165,7 @@ func (t *Trie) tryGet(origNode node, key []byte, pos int) (value []byte, newnode
|
|||
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
|
||||
|
|
@ -200,7 +200,7 @@ func (t *Trie) Update(key, value []byte) {
|
|||
func (t *Trie) TryUpdate(key, value []byte) error {
|
||||
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
|
||||
}
|
||||
|
|
@ -215,15 +215,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.
|
||||
|
|
@ -232,10 +232,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 {
|
||||
|
|
@ -250,9 +250,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
|
||||
|
|
@ -263,9 +263,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.
|
||||
|
|
@ -306,9 +306,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
|
||||
|
|
@ -325,19 +325,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
|
||||
|
|
@ -368,7 +368,7 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
|
|||
}
|
||||
if pos >= 0 {
|
||||
if pos != 16 {
|
||||
// If the remaining entry is a short node, it replaces
|
||||
// If the remaining entry is a short node, it replaces
|
||||
// n and its key gets the missing nibble tacked to the
|
||||
// front. This avoids creating an invalid
|
||||
// shortNode{..., shortNode{...}}. Since the entry
|
||||
|
|
@ -378,25 +378,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.
|
||||
|
|
@ -422,14 +422,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) {
|
||||
cacheMissCounter.Inc(1)
|
||||
|
||||
hash := common.BytesToHash(n)
|
||||
|
|
@ -438,7 +438,7 @@ func (t *Trie) resolveHash(n hashNode, prefix []byte) (node, error) {
|
|||
if err != nil || enc == nil {
|
||||
return nil, &MissingNodeError{NodeHash: hash, Path: prefix}
|
||||
}
|
||||
return mustDecodeNode(n, enc, t.cachegen), nil
|
||||
return MustDecodeNode(n, enc, t.cachegen), nil
|
||||
}
|
||||
|
||||
// Root returns the root hash of the trie.
|
||||
|
|
@ -450,7 +450,7 @@ func (t *Trie) Root() []byte { return t.Hash().Bytes() }
|
|||
func (t *Trie) Hash() common.Hash {
|
||||
hash, cached, _ := t.hashRoot(nil, nil)
|
||||
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
|
||||
|
|
@ -465,12 +465,12 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
|
|||
}
|
||||
t.root = cached
|
||||
t.cachegen++
|
||||
return common.BytesToHash(hash.(hashNode)), nil
|
||||
return common.BytesToHash(hash.(HashNode)), nil
|
||||
}
|
||||
|
||||
func (t *Trie) hashRoot(db *Database, onleaf LeafCallback) (node, node, error) {
|
||||
func (t *Trie) hashRoot(db *Database, onleaf LeafCallback) (Node, Node, error) {
|
||||
if t.root == nil {
|
||||
return hashNode(emptyRoot.Bytes()), nil, nil
|
||||
return HashNode(emptyRoot.Bytes()), nil, nil
|
||||
}
|
||||
h := newHasher(t.cachegen, t.cachelimit, onleaf)
|
||||
defer returnHasherToPool(h)
|
||||
|
|
|
|||
|
|
@ -469,14 +469,14 @@ func runRandTest(rt randTest) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func checkCacheInvariant(n, parent node, parentCachegen uint16, parentDirty bool, depth int) error {
|
||||
var children []node
|
||||
func checkCacheInvariant(n, parent Node, parentCachegen uint16, parentDirty bool, depth int) error {
|
||||
var children []Node
|
||||
var flag nodeFlag
|
||||
switch n := n.(type) {
|
||||
case *shortNode:
|
||||
case *ShortNode:
|
||||
flag = n.flags
|
||||
children = []node{n.Val}
|
||||
case *fullNode:
|
||||
children = []Node{n.Val}
|
||||
case *FullNode:
|
||||
flag = n.flags
|
||||
children = n.Children[:]
|
||||
default:
|
||||
|
|
|
|||
Loading…
Reference in a new issue