mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-12 01:41:36 +00:00
trie/bintrie: unexport NodeStore, NewNodeStore, NodeFlushFn, nodeResolverFn
grep across the repo confirms zero external callers of bintrie.NodeStore, NewNodeStore, NodeFlushFn, or NodeResolverFn. The arena is purely an implementation detail of BinaryTrie; unexport the top-level names so the package's external surface stays confined to BinaryTrie plus the EIP-7864 helpers (ChunkifyCode, GetBinaryTreeKey*). Methods on *nodeStore remain capitalized for now — with nodeStore itself unexported, external code has no way to hold a *nodeStore pointer, so the methods are effectively internal despite their case. Method case is a cosmetic follow-up.
This commit is contained in:
parent
f676f04706
commit
c24930bebf
13 changed files with 118 additions and 118 deletions
|
|
@ -36,9 +36,9 @@ const (
|
|||
|
||||
// DeserializeAndHash deserializes a node from bytes and returns its hash.
|
||||
// This is a convenience function for external callers that need to compute
|
||||
// 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) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
ref, err := s.deserializeNode(blob, depth)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
|
|
|
|||
|
|
@ -24,12 +24,12 @@ import (
|
|||
)
|
||||
|
||||
// TestSerializeDeserializeInternalNode tests flat 65-byte serialization and
|
||||
// deserialization of InternalNode through NodeStore.
|
||||
// deserialization of InternalNode through nodeStore.
|
||||
func TestSerializeDeserializeInternalNode(t *testing.T) {
|
||||
leftHash := common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef")
|
||||
rightHash := common.HexToHash("0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321")
|
||||
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
leftRef := s.newHashedRef(leftHash)
|
||||
rightRef := s.newHashedRef(rightHash)
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ func TestSerializeDeserializeInternalNode(t *testing.T) {
|
|||
}
|
||||
|
||||
// Deserialize into a new store
|
||||
ds := NewNodeStore()
|
||||
ds := newNodeStore()
|
||||
deserialized, err := ds.deserializeNode(serialized, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to deserialize node: %v", err)
|
||||
|
|
@ -94,7 +94,7 @@ func TestSerializeDeserializeInternalNode(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestSerializeDeserializeStemNode tests serialization and deserialization of StemNode through NodeStore.
|
||||
// TestSerializeDeserializeStemNode tests serialization and deserialization of StemNode through nodeStore.
|
||||
func TestSerializeDeserializeStemNode(t *testing.T) {
|
||||
stem := make([]byte, StemSize)
|
||||
for i := range stem {
|
||||
|
|
@ -106,7 +106,7 @@ func TestSerializeDeserializeStemNode(t *testing.T) {
|
|||
values[10] = common.HexToHash("0x0202020202020202020202020202020202020202020202020202020202020202").Bytes()
|
||||
values[255] = common.HexToHash("0x0303030303030303030303030303030303030303030303030303030303030303").Bytes()
|
||||
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
ref := s.newStemRef(stem, 10)
|
||||
sn := s.getStem(ref.Index())
|
||||
for i, v := range values {
|
||||
|
|
@ -129,7 +129,7 @@ func TestSerializeDeserializeStemNode(t *testing.T) {
|
|||
}
|
||||
|
||||
// Deserialize into a new store
|
||||
ds := NewNodeStore()
|
||||
ds := newNodeStore()
|
||||
deserializedRef, err := ds.deserializeNode(serialized, 10)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to deserialize node: %v", err)
|
||||
|
|
@ -170,7 +170,7 @@ func TestSerializeDeserializeStemNode(t *testing.T) {
|
|||
|
||||
// TestDeserializeEmptyNode tests deserialization of empty node.
|
||||
func TestDeserializeEmptyNode(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
deserialized, err := s.deserializeNode([]byte{}, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to deserialize empty node: %v", err)
|
||||
|
|
@ -183,7 +183,7 @@ func TestDeserializeEmptyNode(t *testing.T) {
|
|||
|
||||
// TestDeserializeInvalidType tests deserialization with invalid type byte.
|
||||
func TestDeserializeInvalidType(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
invalidData := []byte{99, 0, 0, 0} // Type byte 99 is invalid
|
||||
|
||||
_, err := s.deserializeNode(invalidData, 0)
|
||||
|
|
@ -194,7 +194,7 @@ func TestDeserializeInvalidType(t *testing.T) {
|
|||
|
||||
// TestDeserializeInvalidLength tests deserialization with invalid data length.
|
||||
func TestDeserializeInvalidLength(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
// InternalNode with valid type byte but wrong length (needs exactly 65 bytes)
|
||||
invalidData := []byte{nodeTypeInternal, 0, 0, 0}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// TestHashedNodeHash tests the Hash method via NodeStore.
|
||||
// TestHashedNodeHash tests the Hash method via nodeStore.
|
||||
func TestHashedNodeHash(t *testing.T) {
|
||||
hash := common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef")
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
ref := s.newHashedRef(hash)
|
||||
|
||||
if s.computeHash(ref) != hash {
|
||||
|
|
@ -35,10 +35,10 @@ func TestHashedNodeHash(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestHashedNodeCopy tests the Copy method via NodeStore.
|
||||
// TestHashedNodeCopy tests the Copy method via nodeStore.
|
||||
func TestHashedNodeCopy(t *testing.T) {
|
||||
hash := common.HexToHash("0xabcdef")
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
ref := s.newHashedRef(hash)
|
||||
s.root = ref
|
||||
|
||||
|
|
@ -50,10 +50,10 @@ func TestHashedNodeCopy(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestHashedNodeInsertValuesAtStem tests InsertValuesAtStem resolution via NodeStore.
|
||||
// TestHashedNodeInsertValuesAtStem tests InsertValuesAtStem resolution via nodeStore.
|
||||
func TestHashedNodeInsertValuesAtStem(t *testing.T) {
|
||||
// Test 1: nil resolver should return an error
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
hashedRef := s.newHashedRef(common.HexToHash("0x1234"))
|
||||
s.root = hashedRef
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ func TestHashedNodeInsertValuesAtStem(t *testing.T) {
|
|||
return []byte{0xff, 0xff, 0xff}, nil
|
||||
}
|
||||
|
||||
s2 := NewNodeStore()
|
||||
s2 := newNodeStore()
|
||||
hashedRef2 := s2.newHashedRef(common.HexToHash("0x1234"))
|
||||
s2.root = hashedRef2
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ func TestHashedNodeInsertValuesAtStem(t *testing.T) {
|
|||
originalValues[1] = common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222").Bytes()
|
||||
|
||||
// Build the serialized node
|
||||
rs := NewNodeStore()
|
||||
rs := newNodeStore()
|
||||
ref := rs.newStemRef(stem, 0)
|
||||
sn := rs.getStem(ref.Index())
|
||||
for i, v := range originalValues {
|
||||
|
|
@ -101,7 +101,7 @@ func TestHashedNodeInsertValuesAtStem(t *testing.T) {
|
|||
return serialized, nil
|
||||
}
|
||||
|
||||
s3 := NewNodeStore()
|
||||
s3 := newNodeStore()
|
||||
hashedRef3 := s3.newHashedRef(common.HexToHash("0x1234"))
|
||||
s3.root = hashedRef3
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ func TestHashedNodeInsertValuesAtStem(t *testing.T) {
|
|||
|
||||
// TestHashedNodeGetError tests that getting through an unresolved HashedNode root returns error.
|
||||
func TestHashedNodeGetError(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
// Create root as hashed, then try to resolve through InternalNode parent
|
||||
rootRef := s.newInternalRef(0)
|
||||
rootNode := s.getInternal(rootRef.Index())
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// TestInternalNodeGet tests the Get method via NodeStore.
|
||||
// TestInternalNodeGet tests the Get method via nodeStore.
|
||||
func TestInternalNodeGet(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
leftStem := make([]byte, 31)
|
||||
rightStem := make([]byte, 31)
|
||||
|
|
@ -71,10 +71,10 @@ func TestInternalNodeGet(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestInternalNodeGetWithResolver tests Get with HashedNode resolution via NodeStore.
|
||||
// TestInternalNodeGetWithResolver tests Get with HashedNode resolution via nodeStore.
|
||||
func TestInternalNodeGetWithResolver(t *testing.T) {
|
||||
// Create a store with an internal node containing a hashed child
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
hashedChild := s.newHashedRef(common.HexToHash("0x1234"))
|
||||
rootRef := s.newInternalRef(0)
|
||||
rootNode := s.getInternal(rootRef.Index())
|
||||
|
|
@ -85,7 +85,7 @@ func TestInternalNodeGetWithResolver(t *testing.T) {
|
|||
// Mock resolver that returns a stem node
|
||||
resolver := func(path []byte, hash common.Hash) ([]byte, error) {
|
||||
if hash == common.HexToHash("0x1234") {
|
||||
rs := NewNodeStore()
|
||||
rs := newNodeStore()
|
||||
stem := make([]byte, 31)
|
||||
ref := rs.newStemRef(stem, 1)
|
||||
sn := rs.getStem(ref.Index())
|
||||
|
|
@ -109,9 +109,9 @@ func TestInternalNodeGetWithResolver(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestInternalNodeInsert tests the Insert method via NodeStore.
|
||||
// TestInternalNodeInsert tests the Insert method via nodeStore.
|
||||
func TestInternalNodeInsert(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
leftKey := make([]byte, 32)
|
||||
leftKey[31] = 10
|
||||
|
|
@ -131,9 +131,9 @@ func TestInternalNodeInsert(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestInternalNodeCopy tests the Copy method via NodeStore.
|
||||
// TestInternalNodeCopy tests the Copy method via nodeStore.
|
||||
func TestInternalNodeCopy(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
leftKey := make([]byte, 32)
|
||||
leftKey[31] = 0
|
||||
|
|
@ -164,9 +164,9 @@ func TestInternalNodeCopy(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestInternalNodeHash tests the Hash method via NodeStore.
|
||||
// TestInternalNodeHash tests the Hash method via nodeStore.
|
||||
func TestInternalNodeHash(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
leftRef := s.newHashedRef(common.HexToHash("0x1111"))
|
||||
rightRef := s.newHashedRef(common.HexToHash("0x2222"))
|
||||
rootRef := s.newInternalRef(0)
|
||||
|
|
@ -192,9 +192,9 @@ func TestInternalNodeHash(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestInternalNodeGetValuesAtStem tests GetValuesAtStem method via NodeStore.
|
||||
// TestInternalNodeGetValuesAtStem tests GetValuesAtStem method via nodeStore.
|
||||
func TestInternalNodeGetValuesAtStem(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
leftStem := make([]byte, 31)
|
||||
rightStem := make([]byte, 31)
|
||||
|
|
@ -239,9 +239,9 @@ func TestInternalNodeGetValuesAtStem(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestInternalNodeInsertValuesAtStem tests InsertValuesAtStem method via NodeStore.
|
||||
// TestInternalNodeInsertValuesAtStem tests InsertValuesAtStem method via nodeStore.
|
||||
func TestInternalNodeInsertValuesAtStem(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
stem := make([]byte, 31)
|
||||
values := make([][]byte, 256)
|
||||
|
|
@ -265,9 +265,9 @@ func TestInternalNodeInsertValuesAtStem(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestInternalNodeCollectNodes tests CollectNodes method via NodeStore.
|
||||
// TestInternalNodeCollectNodes tests CollectNodes method via nodeStore.
|
||||
func TestInternalNodeCollectNodes(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
leftStem := make([]byte, 31)
|
||||
rightStem := make([]byte, 31)
|
||||
|
|
@ -301,9 +301,9 @@ func TestInternalNodeCollectNodes(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestInternalNodeGetHeight tests GetHeight method via NodeStore.
|
||||
// TestInternalNodeGetHeight tests GetHeight method via nodeStore.
|
||||
func TestInternalNodeGetHeight(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
// Insert values that create a deeper tree
|
||||
stem1 := make([]byte, 31) // left
|
||||
|
|
@ -328,9 +328,9 @@ func TestInternalNodeGetHeight(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestInternalNodeDepthTooLarge tests handling of excessive depth via NodeStore.
|
||||
// TestInternalNodeDepthTooLarge tests handling of excessive depth via nodeStore.
|
||||
func TestInternalNodeDepthTooLarge(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
// Creating an internal node beyond max depth should panic
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ type binaryNodeIteratorState struct {
|
|||
|
||||
type binaryNodeIterator struct {
|
||||
trie *BinaryTrie
|
||||
store *NodeStore
|
||||
store *nodeStore
|
||||
current nodeRef
|
||||
lastErr error
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import (
|
|||
// makeTrie creates a BinaryTrie populated with the given key-value pairs.
|
||||
func makeTrie(t *testing.T, entries [][2]common.Hash) *BinaryTrie {
|
||||
t.Helper()
|
||||
store := NewNodeStore()
|
||||
store := newNodeStore()
|
||||
tr := &BinaryTrie{
|
||||
store: store,
|
||||
tracer: trie.NewPrevalueTracer(),
|
||||
|
|
@ -63,7 +63,7 @@ func countLeaves(t *testing.T, tr *BinaryTrie) int {
|
|||
// no nodes and reports no error.
|
||||
func TestIteratorEmptyTrie(t *testing.T) {
|
||||
tr := &BinaryTrie{
|
||||
store: NewNodeStore(),
|
||||
store: newNodeStore(),
|
||||
tracer: trie.NewPrevalueTracer(),
|
||||
}
|
||||
it, err := newBinaryNodeIterator(tr, nil)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const (
|
|||
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)
|
||||
// into a single uint32. Because nodeRef contains no Go pointers, slices
|
||||
// of structs containing nodeRef fields are allocated in noscan spans —
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ import "github.com/ethereum/go-ethereum/common"
|
|||
// storeChunkSize is the number of nodes per chunk in each typed pool.
|
||||
const storeChunkSize = 4096
|
||||
|
||||
// NodeStore is a GC-friendly arena for binary trie nodes. Nodes are packed
|
||||
// nodeStore is a GC-friendly arena for binary trie nodes. Nodes are packed
|
||||
// into typed chunked pools so pointer-free types (InternalNode, HashedNode)
|
||||
// land in noscan spans the GC skips entirely.
|
||||
type NodeStore struct {
|
||||
type nodeStore struct {
|
||||
internalChunks []*[storeChunkSize]InternalNode
|
||||
internalCount uint32
|
||||
|
||||
|
|
@ -43,11 +43,11 @@ type NodeStore struct {
|
|||
freeHashed []uint32
|
||||
}
|
||||
|
||||
func NewNodeStore() *NodeStore {
|
||||
return &NodeStore{root: emptyRef}
|
||||
func newNodeStore() *nodeStore {
|
||||
return &nodeStore{root: emptyRef}
|
||||
}
|
||||
|
||||
func (s *NodeStore) allocInternal() uint32 {
|
||||
func (s *nodeStore) allocInternal() uint32 {
|
||||
idx := s.internalCount
|
||||
chunkIdx := idx / storeChunkSize
|
||||
if uint32(len(s.internalChunks)) <= chunkIdx {
|
||||
|
|
@ -60,11 +60,11 @@ func (s *NodeStore) allocInternal() uint32 {
|
|||
return idx
|
||||
}
|
||||
|
||||
func (s *NodeStore) getInternal(idx uint32) *InternalNode {
|
||||
func (s *nodeStore) getInternal(idx uint32) *InternalNode {
|
||||
return &s.internalChunks[idx/storeChunkSize][idx%storeChunkSize]
|
||||
}
|
||||
|
||||
func (s *NodeStore) newInternalRef(depth int) nodeRef {
|
||||
func (s *nodeStore) newInternalRef(depth int) nodeRef {
|
||||
if depth > 248 {
|
||||
panic("node depth exceeds maximum binary trie depth")
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ func (s *NodeStore) newInternalRef(depth int) nodeRef {
|
|||
return makeRef(kindInternal, idx)
|
||||
}
|
||||
|
||||
func (s *NodeStore) allocStem() uint32 {
|
||||
func (s *nodeStore) allocStem() uint32 {
|
||||
idx := s.stemCount
|
||||
chunkIdx := idx / storeChunkSize
|
||||
if uint32(len(s.stemChunks)) <= chunkIdx {
|
||||
|
|
@ -89,11 +89,11 @@ func (s *NodeStore) allocStem() uint32 {
|
|||
return idx
|
||||
}
|
||||
|
||||
func (s *NodeStore) getStem(idx uint32) *StemNode {
|
||||
func (s *nodeStore) getStem(idx uint32) *StemNode {
|
||||
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 {
|
||||
panic("node depth exceeds maximum binary trie depth")
|
||||
}
|
||||
|
|
@ -106,7 +106,7 @@ func (s *NodeStore) newStemRef(stem []byte, depth int) nodeRef {
|
|||
return makeRef(kindStem, idx)
|
||||
}
|
||||
|
||||
func (s *NodeStore) allocHashed() uint32 {
|
||||
func (s *nodeStore) allocHashed() uint32 {
|
||||
if n := len(s.freeHashed); n > 0 {
|
||||
idx := s.freeHashed[n-1]
|
||||
s.freeHashed = s.freeHashed[:n-1]
|
||||
|
|
@ -125,22 +125,22 @@ func (s *NodeStore) allocHashed() uint32 {
|
|||
return idx
|
||||
}
|
||||
|
||||
func (s *NodeStore) getHashed(idx uint32) *HashedNode {
|
||||
func (s *nodeStore) getHashed(idx uint32) *HashedNode {
|
||||
return &s.hashedChunks[idx/storeChunkSize][idx%storeChunkSize]
|
||||
}
|
||||
|
||||
func (s *NodeStore) freeHashedNode(idx uint32) {
|
||||
func (s *nodeStore) freeHashedNode(idx uint32) {
|
||||
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()
|
||||
*s.getHashed(idx) = HashedNode(hash)
|
||||
return makeRef(kindHashed, idx)
|
||||
}
|
||||
|
||||
func (s *NodeStore) Copy() *NodeStore {
|
||||
ns := &NodeStore{
|
||||
func (s *nodeStore) Copy() *nodeStore {
|
||||
ns := &nodeStore{
|
||||
root: s.root,
|
||||
internalCount: s.internalCount,
|
||||
stemCount: s.stemCount,
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// TestStemNodeInsertSameStem tests inserting values with the same stem via NodeStore.
|
||||
// TestStemNodeInsertSameStem tests inserting values with the same stem via nodeStore.
|
||||
func TestStemNodeInsertSameStem(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
stem := make([]byte, 31)
|
||||
for i := range stem {
|
||||
|
|
@ -66,9 +66,9 @@ func TestStemNodeInsertSameStem(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestStemNodeInsertDifferentStem tests inserting values with different stems via NodeStore.
|
||||
// TestStemNodeInsertDifferentStem tests inserting values with different stems via nodeStore.
|
||||
func TestStemNodeInsertDifferentStem(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
// Insert first value with stem of all zeros
|
||||
key1 := make([]byte, 32)
|
||||
|
|
@ -108,9 +108,9 @@ func TestStemNodeInsertDifferentStem(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestStemNodeInsertInvalidValueLength tests inserting value with invalid length via NodeStore.
|
||||
// TestStemNodeInsertInvalidValueLength tests inserting value with invalid length via nodeStore.
|
||||
func TestStemNodeInsertInvalidValueLength(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
key := make([]byte, 32)
|
||||
invalidValue := []byte{1, 2, 3} // Not 32 bytes
|
||||
|
|
@ -125,9 +125,9 @@ func TestStemNodeInsertInvalidValueLength(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestStemNodeCopy tests the Copy method via NodeStore.
|
||||
// TestStemNodeCopy tests the Copy method via nodeStore.
|
||||
func TestStemNodeCopy(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
key1 := make([]byte, 32)
|
||||
for i := range 31 {
|
||||
|
|
@ -163,7 +163,7 @@ func TestStemNodeCopy(t *testing.T) {
|
|||
|
||||
// TestStemNodeHash tests the Hash method.
|
||||
func TestStemNodeHash(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
key := make([]byte, 32)
|
||||
key[31] = 0
|
||||
|
|
@ -193,9 +193,9 @@ func TestStemNodeHash(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestStemNodeGetValuesAtStem tests GetValuesAtStem method via NodeStore.
|
||||
// TestStemNodeGetValuesAtStem tests GetValuesAtStem method via nodeStore.
|
||||
func TestStemNodeGetValuesAtStem(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
stem := make([]byte, 31)
|
||||
for i := range stem {
|
||||
|
|
@ -248,9 +248,9 @@ func TestStemNodeGetValuesAtStem(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestStemNodeInsertValuesAtStem tests InsertValuesAtStem method via NodeStore.
|
||||
// TestStemNodeInsertValuesAtStem tests InsertValuesAtStem method via nodeStore.
|
||||
func TestStemNodeInsertValuesAtStem(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
stem := make([]byte, 31)
|
||||
values := make([][]byte, 256)
|
||||
|
|
@ -285,9 +285,9 @@ func TestStemNodeInsertValuesAtStem(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestStemNodeGetHeight tests GetHeight method via NodeStore.
|
||||
// TestStemNodeGetHeight tests GetHeight method via nodeStore.
|
||||
func TestStemNodeGetHeight(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
key := make([]byte, 32)
|
||||
value := common.HexToHash("0x01").Bytes()
|
||||
|
|
@ -301,9 +301,9 @@ func TestStemNodeGetHeight(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestStemNodeCollectNodes tests CollectNodes method via NodeStore.
|
||||
// TestStemNodeCollectNodes tests CollectNodes method via nodeStore.
|
||||
func TestStemNodeCollectNodes(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
|
||||
stem := make([]byte, 31)
|
||||
values := make([][]byte, 256)
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func (s *NodeStore) computeHash(ref nodeRef) common.Hash {
|
||||
func (s *nodeStore) computeHash(ref nodeRef) common.Hash {
|
||||
switch ref.Kind() {
|
||||
case kindInternal:
|
||||
return s.hashInternal(ref.Index())
|
||||
|
|
@ -59,7 +59,7 @@ var parallelHashDepth = min(bits.Len(uint(runtime.NumCPU())), 8)
|
|||
// goroutine while the right subtree is hashed inline, then the two digests
|
||||
// are combined. Below that threshold the goroutine spawn cost outweighs the
|
||||
// hashing work, so deeper nodes hash both children sequentially.
|
||||
func (s *NodeStore) hashInternal(idx uint32) common.Hash {
|
||||
func (s *nodeStore) hashInternal(idx uint32) common.Hash {
|
||||
node := s.getInternal(idx)
|
||||
if !node.mustRecompute {
|
||||
return node.hash
|
||||
|
|
@ -108,7 +108,7 @@ func (s *NodeStore) hashInternal(idx uint32) common.Hash {
|
|||
}
|
||||
|
||||
// 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() {
|
||||
case kindInternal:
|
||||
node := s.getInternal(ref.Index())
|
||||
|
|
@ -153,17 +153,17 @@ var errInvalidSerializedLength = errors.New("invalid serialized node length")
|
|||
|
||||
// DeserializeNode deserializes a node from bytes, recomputing its hash. The
|
||||
// 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.decodeNode(serialized, depth, common.Hash{}, true, true)
|
||||
}
|
||||
|
||||
// DeserializeNodeWithHash deserializes a node whose hash is already known and
|
||||
// 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.decodeNode(serialized, depth, hn, false, false)
|
||||
}
|
||||
|
||||
func (s *NodeStore) decodeNode(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 {
|
||||
return emptyRef, nil
|
||||
}
|
||||
|
|
@ -230,7 +230,7 @@ func (s *NodeStore) decodeNode(serialized []byte, depth int, hn common.Hash, mus
|
|||
// 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
|
||||
// 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() {
|
||||
case kindEmpty:
|
||||
return nil
|
||||
|
|
@ -269,7 +269,7 @@ func (s *NodeStore) collectNodes(ref nodeRef, path []byte, flushfn NodeFlushFn)
|
|||
}
|
||||
}
|
||||
|
||||
func (s *NodeStore) toDot(ref nodeRef, parent, path string) string {
|
||||
func (s *nodeStore) toDot(ref nodeRef, parent, path string) string {
|
||||
switch ref.Kind() {
|
||||
case kindInternal:
|
||||
node := s.getInternal(ref.Index())
|
||||
|
|
|
|||
|
|
@ -23,14 +23,14 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// NodeResolverFn resolves a hashed node from the database.
|
||||
type NodeResolverFn func([]byte, common.Hash) ([]byte, error)
|
||||
// nodeResolverFn resolves a hashed node from the database.
|
||||
type nodeResolverFn func([]byte, common.Hash) ([]byte, error)
|
||||
|
||||
// GetValue returns the value at (stem, suffix) or nil if absent. Thin
|
||||
// wrapper over GetValuesAtStem — the underlying StemNode returns its
|
||||
// 256-slot array as a slice header (no allocation), so the per-call cost
|
||||
// is the tree walk plus one index.
|
||||
func (s *NodeStore) GetValue(stem []byte, suffix byte, resolver NodeResolverFn) ([]byte, error) {
|
||||
func (s *nodeStore) GetValue(stem []byte, suffix byte, resolver nodeResolverFn) ([]byte, error) {
|
||||
values, err := s.GetValuesAtStem(stem, resolver)
|
||||
if err != nil || values == nil {
|
||||
return nil, err
|
||||
|
|
@ -41,7 +41,7 @@ func (s *NodeStore) GetValue(stem []byte, suffix byte, resolver NodeResolverFn)
|
|||
// GetValuesAtStem returns the 256 value slots at stem, or nil if the stem
|
||||
// is not in the trie. The returned slice is a view over the in-place
|
||||
// StemNode values array (no allocation) and must be treated read-only.
|
||||
func (s *NodeStore) GetValuesAtStem(stem []byte, resolver NodeResolverFn) ([][]byte, error) {
|
||||
func (s *nodeStore) GetValuesAtStem(stem []byte, resolver nodeResolverFn) ([][]byte, error) {
|
||||
cur := s.root
|
||||
var parentIdx uint32
|
||||
var parentIsLeft bool
|
||||
|
|
@ -115,7 +115,7 @@ func (s *NodeStore) GetValuesAtStem(stem []byte, resolver NodeResolverFn) ([][]b
|
|||
// gballet referenced (comment 3101751325): one primary insert path; the
|
||||
// single-slot variant dispatches through it so the split / resolve logic
|
||||
// lives in one place.
|
||||
func (s *NodeStore) InsertSingle(stem []byte, suffix byte, value []byte, resolver NodeResolverFn) error {
|
||||
func (s *nodeStore) InsertSingle(stem []byte, suffix byte, value []byte, resolver nodeResolverFn) error {
|
||||
if len(value) != HashSize {
|
||||
return errors.New("invalid insertion: value length")
|
||||
}
|
||||
|
|
@ -128,13 +128,13 @@ func (s *NodeStore) InsertSingle(stem []byte, suffix byte, value []byte, resolve
|
|||
// sparse (nil entries are ignored). The recursive implementation dispatches
|
||||
// through the same body, so a single code path handles internal descent,
|
||||
// HashedNode resolution, stem merge, and stem split.
|
||||
func (s *NodeStore) InsertValuesAtStem(stem []byte, values [][]byte, resolver NodeResolverFn) error {
|
||||
func (s *nodeStore) InsertValuesAtStem(stem []byte, values [][]byte, resolver nodeResolverFn) error {
|
||||
var err error
|
||||
s.root, err = s.insertValuesAtStem(s.root, stem, values, resolver, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
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() {
|
||||
case kindInternal:
|
||||
node := s.getInternal(ref.Index())
|
||||
|
|
@ -252,7 +252,7 @@ func (s *NodeStore) insertValuesAtStem(ref nodeRef, stem []byte, values [][]byte
|
|||
}
|
||||
|
||||
// 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())
|
||||
|
||||
if int(existing.depth) >= StemSize*8 {
|
||||
|
|
@ -317,15 +317,15 @@ func (s *NodeStore) splitStemValuesInsert(existingRef nodeRef, newStem []byte, v
|
|||
return nRef, nil
|
||||
}
|
||||
|
||||
func (s *NodeStore) Insert(key []byte, value []byte, resolver NodeResolverFn) error {
|
||||
func (s *nodeStore) Insert(key []byte, value []byte, resolver nodeResolverFn) error {
|
||||
return s.InsertSingle(key[:StemSize], key[StemSize], value, resolver)
|
||||
}
|
||||
|
||||
func (s *NodeStore) Get(key []byte, resolver NodeResolverFn) ([]byte, error) {
|
||||
func (s *nodeStore) Get(key []byte, resolver nodeResolverFn) ([]byte, error) {
|
||||
return s.GetValue(key[:StemSize], key[StemSize], resolver)
|
||||
}
|
||||
|
||||
func (s *NodeStore) getHeight(ref nodeRef) int {
|
||||
func (s *nodeStore) getHeight(ref nodeRef) int {
|
||||
switch ref.Kind() {
|
||||
case kindInternal:
|
||||
node := s.getInternal(ref.Index())
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ func ChunkifyCode(code []byte) ChunkedCode {
|
|||
|
||||
// BinaryTrie is the implementation of https://eips.ethereum.org/EIPS/eip-7864.
|
||||
type BinaryTrie struct {
|
||||
store *NodeStore
|
||||
store *nodeStore
|
||||
reader *trie.Reader
|
||||
tracer *trie.PrevalueTracer
|
||||
}
|
||||
|
|
@ -125,7 +125,7 @@ func NewBinaryTrie(root common.Hash, db database.NodeDatabase) (*BinaryTrie, err
|
|||
return nil, err
|
||||
}
|
||||
t := &BinaryTrie{
|
||||
store: NewNodeStore(),
|
||||
store: newNodeStore(),
|
||||
reader: reader,
|
||||
tracer: trie.NewPrevalueTracer(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ var (
|
|||
)
|
||||
|
||||
func TestSingleEntry(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
if err := s.Insert(zeroKey[:], oneKey[:], nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ func TestSingleEntry(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTwoEntriesDiffFirstBit(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
if err := s.Insert(zeroKey[:], oneKey[:], nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ func TestTwoEntriesDiffFirstBit(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestOneStemColocatedValues(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
if err := s.Insert(common.HexToHash("0000000000000000000000000000000000000000000000000000000000000003").Bytes(), oneKey[:], nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ func TestOneStemColocatedValues(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTwoStemColocatedValues(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
// stem: 0...0
|
||||
if err := s.Insert(common.HexToHash("0000000000000000000000000000000000000000000000000000000000000003").Bytes(), oneKey[:], nil); err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -108,7 +108,7 @@ func TestTwoStemColocatedValues(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTwoKeysMatchFirst42Bits(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
// key1 and key 2 have the same prefix of 42 bits (b0*42+b1+b1) and differ after.
|
||||
key1 := common.HexToHash("0000000000C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0").Bytes()
|
||||
key2 := common.HexToHash("0000000000E00000000000000000000000000000000000000000000000000000").Bytes()
|
||||
|
|
@ -124,7 +124,7 @@ func TestTwoKeysMatchFirst42Bits(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestInsertDuplicateKey(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
if err := s.Insert(oneKey[:], oneKey[:], nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -145,7 +145,7 @@ func TestInsertDuplicateKey(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestLargeNumberOfEntries(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
for i := range StemNodeWidth {
|
||||
var key [HashSize]byte
|
||||
key[0] = byte(i)
|
||||
|
|
@ -160,7 +160,7 @@ func TestLargeNumberOfEntries(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMerkleizeMultipleEntries(t *testing.T) {
|
||||
s := NewNodeStore()
|
||||
s := newNodeStore()
|
||||
keys := [][]byte{
|
||||
zeroKey[:],
|
||||
common.HexToHash("8000000000000000000000000000000000000000000000000000000000000000").Bytes(),
|
||||
|
|
@ -188,7 +188,7 @@ func TestMerkleizeMultipleEntries(t *testing.T) {
|
|||
func TestStorageRoundTrip(t *testing.T) {
|
||||
tracer := trie.NewPrevalueTracer()
|
||||
tr := &BinaryTrie{
|
||||
store: NewNodeStore(),
|
||||
store: newNodeStore(),
|
||||
tracer: tracer,
|
||||
}
|
||||
addr := common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678")
|
||||
|
|
@ -256,7 +256,7 @@ func TestStorageRoundTrip(t *testing.T) {
|
|||
func newEmptyTestTrie(t *testing.T) *BinaryTrie {
|
||||
t.Helper()
|
||||
return &BinaryTrie{
|
||||
store: NewNodeStore(),
|
||||
store: newNodeStore(),
|
||||
tracer: trie.NewPrevalueTracer(),
|
||||
}
|
||||
}
|
||||
|
|
@ -581,7 +581,7 @@ func TestBinaryTrieWitness(t *testing.T) {
|
|||
tracer := trie.NewPrevalueTracer()
|
||||
|
||||
tr := &BinaryTrie{
|
||||
store: NewNodeStore(),
|
||||
store: newNodeStore(),
|
||||
tracer: tracer,
|
||||
}
|
||||
if w := tr.Witness(); len(w) != 0 {
|
||||
|
|
@ -608,7 +608,7 @@ func TestBinaryTrieWitness(t *testing.T) {
|
|||
func testAccount(t *testing.T, addr common.Address, nonce uint64, balance uint64) *BinaryTrie {
|
||||
t.Helper()
|
||||
tr := &BinaryTrie{
|
||||
store: NewNodeStore(),
|
||||
store: newNodeStore(),
|
||||
tracer: trie.NewPrevalueTracer(),
|
||||
}
|
||||
acc := &types.StateAccount{
|
||||
|
|
@ -662,7 +662,7 @@ func TestGetAccountNonMembershipStemRoot(t *testing.T) {
|
|||
// address returns nil when the trie root is an InternalNode (multi-account trie).
|
||||
func TestGetAccountNonMembershipInternalRoot(t *testing.T) {
|
||||
tr := &BinaryTrie{
|
||||
store: NewNodeStore(),
|
||||
store: newNodeStore(),
|
||||
tracer: trie.NewPrevalueTracer(),
|
||||
}
|
||||
|
||||
|
|
@ -725,7 +725,7 @@ func TestGetStorageNonMembershipStemRoot(t *testing.T) {
|
|||
// non-existent address returns nil when the root is an InternalNode.
|
||||
func TestGetStorageNonMembershipInternalRoot(t *testing.T) {
|
||||
tr := &BinaryTrie{
|
||||
store: NewNodeStore(),
|
||||
store: newNodeStore(),
|
||||
tracer: trie.NewPrevalueTracer(),
|
||||
}
|
||||
|
||||
|
|
@ -768,7 +768,7 @@ func TestGetStorageNonMembershipInternalRoot(t *testing.T) {
|
|||
// flushes only the root-to-leaf path.
|
||||
func TestCommitSkipCleanSubtrees(t *testing.T) {
|
||||
tr := &BinaryTrie{
|
||||
store: NewNodeStore(),
|
||||
store: newNodeStore(),
|
||||
tracer: trie.NewPrevalueTracer(),
|
||||
}
|
||||
const n = 200
|
||||
|
|
@ -826,7 +826,7 @@ func TestCommitSkipCleanSubtrees(t *testing.T) {
|
|||
func BenchmarkCollectNodesSparseWrite(b *testing.B) {
|
||||
const n = 10_000
|
||||
tr := &BinaryTrie{
|
||||
store: NewNodeStore(),
|
||||
store: newNodeStore(),
|
||||
tracer: trie.NewPrevalueTracer(),
|
||||
}
|
||||
keys := make([][HashSize]byte, n)
|
||||
|
|
|
|||
Loading…
Reference in a new issue