From a764b364496a729937c2492e06c2b895e8fefad0 Mon Sep 17 00:00:00 2001 From: Guillaume Ballet <3272758+gballet@users.noreply.github.com> Date: Thu, 11 Jun 2026 13:45:23 +0200 Subject: [PATCH] drop bintrie support for now --- trie/bintrie/expired_node.go | 176 ------------------- trie/bintrie/expired_node_test.go | 277 ------------------------------ 2 files changed, 453 deletions(-) delete mode 100644 trie/bintrie/expired_node.go delete mode 100644 trie/bintrie/expired_node_test.go diff --git a/trie/bintrie/expired_node.go b/trie/bintrie/expired_node.go deleted file mode 100644 index d3b90ee9ea..0000000000 --- a/trie/bintrie/expired_node.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2026 go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package bintrie - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/trie/archive" -) - -// expiredNode represents a node whose data has been archived. -// It stores the file offset and size of the archived subtree data. -type expiredNode struct { - Offset uint64 - Size uint64 - depth int - archiveResolver archive.ResolverFn -} - -func archiveRecordsToNode(records []*archive.Record, depth int) (BinaryNode, error) { - if len(records) == 0 { - return nil, archive.EmptyArchiveRecord - } - if len(records) == 1 { - return DeserializeNode(records[0].Value, depth) - } - - var ( - newnode InternalNode - curnode *InternalNode - ) - for _, record := range records { - curnode = &newnode - resolved, err := DeserializeNode(record.Value, depth) - if err != nil { - return nil, err - } - // It's not needed to resurrect all nodes, nodes - // not along the path of what has been asked can - // be updated as expired. This is for v2. - for i, b := range record.Path { - var child BinaryNode - if b == 0 { - child = curnode.left - } else { - child = curnode.right - } - if child == nil { - if i < len(record.Path)-1 { - child = &InternalNode{depth: depth} - } else { - // Not good, I need to update the pointer - child = resolved - } - } - depth++ - } - } - return &newnode, nil -} - -func (n *expiredNode) Get(key []byte, resolver NodeResolverFn) ([]byte, error) { - if n.archiveResolver == nil { - return nil, archive.ErrNoResolver - } - records, err := n.archiveResolver(n.Offset, n.Size) - if err != nil { - return nil, fmt.Errorf("failed to resolve expired node: %w", err) - } - - resolved, err := archiveRecordsToNode(records, n.depth) - if err != nil { - return nil, fmt.Errorf("failed to deserialize expired node: %w", err) - } - return resolved.Get(key, resolver) -} - -func (n *expiredNode) Insert(key, value []byte, resolver NodeResolverFn, depth int) (BinaryNode, error) { - if n.archiveResolver == nil { - return nil, archive.ErrNoResolver - } - blob, err := n.archiveResolver(n.Offset, n.Size) - if err != nil { - return nil, fmt.Errorf("failed to resolve expired node: %w", err) - } - resolved, err := archiveRecordsToNode(blob, n.depth) - if err != nil { - return nil, fmt.Errorf("failed to deserialize expired node: %w", err) - } - return resolved.Insert(key, value, resolver, depth) -} - -func (n *expiredNode) Copy() BinaryNode { - return &expiredNode{ - Offset: n.Offset, - Size: n.Size, - depth: n.depth, - archiveResolver: n.archiveResolver, - } -} - -func (n *expiredNode) Hash() common.Hash { - return common.Hash{} -} - -func (n *expiredNode) GetValuesAtStem(stem []byte, resolver NodeResolverFn) ([][]byte, error) { - if n.archiveResolver == nil { - return nil, archive.ErrNoResolver - } - blob, err := n.archiveResolver(n.Offset, n.Size) - if err != nil { - return nil, fmt.Errorf("failed to resolve expired node: %w", err) - } - resolved, err := archiveRecordsToNode(blob, n.depth) - if err != nil { - return nil, fmt.Errorf("failed to deserialize expired node: %w", err) - } - return resolved.GetValuesAtStem(stem, resolver) -} - -func (n *expiredNode) InsertValuesAtStem(stem []byte, values [][]byte, resolver NodeResolverFn, depth int) (BinaryNode, error) { - if n.archiveResolver == nil { - return nil, archive.ErrNoResolver - } - blob, err := n.archiveResolver(n.Offset, n.Size) - if err != nil { - return nil, fmt.Errorf("failed to resolve expired node: %w", err) - } - resolved, err := archiveRecordsToNode(blob, n.depth) - if err != nil { - return nil, fmt.Errorf("failed to deserialize expired node: %w", err) - } - return resolved.InsertValuesAtStem(stem, values, resolver, depth) -} - -func (n *expiredNode) CollectNodes(path []byte, flushfn NodeFlushFn) error { - return nil -} - -func (n *expiredNode) toDot(parent, path string) string { - me := fmt.Sprintf("expired%s", path) - ret := fmt.Sprintf("%s [label=\"EXPIRED: offset=%d\"]\n", me, n.Offset) - if len(parent) > 0 { - ret = fmt.Sprintf("%s %s -> %s\n", ret, parent, me) - } - return ret -} - -func (n *expiredNode) GetHeight() int { - return 0 -} - -// SetArchiveResolver sets the resolver function for this expired node. -func (n *expiredNode) SetArchiveResolver(resolver archive.ResolverFn) { - n.archiveResolver = resolver -} - -// Depth returns the depth of this node in the trie. -func (n *expiredNode) Depth() int { - return n.depth -} diff --git a/trie/bintrie/expired_node_test.go b/trie/bintrie/expired_node_test.go deleted file mode 100644 index ca9a7548cb..0000000000 --- a/trie/bintrie/expired_node_test.go +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright 2026 go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package bintrie - -import ( - "bytes" - "errors" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/trie/archive" -) - -func TestExpiredNodeSerializeDeserialize(t *testing.T) { - testCases := []struct { - offset uint64 - size uint64 - }{ - {0, 0}, - {1, 100}, - {255, 1024}, - {256, 4096}, - {1 << 16, 1 << 20}, - {1 << 32, 1 << 32}, - {1<<64 - 1, 1<<64 - 1}, - } - - for _, tc := range testCases { - original := &expiredNode{Offset: tc.offset, Size: tc.size, depth: 5} - serialized := SerializeNode(original) - - deserialized, err := DeserializeNode(serialized, 5) - if err != nil { - t.Fatalf("failed to deserialize expired node with offset %d, size %d: %v", tc.offset, tc.size, err) - } - - expNode, ok := deserialized.(*expiredNode) - if !ok { - t.Fatalf("deserialized node is not an expired node, got %T", deserialized) - } - - if expNode.Offset != original.Offset { - t.Errorf("offset mismatch: got %d, want %d", expNode.Offset, original.Offset) - } - - if expNode.Size != original.Size { - t.Errorf("size mismatch: got %d, want %d", expNode.Size, original.Size) - } - - if expNode.depth != original.depth { - t.Errorf("depth mismatch: got %d, want %d", expNode.depth, original.depth) - } - } -} - -func TestExpiredNodeSerializedFormat(t *testing.T) { - node := &expiredNode{Offset: 0x0102030405060708, Size: 0x1112131415161718, depth: 0} - serialized := SerializeNode(node) - - expected := []byte{ - nodeTypeExpired, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - } - if !bytes.Equal(serialized, expected) { - t.Errorf("serialized format mismatch: got %x, want %x", serialized, expected) - } -} - -func TestExpiredNodeSerializedSize(t *testing.T) { - node := &expiredNode{Offset: 12345, Size: 6789, depth: 0} - serialized := SerializeNode(node) - - if len(serialized) != NodeTypeBytes+2*archive.OffsetSize { - t.Errorf("serialized size mismatch: got %d, want %d", len(serialized), NodeTypeBytes+2*archive.OffsetSize) - } -} - -func TestExpiredNodeInvalidLength(t *testing.T) { - invalidCases := [][]byte{ - {nodeTypeExpired}, - {nodeTypeExpired, 0x01}, - {nodeTypeExpired, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, - {nodeTypeExpired, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, - {nodeTypeExpired, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11}, - } - - for _, buf := range invalidCases { - _, err := DeserializeNode(buf, 0) - if err == nil { - t.Errorf("expected error for buffer length %d, got nil", len(buf)) - } - } -} - -func TestExpiredNodeHash(t *testing.T) { - node := &expiredNode{Offset: 100, depth: 5} - hash := node.Hash() - - if hash != (common.Hash{}) { - t.Errorf("expected zero hash, got %x", hash) - } -} - -func TestExpiredNodeGetHeight(t *testing.T) { - node := &expiredNode{Offset: 100, depth: 5} - height := node.GetHeight() - - if height != 0 { - t.Errorf("expected height 0, got %d", height) - } -} - -func TestExpiredNodeCollectNodes(t *testing.T) { - node := &expiredNode{Offset: 100, depth: 5} - called := false - err := node.CollectNodes(nil, func(path []byte, n BinaryNode) { - called = true - }) - - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if called { - t.Error("flush function should not be called for expired nodes") - } -} - -func TestExpiredNodeToDot(t *testing.T) { - node := &expiredNode{Offset: 12345, depth: 5} - dot := node.toDot("parent", "path") - - if dot == "" { - t.Error("toDot should return non-empty string") - } -} - -func TestExpiredNodeCopy(t *testing.T) { - resolver := func(offset, size uint64) ([]*archive.Record, error) { - return nil, nil - } - - original := &expiredNode{ - Offset: 12345, - Size: 6789, - depth: 5, - archiveResolver: resolver, - } - - copied := original.Copy() - copiedExp, ok := copied.(*expiredNode) - if !ok { - t.Fatalf("copied node is not an expired node, got %T", copied) - } - - if copiedExp.Offset != original.Offset { - t.Errorf("offset mismatch: got %d, want %d", copiedExp.Offset, original.Offset) - } - - if copiedExp.Size != original.Size { - t.Errorf("size mismatch: got %d, want %d", copiedExp.Size, original.Size) - } - - if copiedExp.depth != original.depth { - t.Errorf("depth mismatch: got %d, want %d", copiedExp.depth, original.depth) - } - - if copiedExp.archiveResolver == nil { - t.Error("archive resolver was not copied") - } -} - -func TestExpiredNodeNoResolver(t *testing.T) { - node := &expiredNode{Offset: 100, depth: 5} - - _, err := node.Get(make([]byte, 32), nil) - if !errors.Is(err, archive.ErrNoResolver) { - t.Errorf("Get: expected archive.ErrNoResolver, got %v", err) - } - - _, err = node.Insert(make([]byte, 32), make([]byte, 32), nil, 0) - if !errors.Is(err, archive.ErrNoResolver) { - t.Errorf("Insert: expected archive.ErrNoResolver, got %v", err) - } - - _, err = node.GetValuesAtStem(make([]byte, StemSize), nil) - if !errors.Is(err, archive.ErrNoResolver) { - t.Errorf("GetValuesAtStem: expected archive.ErrNoResolver, got %v", err) - } - - _, err = node.InsertValuesAtStem(make([]byte, StemSize), make([][]byte, StemNodeWidth), nil, 0) - if !errors.Is(err, archive.ErrNoResolver) { - t.Errorf("InsertValuesAtStem: expected archive.ErrNoResolver, got %v", err) - } -} - -func TestExpiredNodeWithResolver(t *testing.T) { - var key [32]byte - copy(key[:StemSize], make([]byte, StemSize)) - key[StemSize] = 0 - - var values [StemNodeWidth][]byte - values[0] = make([]byte, HashSize) - copy(values[0], []byte("testvalue")) - - stemNode := &StemNode{ - Stem: key[:StemSize], - Values: values[:], - depth: 5, - } - serializedStem := SerializeNode(stemNode) - - resolver := func(offset, size uint64) ([]*archive.Record, error) { - if offset == 100 { - return []*archive.Record{{Value: serializedStem}}, nil - } - return nil, errors.New("unknown offset") - } - - node := &expiredNode{ - Offset: 100, - Size: uint64(len(serializedStem)), - depth: 5, - archiveResolver: resolver, - } - - vals, err := node.GetValuesAtStem(key[:StemSize], nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - if vals == nil { - t.Fatal("expected non-nil values") - } - - if !bytes.HasPrefix(vals[0], []byte("testvalue")) { - t.Errorf("value mismatch: got %q", vals[0]) - } -} - -func TestExpiredNodeDepth(t *testing.T) { - node := &expiredNode{Offset: 100, depth: 42} - if node.Depth() != 42 { - t.Errorf("expected depth 42, got %d", node.Depth()) - } -} - -func TestExpiredNodeSetArchiveResolver(t *testing.T) { - node := &expiredNode{Offset: 100, depth: 5} - - if node.archiveResolver != nil { - t.Error("expected nil archive resolver initially") - } - - resolver := func(offset, size uint64) ([]*archive.Record, error) { - return nil, nil - } - node.SetArchiveResolver(resolver) - - if node.archiveResolver == nil { - t.Error("expected non-nil archive resolver after setting") - } -}