Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions core/types/hashes.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,7 @@ var (

// EmptyVerkleHash is the known hash of an empty verkle trie.
EmptyVerkleHash = common.Hash{}

// EmptyBinaryHash is the known hash of an empty binary trie.
EmptyBinaryHash = common.Hash{}
)
5 changes: 2 additions & 3 deletions trie/bintrie/binary_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ const (
// BinaryNode is an interface for a binary trie node.
type BinaryNode interface {
Get([]byte, NodeResolverFn) ([]byte, error)
Insert([]byte, []byte, NodeResolverFn) (BinaryNode, error)
// Commit() common.Hash
Insert([]byte, []byte, NodeResolverFn, int) (BinaryNode, error)
Copy() BinaryNode
Hash() common.Hash
GetValuesAtStem([]byte, NodeResolverFn) ([][]byte, error)
Expand All @@ -65,7 +64,7 @@ func SerializeNode(node BinaryNode) []byte {
copy(serialized[33:65], n.right.Hash().Bytes())
return serialized[:]
case *StemNode:
var serialized [32 + 256*32]byte
var serialized [32 + 32 + 256*32]byte
serialized[0] = nodeTypeStem
copy(serialized[1:32], node.(*StemNode).Stem)
bitmap := serialized[32:64]
Expand Down
3 changes: 2 additions & 1 deletion trie/bintrie/empty.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ func (e Empty) Get(_ []byte, _ NodeResolverFn) ([]byte, error) {
return nil, nil
}

func (e Empty) Insert(key []byte, value []byte, _ NodeResolverFn) (BinaryNode, error) {
func (e Empty) Insert(key []byte, value []byte, _ NodeResolverFn, depth int) (BinaryNode, error) {
var values [256][]byte
values[key[31]] = value
return &StemNode{
Stem: slices.Clone(key[:31]),
Values: values[:],
depth: depth,
}, nil
}

Expand Down
2 changes: 1 addition & 1 deletion trie/bintrie/empty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestEmptyInsert(t *testing.T) {
key[31] = 0x34
value := common.HexToHash("0xabcd").Bytes()

newNode, err := node.Insert(key, value, nil)
newNode, err := node.Insert(key, value, nil, 0)
if err != nil {
t.Fatalf("Failed to insert: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion trie/bintrie/hashed_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (h HashedNode) Get(_ []byte, _ NodeResolverFn) ([]byte, error) {
panic("not implemented") // TODO: Implement
}

func (h HashedNode) Insert(key []byte, value []byte, resolver NodeResolverFn) (BinaryNode, error) {
func (h HashedNode) Insert(key []byte, value []byte, resolver NodeResolverFn, depth int) (BinaryNode, error) {
return nil, errors.New("insert not implemented for hashed node")
}

Expand Down
2 changes: 1 addition & 1 deletion trie/bintrie/hashed_node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func TestHashedNodeInsert(t *testing.T) {
key := make([]byte, 32)
value := make([]byte, 32)

_, err := node.Insert(key, value, nil)
_, err := node.Insert(key, value, nil, 0)
if err == nil {
t.Fatal("Expected error for Insert on HashedNode")
}
Expand Down
15 changes: 6 additions & 9 deletions trie/bintrie/internal_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,22 @@
package bintrie

import (
"crypto/sha256"
"errors"
"fmt"

"github.com/ethereum/go-ethereum/common"
"crypto/sha256"
)

func keyToPath(depth int, key []byte) ([]byte, error) {
path := make([]byte, 0, depth+1)

if depth > 31*8 {
return nil, errors.New("node too deep")
}

path := make([]byte, 0, depth+1)
for i := range depth + 1 {
bit := key[i/8] >> (7 - (i % 8)) & 1
path = append(path, bit)
}

return path, nil
}

Expand Down Expand Up @@ -81,16 +78,16 @@ func (bt *InternalNode) GetValuesAtStem(stem []byte, resolver NodeResolverFn) ([
func (bt *InternalNode) Get(key []byte, resolver NodeResolverFn) ([]byte, error) {
values, err := bt.GetValuesAtStem(key[:31], resolver)
if err != nil {
return nil, fmt.Errorf("Get error: %w", err)
return nil, fmt.Errorf("get error: %w", err)
}
return values[key[31]], nil
}

// Insert inserts a new key-value pair into the trie.
func (bt *InternalNode) Insert(key []byte, value []byte, resolver NodeResolverFn) (BinaryNode, error) {
func (bt *InternalNode) Insert(key []byte, value []byte, resolver NodeResolverFn, depth int) (BinaryNode, error) {
var values [256][]byte
values[key[31]] = value
return bt.InsertValuesAtStem(key[:31], values[:], resolver, 0)
return bt.InsertValuesAtStem(key[:31], values[:], resolver, depth)
}

// Copy creates a deep copy of the node.
Expand Down Expand Up @@ -121,11 +118,11 @@ func (bt *InternalNode) Hash() common.Hash {
// InsertValuesAtStem inserts a full value group at the given stem in the internal node.
// Already-existing values will be overwritten.
func (bt *InternalNode) InsertValuesAtStem(stem []byte, values [][]byte, resolver NodeResolverFn, depth int) (BinaryNode, error) {
bit := stem[bt.depth/8] >> (7 - (bt.depth % 8)) & 1
var (
child *BinaryNode
err error
)
bit := stem[bt.depth/8] >> (7 - (bt.depth % 8)) & 1
if bit == 0 {
child = &bt.left
} else {
Expand Down
2 changes: 1 addition & 1 deletion trie/bintrie/internal_node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func TestInternalNodeInsert(t *testing.T) {
leftKey[31] = 10
leftValue := common.HexToHash("0x0101").Bytes()

newNode, err := node.Insert(leftKey, leftValue, nil)
newNode, err := node.Insert(leftKey, leftValue, nil, 0)
if err != nil {
t.Fatalf("Failed to insert: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion trie/bintrie/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (it *binaryNodeIterator) Next(descend bool) bool {
return it.Next(descend)
case HashedNode:
// resolve the node
data, err := it.trie.FlatdbNodeResolver(it.Path(), common.Hash(node))
data, err := it.trie.nodeResolver(it.Path(), common.Hash(node))
if err != nil {
panic(err)
}
Expand Down
79 changes: 79 additions & 0 deletions trie/bintrie/key_encoding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2025 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"
"crypto/sha256"

"github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256"
)

const (
BasicDataLeafKey = 0
CodeHashLeafKey = 1
BasicDataCodeSizeOffset = 5
BasicDataNonceOffset = 8
BasicDataBalanceOffset = 16
)

var (
zeroHash = common.Hash{}
codeOffset = uint256.NewInt(128)
)

func GetBinaryTreeKey(addr common.Address, key []byte) []byte {
hasher := sha256.New()
hasher.Write(zeroHash[:12])
hasher.Write(addr[:])
hasher.Write(key[:31])
k := hasher.Sum(nil)
k[31] = key[31]
return k
}

func GetBinaryTreeKeyCodeHash(addr common.Address) []byte {
var k [32]byte
k[31] = CodeHashLeafKey
return GetBinaryTreeKey(addr, k[:])
}

func GetBinaryTreeKeyStorageSlot(address common.Address, key []byte) []byte {
var k [32]byte

// Case when the key belongs to the account header
if bytes.Equal(key[:31], zeroHash[:31]) && key[31] < 64 {
k[31] = 64 + key[31]
return GetBinaryTreeKey(address, k[:])
}

// Set the main storage offset
// note that the first 64 bytes of the main offset storage
// are unreachable, which is consistent with the spec and
// what verkle does.
k[0] = 1 // 1 << 248
copy(k[1:], key[:31])
k[31] = key[31]

return GetBinaryTreeKey(address, k[:])
}

func GetBinaryTreeKeyCodeChunk(address common.Address, chunknr *uint256.Int) []byte {
chunkOffset := new(uint256.Int).Add(codeOffset, chunknr).Bytes()
return GetBinaryTreeKey(address, chunkOffset)
}
11 changes: 4 additions & 7 deletions trie/bintrie/stem_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ package bintrie

import (
"bytes"
"crypto/sha256"
"errors"
"fmt"
"slices"

"github.com/ethereum/go-ethereum/common"
"crypto/sha256"
)

// StemNode represents a group of `NodeWith` values sharing the same stem.
Expand All @@ -39,7 +39,7 @@ func (bt *StemNode) Get(key []byte, _ NodeResolverFn) ([]byte, error) {
}

// Insert inserts a new key-value pair into the node.
func (bt *StemNode) Insert(key []byte, value []byte, _ NodeResolverFn) (BinaryNode, error) {
func (bt *StemNode) Insert(key []byte, value []byte, _ NodeResolverFn, depth int) (BinaryNode, error) {
if !bytes.Equal(bt.Stem, key[:31]) {
bitStem := bt.Stem[bt.depth/8] >> (7 - (bt.depth % 8)) & 1

Expand All @@ -59,7 +59,7 @@ func (bt *StemNode) Insert(key []byte, value []byte, _ NodeResolverFn) (BinaryNo
bitKey := key[new.depth/8] >> (7 - (new.depth % 8)) & 1
if bitKey == bitStem {
var err error
*child, err = (*child).Insert(key, value, nil)
*child, err = (*child).Insert(key, value, nil, depth+1)
if err != nil {
return new, fmt.Errorf("insert error: %w", err)
}
Expand All @@ -70,16 +70,14 @@ func (bt *StemNode) Insert(key []byte, value []byte, _ NodeResolverFn) (BinaryNo
*other = &StemNode{
Stem: slices.Clone(key[:31]),
Values: values[:],
depth: new.depth + 1,
depth: depth + 1,
}
}

return new, nil
}
if len(value) != 32 {
return bt, errors.New("invalid insertion: value length")
}

bt.Values[key[31]] = value
return bt, nil
}
Expand Down Expand Up @@ -181,7 +179,6 @@ func (bt *StemNode) InsertValuesAtStem(key []byte, values [][]byte, _ NodeResolv
depth: new.depth + 1,
}
}

return new, nil
}

Expand Down
6 changes: 3 additions & 3 deletions trie/bintrie/stem_node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestStemNodeInsertSameStem(t *testing.T) {
key[31] = 10
value := common.HexToHash("0x0202").Bytes()

newNode, err := node.Insert(key, value, nil)
newNode, err := node.Insert(key, value, nil, 0)
if err != nil {
t.Fatalf("Failed to insert: %v", err)
}
Expand Down Expand Up @@ -86,7 +86,7 @@ func TestStemNodeInsertDifferentStem(t *testing.T) {
key[0] = 0x80 // First bit is 1 instead of 0
value := common.HexToHash("0x0202").Bytes()

newNode, err := node.Insert(key, value, nil)
newNode, err := node.Insert(key, value, nil, 0)
if err != nil {
t.Fatalf("Failed to insert: %v", err)
}
Expand Down Expand Up @@ -137,7 +137,7 @@ func TestStemNodeInsertInvalidValueLength(t *testing.T) {
copy(key[:31], stem)
invalidValue := []byte{1, 2, 3} // Not 32 bytes

_, err := node.Insert(key, invalidValue, nil)
_, err := node.Insert(key, invalidValue, nil, 0)
if err == nil {
t.Fatal("Expected error for invalid value length")
}
Expand Down
Loading
Loading