mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-20 13:44:31 +00:00
Replace Keccak256+MSB tagging with SHA256. Remove leaf nodes entirely, replacing them with opaque stem hashes. Simplify NodeKind to just Terminator and Internal. Add HashStem (8-level binary SHA256 tree matching bintrie StemNode.Hash). Reduce max trie depth from 256 to 248 (31-byte stem path). Replace BuildTrie/LeafOp with BuildInternalTree/StemKeyValue. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
142 lines
3.1 KiB
Go
142 lines
3.1 KiB
Go
package core
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestTerminatorIsZero(t *testing.T) {
|
|
var zero [32]byte
|
|
assert.Equal(t, zero, Terminator)
|
|
}
|
|
|
|
func TestNodeKindOf(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
node Node
|
|
want NodeKind
|
|
}{
|
|
{
|
|
name: "terminator",
|
|
node: Terminator,
|
|
want: NodeTerminator,
|
|
},
|
|
{
|
|
name: "non-zero hash is internal",
|
|
node: Node{0x80, 0x01, 0x02},
|
|
want: NodeInternal,
|
|
},
|
|
{
|
|
name: "any non-zero is internal",
|
|
node: Node{0x01, 0x02, 0x03},
|
|
want: NodeInternal,
|
|
},
|
|
{
|
|
name: "high bits set is still internal",
|
|
node: Node{0xFF, 0xFF, 0xFF},
|
|
want: NodeInternal,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := NodeKindOf(&tt.node)
|
|
assert.Equal(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsTerminator(t *testing.T) {
|
|
assert.True(t, IsTerminator(&Terminator))
|
|
|
|
nonZero := Node{0x01}
|
|
assert.False(t, IsTerminator(&nonZero))
|
|
}
|
|
|
|
func TestHashInternalDeterministic(t *testing.T) {
|
|
data := &InternalData{
|
|
Left: Node{0x11, 0x22},
|
|
Right: Node{0x33, 0x44},
|
|
}
|
|
h1 := HashInternal(data)
|
|
h2 := HashInternal(data)
|
|
assert.Equal(t, h1, h2, "same inputs must produce same hash")
|
|
}
|
|
|
|
func TestHashInternalMatchesSHA256(t *testing.T) {
|
|
left := Node{0x01, 0x02, 0x03}
|
|
right := Node{0x04, 0x05, 0x06}
|
|
|
|
data := &InternalData{Left: left, Right: right}
|
|
got := HashInternal(data)
|
|
|
|
// Manual SHA256(left || right)
|
|
h := sha256.New()
|
|
h.Write(left[:])
|
|
h.Write(right[:])
|
|
expected := h.Sum(nil)
|
|
|
|
assert.Equal(t, expected, got[:])
|
|
}
|
|
|
|
func TestHashInternalNoMSBTagging(t *testing.T) {
|
|
// With SHA256, the MSB is determined by the hash output, not forced.
|
|
// Just verify it produces a non-zero, non-terminator result.
|
|
data := &InternalData{
|
|
Left: Node{0xFF, 0x01},
|
|
Right: Node{0x80, 0x02},
|
|
}
|
|
result := HashInternal(data)
|
|
require.False(t, IsTerminator(&result))
|
|
}
|
|
|
|
func TestHashStemDeterministic(t *testing.T) {
|
|
var stem StemPath
|
|
stem[0] = 0xAB
|
|
stem[1] = 0xCD
|
|
|
|
var values [StemNodeWidth][]byte
|
|
values[0] = make([]byte, 32)
|
|
values[0][0] = 0x01
|
|
|
|
h1 := HashStem(stem, values)
|
|
h2 := HashStem(stem, values)
|
|
assert.Equal(t, h1, h2, "same inputs must produce same hash")
|
|
}
|
|
|
|
func TestHashStemAllNilIsNotZero(t *testing.T) {
|
|
// Even with all nil values, the stem hash includes the stem bytes,
|
|
// so it should NOT be the zero hash (unless stem is also zero and
|
|
// subtree root is zero... let's check).
|
|
var stem StemPath
|
|
var values [StemNodeWidth][]byte
|
|
|
|
// With all-zero stem and all-nil values, the subtree root is zero.
|
|
// Final = SHA256(zero_stem || 0x00 || zero_hash)
|
|
result := HashStem(stem, values)
|
|
assert.False(t, IsTerminator(&result),
|
|
"stem hash should not be terminator even with empty values")
|
|
}
|
|
|
|
func TestHashStemSingleValue(t *testing.T) {
|
|
var stem StemPath
|
|
stem[0] = 0x42
|
|
|
|
var values [StemNodeWidth][]byte
|
|
val := make([]byte, 32)
|
|
val[0] = 0xFF
|
|
values[0] = val
|
|
|
|
result := HashStem(stem, values)
|
|
assert.False(t, IsTerminator(&result))
|
|
}
|
|
|
|
func TestStemPathType(t *testing.T) {
|
|
// Verify StemPath is 31 bytes.
|
|
var sp StemPath
|
|
assert.Equal(t, StemSize, len(sp))
|
|
assert.Equal(t, 31, len(sp))
|
|
}
|