go-blockchain/wire/treehash_test.go
Virgil 5789325690 fix(blockchain): complete AX v0.8.0 polish pass
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 16:58:23 +00:00

171 lines
3.8 KiB
Go

// Copyright (c) 2017-2026 Lethean (https://lt.hn)
//
// Licensed under the European Union Public Licence (EUPL) version 1.2.
// SPDX-License-Identifier: EUPL-1.2
package wire
import (
"encoding/hex"
"testing"
)
func TestTreehash_Keccak256_Good(t *testing.T) {
// Empty input: well-known Keccak-256 of "" (pre-NIST).
got := Keccak256(nil)
want := "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
if hex.EncodeToString(got[:]) != want {
t.Errorf("Keccak256(nil) = %x, want %s", got, want)
}
}
func TestTreehash_TreeHashSingle_Good(t *testing.T) {
var h [32]byte
h[0] = 0xAB
h[31] = 0xCD
got := TreeHash([][32]byte{h})
if got != h {
t.Error("TreeHash of single hash should be identity")
}
}
func TestTreehash_TreeHashPair_Good(t *testing.T) {
var h0, h1 [32]byte
h0[0] = 0x01
h1[0] = 0x02
got := TreeHash([][32]byte{h0, h1})
// Manual: Keccak256(h0 || h1)
var buf [64]byte
copy(buf[:32], h0[:])
copy(buf[32:], h1[:])
want := Keccak256(buf[:])
if got != want {
t.Errorf("TreeHash pair: got %x, want %x", got, want)
}
}
func TestTreehash_TreeHashThree_Good(t *testing.T) {
var h0, h1, h2 [32]byte
h0[0] = 0xAA
h1[0] = 0xBB
h2[0] = 0xCC
got := TreeHash([][32]byte{h0, h1, h2})
// For 3 hashes, cnt=2:
// ints[0] = h0 (direct copy)
// ints[1] = Keccak256(h1 || h2)
// result = Keccak256(ints[0] || ints[1])
var buf [64]byte
copy(buf[:32], h1[:])
copy(buf[32:], h2[:])
ints1 := Keccak256(buf[:])
copy(buf[:32], h0[:])
copy(buf[32:], ints1[:])
want := Keccak256(buf[:])
if got != want {
t.Errorf("TreeHash(3): got %x, want %x", got, want)
}
}
func TestTreehash_TreeHashFour_Good(t *testing.T) {
hashes := make([][32]byte, 4)
for i := range hashes {
hashes[i][0] = byte(i + 1)
}
got := TreeHash(hashes)
// For 4 hashes, cnt=2:
// ints[0] = Keccak256(h0 || h1)
// ints[1] = Keccak256(h2 || h3)
// result = Keccak256(ints[0] || ints[1])
var buf [64]byte
copy(buf[:32], hashes[0][:])
copy(buf[32:], hashes[1][:])
ints0 := Keccak256(buf[:])
copy(buf[:32], hashes[2][:])
copy(buf[32:], hashes[3][:])
ints1 := Keccak256(buf[:])
copy(buf[:32], ints0[:])
copy(buf[32:], ints1[:])
want := Keccak256(buf[:])
if got != want {
t.Errorf("TreeHash(4): got %x, want %x", got, want)
}
}
func TestTreehash_TreeHashFive_Good(t *testing.T) {
// 5 hashes exercises the iterative cnt > 2 loop.
hashes := make([][32]byte, 5)
for i := range hashes {
hashes[i][0] = byte(i + 1)
}
got := TreeHash(hashes)
// For 5 hashes: cnt=4, direct=3
// ints[0] = h0, ints[1] = h1, ints[2] = h2
// ints[3] = Keccak256(h3 || h4)
// Then cnt=2: ints[0] = Keccak256(ints[0] || ints[1])
// ints[1] = Keccak256(ints[2] || ints[3])
// Final = Keccak256(ints[0] || ints[1])
var buf [64]byte
// ints[3]
copy(buf[:32], hashes[3][:])
copy(buf[32:], hashes[4][:])
ints3 := Keccak256(buf[:])
// Round 1: pair-hash
copy(buf[:32], hashes[0][:])
copy(buf[32:], hashes[1][:])
r1_0 := Keccak256(buf[:])
copy(buf[:32], hashes[2][:])
copy(buf[32:], ints3[:])
r1_1 := Keccak256(buf[:])
// Final
copy(buf[:32], r1_0[:])
copy(buf[32:], r1_1[:])
want := Keccak256(buf[:])
if got != want {
t.Errorf("TreeHash(5): got %x, want %x", got, want)
}
}
func TestTreehash_TreeHashEight_Good(t *testing.T) {
// 8 hashes = perfect power of 2, exercises multiple loop iterations.
hashes := make([][32]byte, 8)
for i := range hashes {
hashes[i][0] = byte(i + 1)
}
got := TreeHash(hashes)
// Verify determinism.
got2 := TreeHash(hashes)
if got != got2 {
t.Error("TreeHash(8) not deterministic")
}
// Sanity: result should not be zero.
if got == ([32]byte{}) {
t.Error("TreeHash(8) returned zero hash")
}
}
func TestTreehash_TreeHashEmpty_Good(t *testing.T) {
got := TreeHash(nil)
if got != ([32]byte{}) {
t.Errorf("TreeHash(nil) should be zero hash, got %x", got)
}
}