mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 13:21:37 +00:00
drop bintrie support for now
This commit is contained in:
parent
34baa98ea9
commit
a764b36449
2 changed files with 0 additions and 453 deletions
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
}
|
||||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue