From 0911d742fde33b62610caf79517a10405ee35be6 Mon Sep 17 00:00:00 2001 From: cui Date: Tue, 7 Oct 2025 02:06:35 +0800 Subject: [PATCH] refactor: pre calculate the empty hash to save cost (#25359) Co-authored-by: Alex | Interchain Labs --- store/internal/tree/hash.go | 12 +++++------- store/internal/tree/hash_test.go | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 store/internal/tree/hash_test.go diff --git a/store/internal/tree/hash.go b/store/internal/tree/hash.go index 3b9b356691..3a672959da 100644 --- a/store/internal/tree/hash.go +++ b/store/internal/tree/hash.go @@ -4,6 +4,7 @@ import ( "crypto/sha256" "hash" "math/bits" + "slices" ) var ( @@ -17,10 +18,13 @@ func HashFromByteSlices(items [][]byte) []byte { return hashFromByteSlices(sha256.New(), items) } +// emptyHash is the sha256 hash of the empty string. +var emptyHash = [32]byte{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55} + func hashFromByteSlices(sha hash.Hash, items [][]byte) []byte { switch len(items) { case 0: - return emptyHash() + return slices.Clone(emptyHash[:]) case 1: return leafHashOpt(sha, items[0]) default: @@ -47,12 +51,6 @@ func innerHashOpt(s hash.Hash, left, right []byte) []byte { return s.Sum(nil) } -// emptyHash returns tmhash() -func emptyHash() []byte { - h := sha256.Sum256([]byte{}) - return h[:] -} - // getSplitPoint returns the largest power of 2 less than length func getSplitPoint(length int64) int64 { if length < 1 { diff --git a/store/internal/tree/hash_test.go b/store/internal/tree/hash_test.go new file mode 100644 index 0000000000..7197eb19bb --- /dev/null +++ b/store/internal/tree/hash_test.go @@ -0,0 +1,20 @@ +package tree + +import ( + "crypto/sha256" + "testing" +) + +func emptyHashF() []byte { + h := sha256.Sum256([]byte{}) + return h[:] +} + +func TestEmptyHashEqual(t *testing.T) { + var emptyHashBytes [32]byte + copy(emptyHashBytes[:], emptyHashF()) + expected := emptyHash + if emptyHashBytes != expected { + t.Fatalf("empty hash mismatch: got=%#v expected=%#v", emptyHashBytes, expected) + } +}