trie/bintrie: unexport package-internal arena identifiers

Gballet asked on PR #34055 to unexport nodeRef, nodeKind, and makeRef
(comments 3099846639, 3099847640, 3100717855) — none are used outside
trie/bintrie. Cascade to the internal-only support symbols and methods:

  NodeKind          → nodeKind
  KindEmpty/...     → kindEmpty/...
  NodeRef           → nodeRef
  EmptyRef          → emptyRef
  MakeRef           → makeRef
  NodeStore.Root    → deleted; inlined to s.root field access (same pkg)
  NodeStore.SetRoot → deleted; inlined to s.root = ref
  NodeStore.ComputeHash/SerializeNode/DeserializeNode(WithHash)/
  CollectNodes/ToDot/GetHeight → lowercased

All 9 method signatures took or returned nodeRef so their export would
have tripped revive:unexported-return after the type rename. Zero
external callers means no API break. The private deserializeNode helper
was renamed to decodeNode to free the name for the newly-private
deserializeNode public function.

Pure rename; no behaviour change.
This commit is contained in:
CPerezz 2026-04-18 18:49:04 +02:00
parent 939b36345f
commit 2d44d8a4b6
No known key found for this signature in database
GPG key ID: 62045F34B97177DD
14 changed files with 209 additions and 213 deletions

View file

@ -39,9 +39,9 @@ const (
// the hash of a serialized node without maintaining a NodeStore. // the hash of a serialized node without maintaining a NodeStore.
func DeserializeAndHash(blob []byte, depth int) (common.Hash, error) { func DeserializeAndHash(blob []byte, depth int) (common.Hash, error) {
s := NewNodeStore() s := NewNodeStore()
ref, err := s.DeserializeNode(blob, depth) ref, err := s.deserializeNode(blob, depth)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
return s.ComputeHash(ref), nil return s.computeHash(ref), nil
} }

View file

@ -37,10 +37,10 @@ func TestSerializeDeserializeInternalNode(t *testing.T) {
rootNode := s.getInternal(rootRef.Index()) rootNode := s.getInternal(rootRef.Index())
rootNode.left = leftRef rootNode.left = leftRef
rootNode.right = rightRef rootNode.right = rightRef
s.SetRoot(rootRef) s.root = rootRef
// Serialize the node — flat 65-byte format // Serialize the node — flat 65-byte format
serialized := s.SerializeNode(rootRef) serialized := s.serializeNode(rootRef)
// Check the serialized format: [type(1)][leftHash(32)][rightHash(32)] // Check the serialized format: [type(1)][leftHash(32)][rightHash(32)]
if serialized[0] != nodeTypeInternal { if serialized[0] != nodeTypeInternal {
@ -62,14 +62,14 @@ func TestSerializeDeserializeInternalNode(t *testing.T) {
// Deserialize into a new store // Deserialize into a new store
ds := NewNodeStore() ds := NewNodeStore()
deserialized, err := ds.DeserializeNode(serialized, 0) deserialized, err := ds.deserializeNode(serialized, 0)
if err != nil { if err != nil {
t.Fatalf("Failed to deserialize node: %v", err) t.Fatalf("Failed to deserialize node: %v", err)
} }
// Root should be an InternalNode // Root should be an InternalNode
if deserialized.Kind() != KindInternal { if deserialized.Kind() != kindInternal {
t.Fatalf("Expected KindInternal, got kind %d", deserialized.Kind()) t.Fatalf("Expected kindInternal, got kind %d", deserialized.Kind())
} }
internalNode := ds.getInternal(deserialized.Index()) internalNode := ds.getInternal(deserialized.Index())
@ -78,19 +78,19 @@ func TestSerializeDeserializeInternalNode(t *testing.T) {
} }
// Left child should be a HashedNode with the correct hash // Left child should be a HashedNode with the correct hash
if internalNode.left.Kind() != KindHashed { if internalNode.left.Kind() != kindHashed {
t.Fatalf("Expected left child to be KindHashed, got %d", internalNode.left.Kind()) t.Fatalf("Expected left child to be kindHashed, got %d", internalNode.left.Kind())
} }
if ds.ComputeHash(internalNode.left) != leftHash { if ds.computeHash(internalNode.left) != leftHash {
t.Errorf("Left hash mismatch: expected %x, got %x", leftHash, ds.ComputeHash(internalNode.left)) t.Errorf("Left hash mismatch: expected %x, got %x", leftHash, ds.computeHash(internalNode.left))
} }
// Right child should be a HashedNode with the correct hash // Right child should be a HashedNode with the correct hash
if internalNode.right.Kind() != KindHashed { if internalNode.right.Kind() != kindHashed {
t.Fatalf("Expected right child to be KindHashed, got %d", internalNode.right.Kind()) t.Fatalf("Expected right child to be kindHashed, got %d", internalNode.right.Kind())
} }
if ds.ComputeHash(internalNode.right) != rightHash { if ds.computeHash(internalNode.right) != rightHash {
t.Errorf("Right hash mismatch: expected %x, got %x", rightHash, ds.ComputeHash(internalNode.right)) t.Errorf("Right hash mismatch: expected %x, got %x", rightHash, ds.computeHash(internalNode.right))
} }
} }
@ -116,7 +116,7 @@ func TestSerializeDeserializeStemNode(t *testing.T) {
} }
// Serialize the node // Serialize the node
serialized := s.SerializeNode(ref) serialized := s.serializeNode(ref)
// Check the serialized format // Check the serialized format
if serialized[0] != nodeTypeStem { if serialized[0] != nodeTypeStem {
@ -130,13 +130,13 @@ func TestSerializeDeserializeStemNode(t *testing.T) {
// Deserialize into a new store // Deserialize into a new store
ds := NewNodeStore() ds := NewNodeStore()
deserializedRef, err := ds.DeserializeNode(serialized, 10) deserializedRef, err := ds.deserializeNode(serialized, 10)
if err != nil { if err != nil {
t.Fatalf("Failed to deserialize node: %v", err) t.Fatalf("Failed to deserialize node: %v", err)
} }
if deserializedRef.Kind() != KindStem { if deserializedRef.Kind() != kindStem {
t.Fatalf("Expected KindStem, got kind %d", deserializedRef.Kind()) t.Fatalf("Expected kindStem, got kind %d", deserializedRef.Kind())
} }
stemNode := ds.getStem(deserializedRef.Index()) stemNode := ds.getStem(deserializedRef.Index())
@ -171,13 +171,13 @@ func TestSerializeDeserializeStemNode(t *testing.T) {
// TestDeserializeEmptyNode tests deserialization of empty node. // TestDeserializeEmptyNode tests deserialization of empty node.
func TestDeserializeEmptyNode(t *testing.T) { func TestDeserializeEmptyNode(t *testing.T) {
s := NewNodeStore() s := NewNodeStore()
deserialized, err := s.DeserializeNode([]byte{}, 0) deserialized, err := s.deserializeNode([]byte{}, 0)
if err != nil { if err != nil {
t.Fatalf("Failed to deserialize empty node: %v", err) t.Fatalf("Failed to deserialize empty node: %v", err)
} }
if !deserialized.IsEmpty() { if !deserialized.IsEmpty() {
t.Fatalf("Expected EmptyRef, got kind %d", deserialized.Kind()) t.Fatalf("Expected emptyRef, got kind %d", deserialized.Kind())
} }
} }
@ -186,7 +186,7 @@ func TestDeserializeInvalidType(t *testing.T) {
s := NewNodeStore() s := NewNodeStore()
invalidData := []byte{99, 0, 0, 0} // Type byte 99 is invalid invalidData := []byte{99, 0, 0, 0} // Type byte 99 is invalid
_, err := s.DeserializeNode(invalidData, 0) _, err := s.deserializeNode(invalidData, 0)
if err == nil { if err == nil {
t.Fatal("Expected error for invalid type byte, got nil") t.Fatal("Expected error for invalid type byte, got nil")
} }
@ -198,7 +198,7 @@ func TestDeserializeInvalidLength(t *testing.T) {
// InternalNode with valid type byte but wrong length (needs exactly 65 bytes) // InternalNode with valid type byte but wrong length (needs exactly 65 bytes)
invalidData := []byte{nodeTypeInternal, 0, 0, 0} invalidData := []byte{nodeTypeInternal, 0, 0, 0}
_, err := s.DeserializeNode(invalidData, 0) _, err := s.deserializeNode(invalidData, 0)
if err == nil { if err == nil {
t.Fatal("Expected error for invalid data length, got nil") t.Fatal("Expected error for invalid data length, got nil")
} }

View file

@ -30,8 +30,8 @@ func TestHashedNodeHash(t *testing.T) {
s := NewNodeStore() s := NewNodeStore()
ref := s.newHashedRef(hash) ref := s.newHashedRef(hash)
if s.ComputeHash(ref) != hash { if s.computeHash(ref) != hash {
t.Errorf("Hash mismatch: expected %x, got %x", hash, s.ComputeHash(ref)) t.Errorf("Hash mismatch: expected %x, got %x", hash, s.computeHash(ref))
} }
} }
@ -40,10 +40,10 @@ func TestHashedNodeCopy(t *testing.T) {
hash := common.HexToHash("0xabcdef") hash := common.HexToHash("0xabcdef")
s := NewNodeStore() s := NewNodeStore()
ref := s.newHashedRef(hash) ref := s.newHashedRef(hash)
s.SetRoot(ref) s.root = ref
ns := s.Copy() ns := s.Copy()
copiedHash := ns.ComputeHash(ns.Root()) copiedHash := ns.computeHash(ns.root)
if copiedHash != hash { if copiedHash != hash {
t.Errorf("Hash mismatch after copy: expected %x, got %x", hash, copiedHash) t.Errorf("Hash mismatch after copy: expected %x, got %x", hash, copiedHash)
@ -55,7 +55,7 @@ func TestHashedNodeInsertValuesAtStem(t *testing.T) {
// Test 1: nil resolver should return an error // Test 1: nil resolver should return an error
s := NewNodeStore() s := NewNodeStore()
hashedRef := s.newHashedRef(common.HexToHash("0x1234")) hashedRef := s.newHashedRef(common.HexToHash("0x1234"))
s.SetRoot(hashedRef) s.root = hashedRef
stem := make([]byte, StemSize) stem := make([]byte, StemSize)
values := make([][]byte, StemNodeWidth) values := make([][]byte, StemNodeWidth)
@ -72,7 +72,7 @@ func TestHashedNodeInsertValuesAtStem(t *testing.T) {
s2 := NewNodeStore() s2 := NewNodeStore()
hashedRef2 := s2.newHashedRef(common.HexToHash("0x1234")) hashedRef2 := s2.newHashedRef(common.HexToHash("0x1234"))
s2.SetRoot(hashedRef2) s2.root = hashedRef2
err = s2.InsertValuesAtStem(stem, values, mockResolver) err = s2.InsertValuesAtStem(stem, values, mockResolver)
if err == nil { if err == nil {
@ -95,7 +95,7 @@ func TestHashedNodeInsertValuesAtStem(t *testing.T) {
sn.setValue(byte(i), v) sn.setValue(byte(i), v)
} }
} }
serialized := rs.SerializeNode(ref) serialized := rs.serializeNode(ref)
validResolver := func(path []byte, hash common.Hash) ([]byte, error) { validResolver := func(path []byte, hash common.Hash) ([]byte, error) {
return serialized, nil return serialized, nil
@ -103,7 +103,7 @@ func TestHashedNodeInsertValuesAtStem(t *testing.T) {
s3 := NewNodeStore() s3 := NewNodeStore()
hashedRef3 := s3.newHashedRef(common.HexToHash("0x1234")) hashedRef3 := s3.newHashedRef(common.HexToHash("0x1234"))
s3.SetRoot(hashedRef3) s3.root = hashedRef3
newValues := make([][]byte, StemNodeWidth) newValues := make([][]byte, StemNodeWidth)
newValues[2] = common.HexToHash("0x3333333333333333333333333333333333333333333333333333333333333333").Bytes() newValues[2] = common.HexToHash("0x3333333333333333333333333333333333333333333333333333333333333333").Bytes()
@ -137,8 +137,8 @@ func TestHashedNodeGetError(t *testing.T) {
rootNode := s.getInternal(rootRef.Index()) rootNode := s.getInternal(rootRef.Index())
hashedLeft := s.newHashedRef(common.HexToHash("0x1234")) hashedLeft := s.newHashedRef(common.HexToHash("0x1234"))
rootNode.left = hashedLeft rootNode.left = hashedLeft
rootNode.right = EmptyRef rootNode.right = emptyRef
s.SetRoot(rootRef) s.root = rootRef
key := make([]byte, 32) // goes left key := make([]byte, 32) // goes left
key[31] = 5 key[31] = 5

View file

@ -37,7 +37,7 @@ func keyToPath(depth int, key []byte) ([]byte, error) {
// Invariant: dirty=false implies mustRecompute=false. Every mutation that // Invariant: dirty=false implies mustRecompute=false. Every mutation that
// invalidates the cached hash MUST also mark the blob for re-flush. // invalidates the cached hash MUST also mark the blob for re-flush.
type InternalNode struct { type InternalNode struct {
left, right NodeRef left, right nodeRef
depth uint8 depth uint8
mustRecompute bool // hash is stale (cleared by Hash) mustRecompute bool // hash is stale (cleared by Hash)
dirty bool // on-disk blob is stale (cleared by CollectNodes) dirty bool // on-disk blob is stale (cleared by CollectNodes)

View file

@ -39,7 +39,7 @@ func TestInternalNodeGet(t *testing.T) {
// Build tree: root -> left stem, right stem // Build tree: root -> left stem, right stem
// Insert left stem values // Insert left stem values
s.SetRoot(EmptyRef) s.root = emptyRef
if err := s.InsertValuesAtStem(leftStem, leftValues, nil); err != nil { if err := s.InsertValuesAtStem(leftStem, leftValues, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -79,8 +79,8 @@ func TestInternalNodeGetWithResolver(t *testing.T) {
rootRef := s.newInternalRef(0) rootRef := s.newInternalRef(0)
rootNode := s.getInternal(rootRef.Index()) rootNode := s.getInternal(rootRef.Index())
rootNode.left = hashedChild rootNode.left = hashedChild
rootNode.right = EmptyRef rootNode.right = emptyRef
s.SetRoot(rootRef) s.root = rootRef
// Mock resolver that returns a stem node // Mock resolver that returns a stem node
resolver := func(path []byte, hash common.Hash) ([]byte, error) { resolver := func(path []byte, hash common.Hash) ([]byte, error) {
@ -90,7 +90,7 @@ func TestInternalNodeGetWithResolver(t *testing.T) {
ref := rs.newStemRef(stem, 1) ref := rs.newStemRef(stem, 1)
sn := rs.getStem(ref.Index()) sn := rs.getStem(ref.Index())
sn.setValue(5, common.HexToHash("0xabcd").Bytes()) sn.setValue(5, common.HexToHash("0xabcd").Bytes())
return rs.SerializeNode(ref), nil return rs.serializeNode(ref), nil
} }
return nil, errors.New("node not found") return nil, errors.New("node not found")
} }
@ -173,12 +173,12 @@ func TestInternalNodeHash(t *testing.T) {
rootNode := s.getInternal(rootRef.Index()) rootNode := s.getInternal(rootRef.Index())
rootNode.left = leftRef rootNode.left = leftRef
rootNode.right = rightRef rootNode.right = rightRef
s.SetRoot(rootRef) s.root = rootRef
hash1 := s.ComputeHash(rootRef) hash1 := s.computeHash(rootRef)
// Hash should be deterministic // Hash should be deterministic
hash2 := s.ComputeHash(rootRef) hash2 := s.computeHash(rootRef)
if hash1 != hash2 { if hash1 != hash2 {
t.Errorf("Hash not deterministic: %x != %x", hash1, hash2) t.Errorf("Hash not deterministic: %x != %x", hash1, hash2)
} }
@ -186,7 +186,7 @@ func TestInternalNodeHash(t *testing.T) {
// Changing a child should change the hash // Changing a child should change the hash
rootNode.left = s.newHashedRef(common.HexToHash("0x3333")) rootNode.left = s.newHashedRef(common.HexToHash("0x3333"))
rootNode.mustRecompute = true rootNode.mustRecompute = true
hash3 := s.ComputeHash(rootRef) hash3 := s.computeHash(rootRef)
if hash1 == hash3 { if hash1 == hash3 {
t.Error("Hash didn't change after modifying left child") t.Error("Hash didn't change after modifying left child")
} }
@ -290,7 +290,7 @@ func TestInternalNodeCollectNodes(t *testing.T) {
collectedPaths = append(collectedPaths, pathCopy) collectedPaths = append(collectedPaths, pathCopy)
} }
err := s.CollectNodes(s.Root(), []byte{1}, flushFn) err := s.collectNodes(s.root, []byte{1}, flushFn)
if err != nil { if err != nil {
t.Fatalf("Failed to collect nodes: %v", err) t.Fatalf("Failed to collect nodes: %v", err)
} }
@ -322,7 +322,7 @@ func TestInternalNodeGetHeight(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
height := s.GetHeight(s.Root()) height := s.getHeight(s.root)
if height < 2 { if height < 2 {
t.Errorf("Expected height >= 2, got %d", height) t.Errorf("Expected height >= 2, got %d", height)
} }

View file

@ -26,14 +26,14 @@ import (
var errIteratorEnd = errors.New("end of iteration") var errIteratorEnd = errors.New("end of iteration")
type binaryNodeIteratorState struct { type binaryNodeIteratorState struct {
Node NodeRef Node nodeRef
Index int Index int
} }
type binaryNodeIterator struct { type binaryNodeIterator struct {
trie *BinaryTrie trie *BinaryTrie
store *NodeStore store *NodeStore
current NodeRef current nodeRef
lastErr error lastErr error
stack []binaryNodeIteratorState stack []binaryNodeIteratorState
@ -43,7 +43,7 @@ func newBinaryNodeIterator(t *BinaryTrie, _ []byte) (trie.NodeIterator, error) {
if t.Hash() == zero { if t.Hash() == zero {
return &binaryNodeIterator{trie: t, store: t.store, lastErr: errIteratorEnd}, nil return &binaryNodeIterator{trie: t, store: t.store, lastErr: errIteratorEnd}, nil
} }
it := &binaryNodeIterator{trie: t, store: t.store, current: t.store.Root()} it := &binaryNodeIterator{trie: t, store: t.store, current: t.store.root}
return it, nil return it, nil
} }
@ -55,13 +55,13 @@ func (it *binaryNodeIterator) Next(descend bool) bool {
} }
if len(it.stack) == 0 { if len(it.stack) == 0 {
it.stack = append(it.stack, binaryNodeIteratorState{Node: it.trie.store.Root()}) it.stack = append(it.stack, binaryNodeIteratorState{Node: it.trie.store.root})
it.current = it.trie.store.Root() it.current = it.trie.store.root
return true return true
} }
switch it.current.Kind() { switch it.current.Kind() {
case KindInternal: case kindInternal:
// index: 0 = nothing visited, 1 = left visited, 2 = right visited. // index: 0 = nothing visited, 1 = left visited, 2 = right visited.
node := it.store.getInternal(it.current.Index()) node := it.store.getInternal(it.current.Index())
context := &it.stack[len(it.stack)-1] context := &it.stack[len(it.stack)-1]
@ -107,7 +107,7 @@ func (it *binaryNodeIterator) Next(descend bool) bool {
it.stack[len(it.stack)-1].Index++ it.stack[len(it.stack)-1].Index++
return it.Next(descend) return it.Next(descend)
case KindStem: case kindStem:
// Look for the next non-empty value in this stem. // Look for the next non-empty value in this stem.
sn := it.store.getStem(it.current.Index()) sn := it.store.getStem(it.current.Index())
for i := it.stack[len(it.stack)-1].Index; i < 256; i++ { for i := it.stack[len(it.stack)-1].Index; i < 256; i++ {
@ -127,7 +127,7 @@ func (it *binaryNodeIterator) Next(descend bool) bool {
it.stack[len(it.stack)-1].Index++ it.stack[len(it.stack)-1].Index++
return it.Next(descend) return it.Next(descend)
case KindHashed: case kindHashed:
// Resolve the hashed node from disk, then rewire the parent to point at the // Resolve the hashed node from disk, then rewire the parent to point at the
// resolved node in place. // resolved node in place.
if len(it.stack) < 2 { if len(it.stack) < 2 {
@ -140,7 +140,7 @@ func (it *binaryNodeIterator) Next(descend bool) bool {
it.lastErr = err it.lastErr = err
return false return false
} }
resolved, err := it.store.DeserializeNodeWithHash(data, len(it.stack)-1, hn.Hash()) resolved, err := it.store.deserializeNodeWithHash(data, len(it.stack)-1, hn.Hash())
if err != nil { if err != nil {
it.lastErr = err it.lastErr = err
return false return false
@ -159,7 +159,7 @@ func (it *binaryNodeIterator) Next(descend bool) bool {
it.store.freeHashedNode(oldHashedIdx) it.store.freeHashedNode(oldHashedIdx)
return it.Next(descend) return it.Next(descend)
case KindEmpty: case kindEmpty:
return false return false
default: default:
@ -175,7 +175,7 @@ func (it *binaryNodeIterator) Error() error {
} }
func (it *binaryNodeIterator) Hash() common.Hash { func (it *binaryNodeIterator) Hash() common.Hash {
return it.store.ComputeHash(it.current) return it.store.computeHash(it.current)
} }
// Parent returns the hash of the current node's parent. When the immediate // Parent returns the hash of the current node's parent. When the immediate
@ -185,7 +185,7 @@ func (it *binaryNodeIterator) Parent() common.Hash {
if len(it.stack) < 2 { if len(it.stack) < 2 {
return common.Hash{} return common.Hash{}
} }
return it.store.ComputeHash(it.stack[len(it.stack)-2].Node) return it.store.computeHash(it.stack[len(it.stack)-2].Node)
} }
// Path returns the bit-path to the current node. // Path returns the bit-path to the current node.
@ -205,7 +205,7 @@ func (it *binaryNodeIterator) Path() []byte {
} }
func (it *binaryNodeIterator) NodeBlob() []byte { func (it *binaryNodeIterator) NodeBlob() []byte {
return it.store.SerializeNode(it.current) return it.store.serializeNode(it.current)
} }
// Leaf reports whether the iterator is currently positioned at a leaf value. // Leaf reports whether the iterator is currently positioned at a leaf value.
@ -214,7 +214,7 @@ func (it *binaryNodeIterator) NodeBlob() []byte {
// StemNode itself. The stack Index points to the NEXT position after the // StemNode itself. The stack Index points to the NEXT position after the
// current value, so Index == 0 means we haven't yielded anything yet. // current value, so Index == 0 means we haven't yielded anything yet.
func (it *binaryNodeIterator) Leaf() bool { func (it *binaryNodeIterator) Leaf() bool {
if it.current.Kind() != KindStem { if it.current.Kind() != kindStem {
return false return false
} }
@ -236,7 +236,7 @@ func (it *binaryNodeIterator) Leaf() bool {
// positioned at a leaf. Callers must not retain references to the returned // positioned at a leaf. Callers must not retain references to the returned
// slice after calling Next. // slice after calling Next.
func (it *binaryNodeIterator) LeafKey() []byte { func (it *binaryNodeIterator) LeafKey() []byte {
if it.current.Kind() != KindStem { if it.current.Kind() != kindStem {
panic("Leaf() called on an binary node iterator not at a leaf location") panic("Leaf() called on an binary node iterator not at a leaf location")
} }
sn := it.store.getStem(it.current.Index()) sn := it.store.getStem(it.current.Index())
@ -247,7 +247,7 @@ func (it *binaryNodeIterator) LeafKey() []byte {
// at a leaf. Callers must not retain references to the returned slice after // at a leaf. Callers must not retain references to the returned slice after
// calling Next. // calling Next.
func (it *binaryNodeIterator) LeafBlob() []byte { func (it *binaryNodeIterator) LeafBlob() []byte {
if it.current.Kind() != KindStem { if it.current.Kind() != kindStem {
panic("LeafBlob() called on an binary node iterator not at a leaf location") panic("LeafBlob() called on an binary node iterator not at a leaf location")
} }
sn := it.store.getStem(it.current.Index()) sn := it.store.getStem(it.current.Index())
@ -258,7 +258,7 @@ func (it *binaryNodeIterator) LeafBlob() []byte {
// not positioned at a leaf. Callers must not retain references to the // not positioned at a leaf. Callers must not retain references to the
// returned slices after calling Next. // returned slices after calling Next.
func (it *binaryNodeIterator) LeafProof() [][]byte { func (it *binaryNodeIterator) LeafProof() [][]byte {
if it.current.Kind() != KindStem { if it.current.Kind() != kindStem {
panic("LeafProof() called on an binary node iterator not at a leaf location") panic("LeafProof() called on an binary node iterator not at a leaf location")
} }
sn := it.store.getStem(it.current.Index()) sn := it.store.getStem(it.current.Index())
@ -276,10 +276,10 @@ func (it *binaryNodeIterator) LeafProof() [][]byte {
internalNode := it.store.getInternal(state.Node.Index()) internalNode := it.store.getInternal(state.Node.Index())
if state.Index == 0 { if state.Index == 0 {
rh := it.store.ComputeHash(internalNode.right) rh := it.store.computeHash(internalNode.right)
proof = append(proof, rh.Bytes()) proof = append(proof, rh.Bytes())
} else { } else {
lh := it.store.ComputeHash(internalNode.left) lh := it.store.computeHash(internalNode.left)
proof = append(proof, lh.Bytes()) proof = append(proof, lh.Bytes())
} }
} }

View file

@ -144,8 +144,8 @@ func TestIteratorEmptyNodeBacktrack(t *testing.T) {
{common.HexToHash("8000000000000000000000000000000000000000000000000000000000000001"), oneKey}, {common.HexToHash("8000000000000000000000000000000000000000000000000000000000000001"), oneKey},
}) })
if tr.store.Root().Kind() != KindInternal { if tr.store.root.Kind() != kindInternal {
t.Fatalf("expected InternalNode root, got kind %d", tr.store.Root().Kind()) t.Fatalf("expected InternalNode root, got kind %d", tr.store.root.Kind())
} }
if leaves := countLeaves(t, tr); leaves != 2 { if leaves := countLeaves(t, tr); leaves != 2 {
t.Fatalf("expected 2 leaves, got %d (Empty backtrack bug?)", leaves) t.Fatalf("expected 2 leaves, got %d (Empty backtrack bug?)", leaves)
@ -161,8 +161,8 @@ func TestIteratorHashedNodeNilData(t *testing.T) {
{common.HexToHash("8000000000000000000000000000000000000000000000000000000000000001"), oneKey}, {common.HexToHash("8000000000000000000000000000000000000000000000000000000000000001"), oneKey},
}) })
root := tr.store.Root() root := tr.store.root
if root.Kind() != KindInternal { if root.Kind() != kindInternal {
t.Fatalf("expected InternalNode root, got kind %d", root.Kind()) t.Fatalf("expected InternalNode root, got kind %d", root.Kind())
} }
rootNode := tr.store.getInternal(root.Index()) rootNode := tr.store.getInternal(root.Index())

View file

@ -16,38 +16,38 @@
package bintrie package bintrie
// NodeKind identifies the type of a trie node stored in a NodeRef. // nodeKind identifies the type of a trie node stored in a nodeRef.
type NodeKind uint8 type nodeKind uint8
const ( const (
KindEmpty NodeKind = iota kindEmpty nodeKind = iota
KindInternal kindInternal
KindStem // up to 256 values per stem kindStem // up to 256 values per stem
KindHashed kindHashed
) )
// NodeRef is a compact, GC-invisible reference to a node in a NodeStore. // nodeRef is a compact, GC-invisible reference to a node in a NodeStore.
// It packs a 2-bit type tag (bits 31-30) and a 30-bit index (bits 29-0) // It packs a 2-bit type tag (bits 31-30) and a 30-bit index (bits 29-0)
// into a single uint32. Because NodeRef contains no Go pointers, slices // into a single uint32. Because nodeRef contains no Go pointers, slices
// of structs containing NodeRef fields are allocated in noscan spans — // of structs containing nodeRef fields are allocated in noscan spans —
// the garbage collector never examines them. // the garbage collector never examines them.
type NodeRef uint32 type nodeRef uint32
const ( const (
kindShift uint32 = 30 kindShift uint32 = 30
indexMask uint32 = (1 << kindShift) - 1 indexMask uint32 = (1 << kindShift) - 1
// EmptyRef represents an empty node. // emptyRef represents an empty node.
EmptyRef NodeRef = 0 emptyRef nodeRef = 0
) )
func MakeRef(kind NodeKind, idx uint32) NodeRef { func makeRef(kind nodeKind, idx uint32) nodeRef {
return NodeRef(uint32(kind)<<kindShift | (idx & indexMask)) return nodeRef(uint32(kind)<<kindShift | (idx & indexMask))
} }
func (r NodeRef) Kind() NodeKind { return NodeKind(uint32(r) >> kindShift) } func (r nodeRef) Kind() nodeKind { return nodeKind(uint32(r) >> kindShift) }
// Index within the typed pool. // Index within the typed pool.
func (r NodeRef) Index() uint32 { return uint32(r) & indexMask } func (r nodeRef) Index() uint32 { return uint32(r) & indexMask }
func (r NodeRef) IsEmpty() bool { return r == EmptyRef } func (r nodeRef) IsEmpty() bool { return r == emptyRef }

View file

@ -37,7 +37,7 @@ type NodeStore struct {
hashedChunks []*[storeChunkSize]HashedNode hashedChunks []*[storeChunkSize]HashedNode
hashedCount uint32 hashedCount uint32
root NodeRef root nodeRef
// Free lists for recycling deleted node slots. // Free lists for recycling deleted node slots.
freeInternals []uint32 freeInternals []uint32
@ -46,13 +46,9 @@ type NodeStore struct {
} }
func NewNodeStore() *NodeStore { func NewNodeStore() *NodeStore {
return &NodeStore{root: EmptyRef} return &NodeStore{root: emptyRef}
} }
func (s *NodeStore) Root() NodeRef { return s.root }
func (s *NodeStore) SetRoot(ref NodeRef) { s.root = ref }
func (s *NodeStore) allocInternal() uint32 { func (s *NodeStore) allocInternal() uint32 {
if n := len(s.freeInternals); n > 0 { if n := len(s.freeInternals); n > 0 {
idx := s.freeInternals[n-1] idx := s.freeInternals[n-1]
@ -76,7 +72,7 @@ func (s *NodeStore) getInternal(idx uint32) *InternalNode {
return &s.internalChunks[idx/storeChunkSize][idx%storeChunkSize] return &s.internalChunks[idx/storeChunkSize][idx%storeChunkSize]
} }
func (s *NodeStore) newInternalRef(depth int) NodeRef { func (s *NodeStore) newInternalRef(depth int) nodeRef {
if depth > 248 { if depth > 248 {
panic("node depth exceeds maximum binary trie depth") panic("node depth exceeds maximum binary trie depth")
} }
@ -85,7 +81,7 @@ func (s *NodeStore) newInternalRef(depth int) NodeRef {
n.depth = uint8(depth) n.depth = uint8(depth)
n.mustRecompute = true n.mustRecompute = true
n.dirty = true n.dirty = true
return MakeRef(KindInternal, idx) return makeRef(kindInternal, idx)
} }
func (s *NodeStore) allocStem() uint32 { func (s *NodeStore) allocStem() uint32 {
@ -111,7 +107,7 @@ func (s *NodeStore) getStem(idx uint32) *StemNode {
return &s.stemChunks[idx/storeChunkSize][idx%storeChunkSize] return &s.stemChunks[idx/storeChunkSize][idx%storeChunkSize]
} }
func (s *NodeStore) newStemRef(stem []byte, depth int) NodeRef { func (s *NodeStore) newStemRef(stem []byte, depth int) nodeRef {
if depth > 248 { if depth > 248 {
panic("node depth exceeds maximum binary trie depth") panic("node depth exceeds maximum binary trie depth")
} }
@ -121,7 +117,7 @@ func (s *NodeStore) newStemRef(stem []byte, depth int) NodeRef {
sn.depth = uint8(depth) sn.depth = uint8(depth)
sn.mustRecompute = true sn.mustRecompute = true
sn.dirty = true sn.dirty = true
return MakeRef(KindStem, idx) return makeRef(kindStem, idx)
} }
func (s *NodeStore) allocHashed() uint32 { func (s *NodeStore) allocHashed() uint32 {
@ -151,10 +147,10 @@ func (s *NodeStore) freeHashedNode(idx uint32) {
s.freeHashed = append(s.freeHashed, idx) s.freeHashed = append(s.freeHashed, idx)
} }
func (s *NodeStore) newHashedRef(hash common.Hash) NodeRef { func (s *NodeStore) newHashedRef(hash common.Hash) nodeRef {
idx := s.allocHashed() idx := s.allocHashed()
*s.getHashed(idx) = HashedNode(hash) *s.getHashed(idx) = HashedNode(hash)
return MakeRef(KindHashed, idx) return makeRef(kindHashed, idx)
} }
func (s *NodeStore) Copy() *NodeStore { func (s *NodeStore) Copy() *NodeStore {

View file

@ -51,8 +51,8 @@ func TestStemNodeInsertSameStem(t *testing.T) {
} }
// Root should still be a StemNode // Root should still be a StemNode
if s.Root().Kind() != KindStem { if s.root.Kind() != kindStem {
t.Fatalf("Expected KindStem root, got kind %d", s.Root().Kind()) t.Fatalf("Expected kindStem root, got kind %d", s.root.Kind())
} }
// Check that both values are present // Check that both values are present
@ -87,12 +87,12 @@ func TestStemNodeInsertDifferentStem(t *testing.T) {
} }
// Should now be an InternalNode // Should now be an InternalNode
if s.Root().Kind() != KindInternal { if s.root.Kind() != kindInternal {
t.Fatalf("Expected KindInternal root, got kind %d", s.Root().Kind()) t.Fatalf("Expected kindInternal root, got kind %d", s.root.Kind())
} }
// Check depth // Check depth
rootNode := s.getInternal(s.Root().Index()) rootNode := s.getInternal(s.root.Index())
if rootNode.depth != 0 { if rootNode.depth != 0 {
t.Errorf("Expected depth 0, got %d", rootNode.depth) t.Errorf("Expected depth 0, got %d", rootNode.depth)
} }
@ -172,10 +172,10 @@ func TestStemNodeHash(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
hash1 := s.ComputeHash(s.Root()) hash1 := s.computeHash(s.root)
// Hash should be deterministic // Hash should be deterministic
hash2 := s.ComputeHash(s.Root()) hash2 := s.computeHash(s.root)
if hash1 != hash2 { if hash1 != hash2 {
t.Errorf("Hash not deterministic: %x != %x", hash1, hash2) t.Errorf("Hash not deterministic: %x != %x", hash1, hash2)
} }
@ -187,7 +187,7 @@ func TestStemNodeHash(t *testing.T) {
if err := s.Insert(key2, value2, nil); err != nil { if err := s.Insert(key2, value2, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
hash3 := s.ComputeHash(s.Root()) hash3 := s.computeHash(s.root)
if hash1 == hash3 { if hash1 == hash3 {
t.Error("Hash didn't change after modifying values") t.Error("Hash didn't change after modifying values")
} }
@ -295,7 +295,7 @@ func TestStemNodeGetHeight(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
height := s.GetHeight(s.Root()) height := s.getHeight(s.root)
if height != 1 { if height != 1 {
t.Errorf("Expected height 1, got %d", height) t.Errorf("Expected height 1, got %d", height)
} }
@ -320,7 +320,7 @@ func TestStemNodeCollectNodes(t *testing.T) {
collectedPaths = append(collectedPaths, pathCopy) collectedPaths = append(collectedPaths, pathCopy)
} }
err := s.CollectNodes(s.Root(), []byte{0, 1, 0}, flushFn) err := s.collectNodes(s.root, []byte{0, 1, 0}, flushFn)
if err != nil { if err != nil {
t.Fatalf("Failed to collect nodes: %v", err) t.Fatalf("Failed to collect nodes: %v", err)
} }

View file

@ -28,18 +28,18 @@ import (
type NodeFlushFn func(path []byte, hash common.Hash, serialized []byte) type NodeFlushFn func(path []byte, hash common.Hash, serialized []byte)
func (s *NodeStore) Hash() common.Hash { func (s *NodeStore) Hash() common.Hash {
return s.ComputeHash(s.root) return s.computeHash(s.root)
} }
func (s *NodeStore) ComputeHash(ref NodeRef) common.Hash { func (s *NodeStore) computeHash(ref nodeRef) common.Hash {
switch ref.Kind() { switch ref.Kind() {
case KindInternal: case kindInternal:
return s.hashInternal(ref.Index()) return s.hashInternal(ref.Index())
case KindStem: case kindStem:
return s.getStem(ref.Index()).Hash() return s.getStem(ref.Index()).Hash()
case KindHashed: case kindHashed:
return s.getHashed(ref.Index()).Hash() return s.getHashed(ref.Index()).Hash()
case KindEmpty: case kindEmpty:
return common.Hash{} return common.Hash{}
default: default:
return common.Hash{} return common.Hash{}
@ -65,12 +65,12 @@ func (s *NodeStore) hashInternal(idx uint32) common.Hash {
if !node.left.IsEmpty() { if !node.left.IsEmpty() {
wg.Add(1) wg.Add(1)
go func() { go func() {
lh = s.ComputeHash(node.left) lh = s.computeHash(node.left)
wg.Done() wg.Done()
}() }()
} }
if !node.right.IsEmpty() { if !node.right.IsEmpty() {
rh := s.ComputeHash(node.right) rh := s.computeHash(node.right)
copy(input[32:], rh[:]) copy(input[32:], rh[:])
} }
wg.Wait() wg.Wait()
@ -82,11 +82,11 @@ func (s *NodeStore) hashInternal(idx uint32) common.Hash {
var input [64]byte var input [64]byte
if !node.left.IsEmpty() { if !node.left.IsEmpty() {
lh := s.ComputeHash(node.left) lh := s.computeHash(node.left)
copy(input[:32], lh[:]) copy(input[:32], lh[:])
} }
if !node.right.IsEmpty() { if !node.right.IsEmpty() {
rh := s.ComputeHash(node.right) rh := s.computeHash(node.right)
copy(input[32:], rh[:]) copy(input[32:], rh[:])
} }
node.hash = sha256Sum256(input[:]) node.hash = sha256Sum256(input[:])
@ -95,19 +95,19 @@ func (s *NodeStore) hashInternal(idx uint32) common.Hash {
} }
// SerializeNode serializes a node into the flat on-disk format. // SerializeNode serializes a node into the flat on-disk format.
func (s *NodeStore) SerializeNode(ref NodeRef) []byte { func (s *NodeStore) serializeNode(ref nodeRef) []byte {
switch ref.Kind() { switch ref.Kind() {
case KindInternal: case kindInternal:
node := s.getInternal(ref.Index()) node := s.getInternal(ref.Index())
var serialized [NodeTypeBytes + HashSize + HashSize]byte var serialized [NodeTypeBytes + HashSize + HashSize]byte
serialized[0] = nodeTypeInternal serialized[0] = nodeTypeInternal
lh := s.ComputeHash(node.left) lh := s.computeHash(node.left)
rh := s.ComputeHash(node.right) rh := s.computeHash(node.right)
copy(serialized[NodeTypeBytes:NodeTypeBytes+HashSize], lh[:]) copy(serialized[NodeTypeBytes:NodeTypeBytes+HashSize], lh[:])
copy(serialized[NodeTypeBytes+HashSize:], rh[:]) copy(serialized[NodeTypeBytes+HashSize:], rh[:])
return serialized[:] return serialized[:]
case KindStem: case kindStem:
sn := s.getStem(ref.Index()) sn := s.getStem(ref.Index())
serializedLen := NodeTypeBytes + StemSize + StemBitmapSize + len(sn.valueData) serializedLen := NodeTypeBytes + StemSize + StemBitmapSize + len(sn.valueData)
serialized := make([]byte, serializedLen) serialized := make([]byte, serializedLen)
@ -126,31 +126,31 @@ var errInvalidSerializedLength = errors.New("invalid serialized node length")
// DeserializeNode deserializes a node from bytes, recomputing its hash. The // DeserializeNode deserializes a node from bytes, recomputing its hash. The
// returned node is marked dirty (provenance unknown, safe re-flush default). // returned node is marked dirty (provenance unknown, safe re-flush default).
func (s *NodeStore) DeserializeNode(serialized []byte, depth int) (NodeRef, error) { func (s *NodeStore) deserializeNode(serialized []byte, depth int) (nodeRef, error) {
return s.deserializeNode(serialized, depth, common.Hash{}, true, true) return s.decodeNode(serialized, depth, common.Hash{}, true, true)
} }
// DeserializeNodeWithHash deserializes a node whose hash is already known and // DeserializeNodeWithHash deserializes a node whose hash is already known and
// whose blob is already on disk (mustRecompute=false, dirty=false). // whose blob is already on disk (mustRecompute=false, dirty=false).
func (s *NodeStore) DeserializeNodeWithHash(serialized []byte, depth int, hn common.Hash) (NodeRef, error) { func (s *NodeStore) deserializeNodeWithHash(serialized []byte, depth int, hn common.Hash) (nodeRef, error) {
return s.deserializeNode(serialized, depth, hn, false, false) return s.decodeNode(serialized, depth, hn, false, false)
} }
func (s *NodeStore) deserializeNode(serialized []byte, depth int, hn common.Hash, mustRecompute, dirty bool) (NodeRef, error) { func (s *NodeStore) decodeNode(serialized []byte, depth int, hn common.Hash, mustRecompute, dirty bool) (nodeRef, error) {
if len(serialized) == 0 { if len(serialized) == 0 {
return EmptyRef, nil return emptyRef, nil
} }
switch serialized[0] { switch serialized[0] {
case nodeTypeInternal: case nodeTypeInternal:
if len(serialized) != NodeTypeBytes+2*HashSize { if len(serialized) != NodeTypeBytes+2*HashSize {
return EmptyRef, errInvalidSerializedLength return emptyRef, errInvalidSerializedLength
} }
var leftHash, rightHash common.Hash var leftHash, rightHash common.Hash
copy(leftHash[:], serialized[NodeTypeBytes:NodeTypeBytes+HashSize]) copy(leftHash[:], serialized[NodeTypeBytes:NodeTypeBytes+HashSize])
copy(rightHash[:], serialized[NodeTypeBytes+HashSize:]) copy(rightHash[:], serialized[NodeTypeBytes+HashSize:])
var leftRef, rightRef NodeRef var leftRef, rightRef nodeRef
if leftHash != (common.Hash{}) { if leftHash != (common.Hash{}) {
leftRef = s.newHashedRef(leftHash) leftRef = s.newHashedRef(leftHash)
} }
@ -171,7 +171,7 @@ func (s *NodeStore) deserializeNode(serialized []byte, depth int, hn common.Hash
case nodeTypeStem: case nodeTypeStem:
if len(serialized) < 64 { if len(serialized) < 64 {
return EmptyRef, errInvalidSerializedLength return emptyRef, errInvalidSerializedLength
} }
stemIdx := s.allocStem() stemIdx := s.allocStem()
sn := s.getStem(stemIdx) sn := s.getStem(stemIdx)
@ -186,7 +186,7 @@ func (s *NodeStore) deserializeNode(serialized []byte, depth int, hn common.Hash
dataStart := NodeTypeBytes + StemSize + StemBitmapSize dataStart := NodeTypeBytes + StemSize + StemBitmapSize
dataEnd := dataStart + int(count)*HashSize dataEnd := dataStart + int(count)*HashSize
if len(serialized) < dataEnd { if len(serialized) < dataEnd {
return EmptyRef, errInvalidSerializedLength return emptyRef, errInvalidSerializedLength
} }
// Zero-copy: aliases the serialized buffer; ensureWritable() COWs before mutation. // Zero-copy: aliases the serialized buffer; ensureWritable() COWs before mutation.
sn.valueData = serialized[dataStart:dataEnd] sn.valueData = serialized[dataStart:dataEnd]
@ -195,21 +195,21 @@ func (s *NodeStore) deserializeNode(serialized []byte, depth int, hn common.Hash
sn.hash = hn sn.hash = hn
sn.mustRecompute = mustRecompute sn.mustRecompute = mustRecompute
sn.dirty = dirty sn.dirty = dirty
return MakeRef(KindStem, stemIdx), nil return makeRef(kindStem, stemIdx), nil
default: default:
return EmptyRef, errors.New("invalid node type") return emptyRef, errors.New("invalid node type")
} }
} }
// CollectNodes flushes every node that needs flushing via flushfn in post-order. // CollectNodes flushes every node that needs flushing via flushfn in post-order.
// Invariant: any ancestor of a node that needs flushing is itself marked, so a // Invariant: any ancestor of a node that needs flushing is itself marked, so a
// clean root means the whole subtree is clean. // clean root means the whole subtree is clean.
func (s *NodeStore) CollectNodes(ref NodeRef, path []byte, flushfn NodeFlushFn) error { func (s *NodeStore) collectNodes(ref nodeRef, path []byte, flushfn NodeFlushFn) error {
switch ref.Kind() { switch ref.Kind() {
case KindEmpty: case kindEmpty:
return nil return nil
case KindInternal: case kindInternal:
node := s.getInternal(ref.Index()) node := s.getInternal(ref.Index())
if !node.dirty { if !node.dirty {
return nil return nil
@ -217,50 +217,50 @@ func (s *NodeStore) CollectNodes(ref NodeRef, path []byte, flushfn NodeFlushFn)
leftPath := make([]byte, len(path)+1) leftPath := make([]byte, len(path)+1)
copy(leftPath, path) copy(leftPath, path)
leftPath[len(path)] = 0 leftPath[len(path)] = 0
if err := s.CollectNodes(node.left, leftPath, flushfn); err != nil { if err := s.collectNodes(node.left, leftPath, flushfn); err != nil {
return err return err
} }
rightPath := make([]byte, len(path)+1) rightPath := make([]byte, len(path)+1)
copy(rightPath, path) copy(rightPath, path)
rightPath[len(path)] = 1 rightPath[len(path)] = 1
if err := s.CollectNodes(node.right, rightPath, flushfn); err != nil { if err := s.collectNodes(node.right, rightPath, flushfn); err != nil {
return err return err
} }
flushfn(path, s.ComputeHash(ref), s.SerializeNode(ref)) flushfn(path, s.computeHash(ref), s.serializeNode(ref))
node.dirty = false node.dirty = false
return nil return nil
case KindStem: case kindStem:
sn := s.getStem(ref.Index()) sn := s.getStem(ref.Index())
if !sn.dirty { if !sn.dirty {
return nil return nil
} }
flushfn(path, s.ComputeHash(ref), s.SerializeNode(ref)) flushfn(path, s.computeHash(ref), s.serializeNode(ref))
sn.dirty = false sn.dirty = false
return nil return nil
case KindHashed: case kindHashed:
return nil // Already committed return nil // Already committed
default: default:
return fmt.Errorf("CollectNodes: unexpected kind %d", ref.Kind()) return fmt.Errorf("CollectNodes: unexpected kind %d", ref.Kind())
} }
} }
func (s *NodeStore) ToDot(ref NodeRef, parent, path string) string { func (s *NodeStore) toDot(ref nodeRef, parent, path string) string {
switch ref.Kind() { switch ref.Kind() {
case KindInternal: case kindInternal:
node := s.getInternal(ref.Index()) node := s.getInternal(ref.Index())
me := fmt.Sprintf("internal%s", path) me := fmt.Sprintf("internal%s", path)
ret := fmt.Sprintf("%s [label=\"I: %x\"]\n", me, s.ComputeHash(ref)) ret := fmt.Sprintf("%s [label=\"I: %x\"]\n", me, s.computeHash(ref))
if len(parent) > 0 { if len(parent) > 0 {
ret = fmt.Sprintf("%s %s -> %s\n", ret, parent, me) ret = fmt.Sprintf("%s %s -> %s\n", ret, parent, me)
} }
if !node.left.IsEmpty() { if !node.left.IsEmpty() {
ret += s.ToDot(node.left, me, fmt.Sprintf("%s%02x", path, 0)) ret += s.toDot(node.left, me, fmt.Sprintf("%s%02x", path, 0))
} }
if !node.right.IsEmpty() { if !node.right.IsEmpty() {
ret += s.ToDot(node.right, me, fmt.Sprintf("%s%02x", path, 1)) ret += s.toDot(node.right, me, fmt.Sprintf("%s%02x", path, 1))
} }
return ret return ret
case KindStem: case kindStem:
sn := s.getStem(ref.Index()) sn := s.getStem(ref.Index())
me := fmt.Sprintf("stem%s", path) me := fmt.Sprintf("stem%s", path)
ret := fmt.Sprintf("%s [label=\"stem=%x c=%x\"]\n", me, sn.Stem, sn.Hash()) ret := fmt.Sprintf("%s [label=\"stem=%x c=%x\"]\n", me, sn.Stem, sn.Hash())
@ -276,7 +276,7 @@ func (s *NodeStore) ToDot(ref NodeRef, parent, path string) string {
ret += fmt.Sprintf("%s -> %s%x\n", me, me, i) ret += fmt.Sprintf("%s -> %s%x\n", me, me, i)
} }
return ret return ret
case KindHashed: case kindHashed:
hn := s.getHashed(ref.Index()) hn := s.getHashed(ref.Index())
me := fmt.Sprintf("hash%s", path) me := fmt.Sprintf("hash%s", path)
ret := fmt.Sprintf("%s [label=\"%x\"]\n", me, hn.Hash()) ret := fmt.Sprintf("%s [label=\"%x\"]\n", me, hn.Hash())

View file

@ -30,7 +30,7 @@ func (s *NodeStore) GetSingle(stem []byte, suffix byte, resolver NodeResolverFn)
return s.getSingle(s.root, stem, suffix, resolver) return s.getSingle(s.root, stem, suffix, resolver)
} }
func (s *NodeStore) getSingle(ref NodeRef, stem []byte, suffix byte, resolver NodeResolverFn) ([]byte, error) { func (s *NodeStore) getSingle(ref nodeRef, stem []byte, suffix byte, resolver NodeResolverFn) ([]byte, error) {
cur := ref cur := ref
// Track parent for HashedNode resolution (update parent's child ref). // Track parent for HashedNode resolution (update parent's child ref).
var parentIdx uint32 var parentIdx uint32
@ -39,7 +39,7 @@ func (s *NodeStore) getSingle(ref NodeRef, stem []byte, suffix byte, resolver No
for { for {
switch cur.Kind() { switch cur.Kind() {
case KindInternal: case kindInternal:
node := s.getInternal(cur.Index()) node := s.getInternal(cur.Index())
if node.depth >= 31*8 { if node.depth >= 31*8 {
return nil, errors.New("node too deep") return nil, errors.New("node too deep")
@ -55,14 +55,14 @@ func (s *NodeStore) getSingle(ref NodeRef, stem []byte, suffix byte, resolver No
cur = node.right cur = node.right
} }
case KindStem: case kindStem:
sn := s.getStem(cur.Index()) sn := s.getStem(cur.Index())
if sn.Stem != [StemSize]byte(stem[:StemSize]) { if sn.Stem != [StemSize]byte(stem[:StemSize]) {
return nil, nil return nil, nil
} }
return sn.getValue(suffix), nil return sn.getValue(suffix), nil
case KindHashed: case kindHashed:
if !hasParent { if !hasParent {
return nil, errors.New("getSingle: hashed node at root") return nil, errors.New("getSingle: hashed node at root")
} }
@ -79,7 +79,7 @@ func (s *NodeStore) getSingle(ref NodeRef, stem []byte, suffix byte, resolver No
if err != nil { if err != nil {
return nil, fmt.Errorf("getSingle resolve error: %w", err) return nil, fmt.Errorf("getSingle resolve error: %w", err)
} }
resolved, err := s.DeserializeNodeWithHash(data, int(parentNode.depth)+1, hn.Hash()) resolved, err := s.deserializeNodeWithHash(data, int(parentNode.depth)+1, hn.Hash())
if err != nil { if err != nil {
return nil, fmt.Errorf("getSingle deserialization error: %w", err) return nil, fmt.Errorf("getSingle deserialization error: %w", err)
} }
@ -92,7 +92,7 @@ func (s *NodeStore) getSingle(ref NodeRef, stem []byte, suffix byte, resolver No
} }
cur = resolved cur = resolved
case KindEmpty: case kindEmpty:
return nil, nil return nil, nil
default: default:
@ -105,7 +105,7 @@ func (s *NodeStore) GetValuesAtStem(stem []byte, resolver NodeResolverFn) ([][]b
return s.getValuesAtStem(s.root, stem, resolver) return s.getValuesAtStem(s.root, stem, resolver)
} }
func (s *NodeStore) getValuesAtStem(ref NodeRef, stem []byte, resolver NodeResolverFn) ([][]byte, error) { func (s *NodeStore) getValuesAtStem(ref nodeRef, stem []byte, resolver NodeResolverFn) ([][]byte, error) {
cur := ref cur := ref
var parentIdx uint32 var parentIdx uint32
var parentIsLeft bool var parentIsLeft bool
@ -113,7 +113,7 @@ func (s *NodeStore) getValuesAtStem(ref NodeRef, stem []byte, resolver NodeResol
for { for {
switch cur.Kind() { switch cur.Kind() {
case KindInternal: case kindInternal:
node := s.getInternal(cur.Index()) node := s.getInternal(cur.Index())
if node.depth >= 31*8 { if node.depth >= 31*8 {
return nil, errors.New("node too deep") return nil, errors.New("node too deep")
@ -129,14 +129,14 @@ func (s *NodeStore) getValuesAtStem(ref NodeRef, stem []byte, resolver NodeResol
cur = node.right cur = node.right
} }
case KindStem: case kindStem:
sn := s.getStem(cur.Index()) sn := s.getStem(cur.Index())
if sn.Stem != [StemSize]byte(stem[:StemSize]) { if sn.Stem != [StemSize]byte(stem[:StemSize]) {
return nil, nil return nil, nil
} }
return sn.allValues(), nil return sn.allValues(), nil
case KindHashed: case kindHashed:
if !hasParent { if !hasParent {
return nil, errors.New("getValuesAtStem: hashed node at root") return nil, errors.New("getValuesAtStem: hashed node at root")
} }
@ -153,7 +153,7 @@ func (s *NodeStore) getValuesAtStem(ref NodeRef, stem []byte, resolver NodeResol
if err != nil { if err != nil {
return nil, fmt.Errorf("getValuesAtStem resolve error: %w", err) return nil, fmt.Errorf("getValuesAtStem resolve error: %w", err)
} }
resolved, err := s.DeserializeNodeWithHash(data, int(parentNode.depth)+1, hn.Hash()) resolved, err := s.deserializeNodeWithHash(data, int(parentNode.depth)+1, hn.Hash())
if err != nil { if err != nil {
return nil, fmt.Errorf("getValuesAtStem deserialization error: %w", err) return nil, fmt.Errorf("getValuesAtStem deserialization error: %w", err)
} }
@ -165,7 +165,7 @@ func (s *NodeStore) getValuesAtStem(ref NodeRef, stem []byte, resolver NodeResol
} }
cur = resolved cur = resolved
case KindEmpty: case kindEmpty:
var values [StemNodeWidth][]byte var values [StemNodeWidth][]byte
return values[:], nil return values[:], nil
@ -188,7 +188,7 @@ func (s *NodeStore) InsertSingle(stem []byte, suffix byte, value []byte, resolve
return nil return nil
} }
if s.root.Kind() == KindStem { if s.root.Kind() == kindStem {
sn := s.getStem(s.root.Index()) sn := s.getStem(s.root.Index())
if sn.Stem == [StemSize]byte(stem[:StemSize]) { if sn.Stem == [StemSize]byte(stem[:StemSize]) {
sn.setValue(suffix, value) sn.setValue(suffix, value)
@ -216,7 +216,7 @@ func (s *NodeStore) insertSingleInternal(stem []byte, suffix byte, value []byte,
for { for {
switch cur.Kind() { switch cur.Kind() {
case KindInternal: case kindInternal:
node := s.getInternal(cur.Index()) node := s.getInternal(cur.Index())
node.mustRecompute = true node.mustRecompute = true
node.dirty = true node.dirty = true
@ -229,7 +229,7 @@ func (s *NodeStore) insertSingleInternal(stem []byte, suffix byte, value []byte,
cur = node.right cur = node.right
} }
case KindStem: case kindStem:
sn := s.getStem(cur.Index()) sn := s.getStem(cur.Index())
if sn.Stem == [StemSize]byte(stem[:StemSize]) { if sn.Stem == [StemSize]byte(stem[:StemSize]) {
sn.setValue(suffix, value) sn.setValue(suffix, value)
@ -249,7 +249,7 @@ func (s *NodeStore) insertSingleInternal(stem []byte, suffix byte, value []byte,
} }
return nil return nil
case KindHashed: case kindHashed:
if pathLen == 0 { if pathLen == 0 {
return errors.New("insertSingle: hashed node at root") return errors.New("insertSingle: hashed node at root")
} }
@ -267,7 +267,7 @@ func (s *NodeStore) insertSingleInternal(stem []byte, suffix byte, value []byte,
if err != nil { if err != nil {
return fmt.Errorf("insertSingle resolve error: %w", err) return fmt.Errorf("insertSingle resolve error: %w", err)
} }
resolved, err := s.DeserializeNodeWithHash(data, int(parentNode.depth)+1, hn.Hash()) resolved, err := s.deserializeNodeWithHash(data, int(parentNode.depth)+1, hn.Hash())
if err != nil { if err != nil {
return fmt.Errorf("insertSingle deserialization error: %w", err) return fmt.Errorf("insertSingle deserialization error: %w", err)
} }
@ -279,7 +279,7 @@ func (s *NodeStore) insertSingleInternal(stem []byte, suffix byte, value []byte,
} }
cur = resolved cur = resolved
case KindEmpty: case kindEmpty:
parentDepth := int(s.getInternal(pathStack[pathLen-1].internalIdx).depth) + 1 parentDepth := int(s.getInternal(pathStack[pathLen-1].internalIdx).depth) + 1
ref := s.newStemRef(stem, parentDepth) ref := s.newStemRef(stem, parentDepth)
sn := s.getStem(ref.Index()) sn := s.getStem(ref.Index())
@ -300,11 +300,11 @@ func (s *NodeStore) insertSingleInternal(stem []byte, suffix byte, value []byte,
} }
// splitStemInsert splits a StemNode into InternalNodes for a divergent stem. // splitStemInsert splits a StemNode into InternalNodes for a divergent stem.
func (s *NodeStore) splitStemInsert(existingRef NodeRef, newStem []byte, suffix byte, value []byte, depth int) NodeRef { func (s *NodeStore) splitStemInsert(existingRef nodeRef, newStem []byte, suffix byte, value []byte, depth int) nodeRef {
existing := s.getStem(existingRef.Index()) existing := s.getStem(existingRef.Index())
existingDepth := depth existingDepth := depth
var firstRef NodeRef var firstRef nodeRef
var lastInternalIdx uint32 var lastInternalIdx uint32
var lastIsLeft bool var lastIsLeft bool
first := true first := true
@ -343,7 +343,7 @@ func (s *NodeStore) splitStemInsert(existingRef NodeRef, newStem []byte, suffix
newSn.mustRecompute = true newSn.mustRecompute = true
newSn.dirty = true newSn.dirty = true
newSn.setValue(suffix, value) newSn.setValue(suffix, value)
newStemRef := MakeRef(KindStem, newStemIdx) newStemRef := makeRef(kindStem, newStemIdx)
if bitExisting == 0 { if bitExisting == 0 {
newInternal.left = existingRef newInternal.left = existingRef
@ -371,13 +371,13 @@ func (s *NodeStore) InsertValuesAtStem(stem []byte, values [][]byte, resolver No
return nil return nil
} }
func (s *NodeStore) insertValuesAtStem(ref NodeRef, stem []byte, values [][]byte, resolver NodeResolverFn, depth int) (NodeRef, error) { func (s *NodeStore) insertValuesAtStem(ref nodeRef, stem []byte, values [][]byte, resolver NodeResolverFn, depth int) (nodeRef, error) {
switch ref.Kind() { switch ref.Kind() {
case KindInternal: case kindInternal:
node := s.getInternal(ref.Index()) node := s.getInternal(ref.Index())
bit := stem[node.depth/8] >> (7 - (node.depth % 8)) & 1 bit := stem[node.depth/8] >> (7 - (node.depth % 8)) & 1
if bit == 0 { if bit == 0 {
if node.left.Kind() == KindHashed { if node.left.Kind() == kindHashed {
if resolver == nil { if resolver == nil {
return ref, errors.New("insertValuesAtStem: cannot resolve hashed node without resolver") return ref, errors.New("insertValuesAtStem: cannot resolve hashed node without resolver")
} }
@ -390,7 +390,7 @@ func (s *NodeStore) insertValuesAtStem(ref NodeRef, stem []byte, values [][]byte
if err != nil { if err != nil {
return ref, fmt.Errorf("InsertValuesAtStem resolve error: %w", err) return ref, fmt.Errorf("InsertValuesAtStem resolve error: %w", err)
} }
resolved, err := s.DeserializeNodeWithHash(data, int(node.depth)+1, hn.Hash()) resolved, err := s.deserializeNodeWithHash(data, int(node.depth)+1, hn.Hash())
if err != nil { if err != nil {
return ref, fmt.Errorf("InsertValuesAtStem deserialization error: %w", err) return ref, fmt.Errorf("InsertValuesAtStem deserialization error: %w", err)
} }
@ -403,7 +403,7 @@ func (s *NodeStore) insertValuesAtStem(ref NodeRef, stem []byte, values [][]byte
} }
node.left = newChild node.left = newChild
} else { } else {
if node.right.Kind() == KindHashed { if node.right.Kind() == kindHashed {
if resolver == nil { if resolver == nil {
return ref, errors.New("insertValuesAtStem: cannot resolve hashed node without resolver") return ref, errors.New("insertValuesAtStem: cannot resolve hashed node without resolver")
} }
@ -416,7 +416,7 @@ func (s *NodeStore) insertValuesAtStem(ref NodeRef, stem []byte, values [][]byte
if err != nil { if err != nil {
return ref, fmt.Errorf("InsertValuesAtStem resolve error: %w", err) return ref, fmt.Errorf("InsertValuesAtStem resolve error: %w", err)
} }
resolved, err := s.DeserializeNodeWithHash(data, int(node.depth)+1, hn.Hash()) resolved, err := s.deserializeNodeWithHash(data, int(node.depth)+1, hn.Hash())
if err != nil { if err != nil {
return ref, fmt.Errorf("InsertValuesAtStem deserialization error: %w", err) return ref, fmt.Errorf("InsertValuesAtStem deserialization error: %w", err)
} }
@ -433,7 +433,7 @@ func (s *NodeStore) insertValuesAtStem(ref NodeRef, stem []byte, values [][]byte
node.dirty = true node.dirty = true
return ref, nil return ref, nil
case KindStem: case kindStem:
sn := s.getStem(ref.Index()) sn := s.getStem(ref.Index())
if sn.Stem == [StemSize]byte(stem[:StemSize]) { if sn.Stem == [StemSize]byte(stem[:StemSize]) {
// Same stem — merge values // Same stem — merge values
@ -449,7 +449,7 @@ func (s *NodeStore) insertValuesAtStem(ref NodeRef, stem []byte, values [][]byte
// Different stem — split // Different stem — split
return s.splitStemValuesInsert(ref, stem, values, resolver, depth) return s.splitStemValuesInsert(ref, stem, values, resolver, depth)
case KindHashed: case kindHashed:
hn := s.getHashed(ref.Index()) hn := s.getHashed(ref.Index())
path, err := keyToPath(depth, stem) path, err := keyToPath(depth, stem)
if err != nil { if err != nil {
@ -462,14 +462,14 @@ func (s *NodeStore) insertValuesAtStem(ref NodeRef, stem []byte, values [][]byte
if err != nil { if err != nil {
return ref, fmt.Errorf("InsertValuesAtStem resolve error: %w", err) return ref, fmt.Errorf("InsertValuesAtStem resolve error: %w", err)
} }
resolved, err := s.DeserializeNodeWithHash(data, depth, hn.Hash()) resolved, err := s.deserializeNodeWithHash(data, depth, hn.Hash())
if err != nil { if err != nil {
return ref, fmt.Errorf("InsertValuesAtStem deserialization error: %w", err) return ref, fmt.Errorf("InsertValuesAtStem deserialization error: %w", err)
} }
s.freeHashedNode(ref.Index()) s.freeHashedNode(ref.Index())
return s.insertValuesAtStem(resolved, stem, values, resolver, depth) return s.insertValuesAtStem(resolved, stem, values, resolver, depth)
case KindEmpty: case kindEmpty:
// Create new StemNode // Create new StemNode
stemIdx := s.allocStem() stemIdx := s.allocStem()
sn := s.getStem(stemIdx) sn := s.getStem(stemIdx)
@ -484,7 +484,7 @@ func (s *NodeStore) insertValuesAtStem(ref NodeRef, stem []byte, values [][]byte
sn.valueData = append(sn.valueData, v[:HashSize]...) sn.valueData = append(sn.valueData, v[:HashSize]...)
} }
} }
return MakeRef(KindStem, stemIdx), nil return makeRef(kindStem, stemIdx), nil
default: default:
return ref, fmt.Errorf("insertValuesAtStem: unexpected kind %d", ref.Kind()) return ref, fmt.Errorf("insertValuesAtStem: unexpected kind %d", ref.Kind())
@ -492,7 +492,7 @@ func (s *NodeStore) insertValuesAtStem(ref NodeRef, stem []byte, values [][]byte
} }
// splitStemValuesInsert splits a StemNode when the new stem diverges. // splitStemValuesInsert splits a StemNode when the new stem diverges.
func (s *NodeStore) splitStemValuesInsert(existingRef NodeRef, newStem []byte, values [][]byte, resolver NodeResolverFn, depth int) (NodeRef, error) { func (s *NodeStore) splitStemValuesInsert(existingRef nodeRef, newStem []byte, values [][]byte, resolver NodeResolverFn, depth int) (nodeRef, error) {
existing := s.getStem(existingRef.Index()) existing := s.getStem(existingRef.Index())
if int(existing.depth) >= StemSize*8 { if int(existing.depth) >= StemSize*8 {
@ -507,7 +507,7 @@ func (s *NodeStore) splitStemValuesInsert(existingRef NodeRef, newStem []byte, v
bitKey := newStem[nNode.depth/8] >> (7 - (nNode.depth % 8)) & 1 bitKey := newStem[nNode.depth/8] >> (7 - (nNode.depth % 8)) & 1
if bitKey == bitStem { if bitKey == bitStem {
// Same direction — need deeper split // Same direction — need deeper split
var child NodeRef var child nodeRef
if bitStem == 0 { if bitStem == 0 {
nNode.left = existingRef nNode.left = existingRef
child = nNode.left child = nNode.left
@ -521,10 +521,10 @@ func (s *NodeStore) splitStemValuesInsert(existingRef NodeRef, newStem []byte, v
} }
if bitStem == 0 { if bitStem == 0 {
nNode.left = newChild nNode.left = newChild
nNode.right = EmptyRef nNode.right = emptyRef
} else { } else {
nNode.right = newChild nNode.right = newChild
nNode.left = EmptyRef nNode.left = emptyRef
} }
} else { } else {
// Divergence — create new StemNode for the new values // Divergence — create new StemNode for the new values
@ -539,7 +539,7 @@ func (s *NodeStore) splitStemValuesInsert(existingRef NodeRef, newStem []byte, v
newSn.setValue(byte(i), v) newSn.setValue(byte(i), v)
} }
} }
newStemRef := MakeRef(KindStem, newStemIdx) newStemRef := makeRef(kindStem, newStemIdx)
if bitStem == 0 { if bitStem == 0 {
nNode.left = existingRef nNode.left = existingRef
@ -560,19 +560,19 @@ func (s *NodeStore) Get(key []byte, resolver NodeResolverFn) ([]byte, error) {
return s.GetSingle(key[:StemSize], key[StemSize], resolver) return s.GetSingle(key[:StemSize], key[StemSize], resolver)
} }
func (s *NodeStore) GetHeight(ref NodeRef) int { func (s *NodeStore) getHeight(ref nodeRef) int {
switch ref.Kind() { switch ref.Kind() {
case KindInternal: case kindInternal:
node := s.getInternal(ref.Index()) node := s.getInternal(ref.Index())
lh := s.GetHeight(node.left) lh := s.getHeight(node.left)
rh := s.GetHeight(node.right) rh := s.getHeight(node.right)
if lh > rh { if lh > rh {
return 1 + lh return 1 + lh
} }
return 1 + rh return 1 + rh
case KindStem: case kindStem:
return 1 return 1
case KindEmpty: case kindEmpty:
return 0 return 0
default: default:
return 0 return 0

View file

@ -114,8 +114,8 @@ type BinaryTrie struct {
// ToDot converts the binary trie to a DOT language representation. Useful for debugging. // ToDot converts the binary trie to a DOT language representation. Useful for debugging.
func (t *BinaryTrie) ToDot() string { func (t *BinaryTrie) ToDot() string {
t.store.ComputeHash(t.store.Root()) t.store.computeHash(t.store.root)
return t.store.ToDot(t.store.Root(), "", "") return t.store.toDot(t.store.root, "", "")
} }
// NewBinaryTrie creates a new binary trie. // NewBinaryTrie creates a new binary trie.
@ -135,11 +135,11 @@ func NewBinaryTrie(root common.Hash, db database.NodeDatabase) (*BinaryTrie, err
if err != nil { if err != nil {
return nil, err return nil, err
} }
ref, err := t.store.DeserializeNodeWithHash(blob, 0, root) ref, err := t.store.deserializeNodeWithHash(blob, 0, root)
if err != nil { if err != nil {
return nil, err return nil, err
} }
t.store.SetRoot(ref) t.store.root = ref
} }
return t, nil return t, nil
} }
@ -301,7 +301,7 @@ func (t *BinaryTrie) DeleteStorage(addr common.Address, key []byte) error {
// Hash returns the root hash of the trie. It does not write to the database and // Hash returns the root hash of the trie. It does not write to the database and
// can be used even if the trie doesn't have one. // can be used even if the trie doesn't have one.
func (t *BinaryTrie) Hash() common.Hash { func (t *BinaryTrie) Hash() common.Hash {
return t.store.ComputeHash(t.store.Root()) return t.store.computeHash(t.store.root)
} }
// Commit writes all nodes to the trie's memory database, tracking the internal // Commit writes all nodes to the trie's memory database, tracking the internal
@ -309,7 +309,7 @@ func (t *BinaryTrie) Hash() common.Hash {
func (t *BinaryTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet) { func (t *BinaryTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet) {
nodeset := trienode.NewNodeSet(common.Hash{}) nodeset := trienode.NewNodeSet(common.Hash{})
err := t.store.CollectNodes(t.store.Root(), nil, func(path []byte, hash common.Hash, serialized []byte) { err := t.store.collectNodes(t.store.root, nil, func(path []byte, hash common.Hash, serialized []byte) {
nodeset.AddNode(path, trienode.NewNodeWithPrev(hash, serialized, t.tracer.Get(path))) nodeset.AddNode(path, trienode.NewNodeWithPrev(hash, serialized, t.tracer.Get(path)))
}) })
if err != nil { if err != nil {

View file

@ -41,7 +41,7 @@ func TestSingleEntry(t *testing.T) {
if err := s.Insert(zeroKey[:], oneKey[:], nil); err != nil { if err := s.Insert(zeroKey[:], oneKey[:], nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if s.GetHeight(s.Root()) != 1 { if s.getHeight(s.root) != 1 {
t.Fatal("invalid depth") t.Fatal("invalid depth")
} }
expected := common.HexToHash("aab1060e04cb4f5dc6f697ae93156a95714debbf77d54238766adc5709282b6f") expected := common.HexToHash("aab1060e04cb4f5dc6f697ae93156a95714debbf77d54238766adc5709282b6f")
@ -59,7 +59,7 @@ func TestTwoEntriesDiffFirstBit(t *testing.T) {
if err := s.Insert(common.HexToHash("8000000000000000000000000000000000000000000000000000000000000000").Bytes(), twoKey[:], nil); err != nil { if err := s.Insert(common.HexToHash("8000000000000000000000000000000000000000000000000000000000000000").Bytes(), twoKey[:], nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if s.GetHeight(s.Root()) != 2 { if s.getHeight(s.root) != 2 {
t.Fatal("invalid height") t.Fatal("invalid height")
} }
if s.Hash() != common.HexToHash("dfc69c94013a8b3c65395625a719a87534a7cfd38719251ad8c8ea7fe79f065e") { if s.Hash() != common.HexToHash("dfc69c94013a8b3c65395625a719a87534a7cfd38719251ad8c8ea7fe79f065e") {
@ -81,7 +81,7 @@ func TestOneStemColocatedValues(t *testing.T) {
if err := s.Insert(common.HexToHash("00000000000000000000000000000000000000000000000000000000000000FF").Bytes(), fourKey[:], nil); err != nil { if err := s.Insert(common.HexToHash("00000000000000000000000000000000000000000000000000000000000000FF").Bytes(), fourKey[:], nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if s.GetHeight(s.Root()) != 1 { if s.getHeight(s.root) != 1 {
t.Fatal("invalid height") t.Fatal("invalid height")
} }
} }
@ -102,7 +102,7 @@ func TestTwoStemColocatedValues(t *testing.T) {
if err := s.Insert(common.HexToHash("8000000000000000000000000000000000000000000000000000000000000004").Bytes(), twoKey[:], nil); err != nil { if err := s.Insert(common.HexToHash("8000000000000000000000000000000000000000000000000000000000000004").Bytes(), twoKey[:], nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if s.GetHeight(s.Root()) != 2 { if s.getHeight(s.root) != 2 {
t.Fatal("invalid height") t.Fatal("invalid height")
} }
} }
@ -118,7 +118,7 @@ func TestTwoKeysMatchFirst42Bits(t *testing.T) {
if err := s.Insert(key2, twoKey[:], nil); err != nil { if err := s.Insert(key2, twoKey[:], nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if s.GetHeight(s.Root()) != 1+42+1 { if s.getHeight(s.root) != 1+42+1 {
t.Fatal("invalid height") t.Fatal("invalid height")
} }
} }
@ -131,7 +131,7 @@ func TestInsertDuplicateKey(t *testing.T) {
if err := s.Insert(oneKey[:], twoKey[:], nil); err != nil { if err := s.Insert(oneKey[:], twoKey[:], nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if s.GetHeight(s.Root()) != 1 { if s.getHeight(s.root) != 1 {
t.Fatal("invalid height") t.Fatal("invalid height")
} }
// Verify that the value is updated // Verify that the value is updated
@ -153,7 +153,7 @@ func TestLargeNumberOfEntries(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
} }
height := s.GetHeight(s.Root()) height := s.getHeight(s.root)
if height != 1+8 { if height != 1+8 {
t.Fatalf("invalid height, wanted %d, got %d", 1+8, height) t.Fatalf("invalid height, wanted %d, got %d", 1+8, height)
} }
@ -631,8 +631,8 @@ func TestGetAccountNonMembershipStemRoot(t *testing.T) {
tr := testAccount(t, addr, 42, 100) tr := testAccount(t, addr, 42, 100)
// Verify root is a StemNode (single stem inserted). // Verify root is a StemNode (single stem inserted).
if tr.store.Root().Kind() != KindStem { if tr.store.root.Kind() != kindStem {
t.Fatalf("expected StemNode root, got kind %d", tr.store.Root().Kind()) t.Fatalf("expected StemNode root, got kind %d", tr.store.root.Kind())
} }
// Query a completely different address — must return nil. // Query a completely different address — must return nil.
@ -682,8 +682,8 @@ func TestGetAccountNonMembershipInternalRoot(t *testing.T) {
} }
// Verify root is an InternalNode. // Verify root is an InternalNode.
if tr.store.Root().Kind() != KindInternal { if tr.store.root.Kind() != kindInternal {
t.Fatalf("expected InternalNode root, got kind %d", tr.store.Root().Kind()) t.Fatalf("expected InternalNode root, got kind %d", tr.store.root.Kind())
} }
// Query a non-existent address — must return nil. // Query a non-existent address — must return nil.
@ -705,8 +705,8 @@ func TestGetStorageNonMembershipStemRoot(t *testing.T) {
tr := testAccount(t, addr, 1, 100) tr := testAccount(t, addr, 1, 100)
// Verify root is a StemNode. // Verify root is a StemNode.
if tr.store.Root().Kind() != KindStem { if tr.store.root.Kind() != kindStem {
t.Fatalf("expected StemNode root, got kind %d", tr.store.Root().Kind()) t.Fatalf("expected StemNode root, got kind %d", tr.store.root.Kind())
} }
// Query storage for a different address — must return nil, not panic. // Query storage for a different address — must return nil, not panic.
@ -747,8 +747,8 @@ func TestGetStorageNonMembershipInternalRoot(t *testing.T) {
t.Fatalf("UpdateStorage error: %v", err) t.Fatalf("UpdateStorage error: %v", err)
} }
if tr.store.Root().Kind() != KindInternal { if tr.store.root.Kind() != kindInternal {
t.Fatalf("expected InternalNode root, got kind %d", tr.store.Root().Kind()) t.Fatalf("expected InternalNode root, got kind %d", tr.store.root.Kind())
} }
// Query storage for a non-existent address — must return nil. // Query storage for a non-existent address — must return nil.