From 6ab502d302ca16f52712eb63a3fbfda106d492e6 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Thu, 9 Oct 2025 11:10:48 +0800 Subject: [PATCH] core, triedb: address comments from marius --- core/rawdb/schema.go | 15 ++-------- triedb/pathdb/history_trienode.go | 10 +++---- triedb/pathdb/history_trienode_test.go | 41 +++++++++++++++++--------- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go index ed7922e563..d9140c5fd6 100644 --- a/core/rawdb/schema.go +++ b/core/rawdb/schema.go @@ -416,25 +416,19 @@ func trienodeHistoryIndexKey(addressHash common.Hash, path []byte) []byte { // accountHistoryIndexBlockKey = StateHistoryAccountBlockPrefix + addressHash + blockID func accountHistoryIndexBlockKey(addressHash common.Hash, blockID uint32) []byte { - var buf4 [4]byte - binary.BigEndian.PutUint32(buf4[:], blockID) - totalLen := len(StateHistoryAccountBlockPrefix) + common.HashLength + 4 out := make([]byte, totalLen) off := 0 off += copy(out[off:], StateHistoryAccountBlockPrefix) off += copy(out[off:], addressHash.Bytes()) - copy(out[off:], buf4[:]) + binary.BigEndian.PutUint32(out[off:], blockID) return out } // storageHistoryIndexBlockKey = StateHistoryStorageBlockPrefix + addressHash + storageHash + blockID func storageHistoryIndexBlockKey(addressHash common.Hash, storageHash common.Hash, blockID uint32) []byte { - var buf4 [4]byte - binary.BigEndian.PutUint32(buf4[:], blockID) - totalLen := len(StateHistoryStorageBlockPrefix) + 2*common.HashLength + 4 out := make([]byte, totalLen) @@ -442,16 +436,13 @@ func storageHistoryIndexBlockKey(addressHash common.Hash, storageHash common.Has off += copy(out[off:], StateHistoryStorageBlockPrefix) off += copy(out[off:], addressHash.Bytes()) off += copy(out[off:], storageHash.Bytes()) - copy(out[off:], buf4[:]) + binary.BigEndian.PutUint32(out[off:], blockID) return out } // trienodeHistoryIndexBlockKey = TrienodeHistoryBlockPrefix + addressHash + trienode path + blockID func trienodeHistoryIndexBlockKey(addressHash common.Hash, path []byte, blockID uint32) []byte { - var buf4 [4]byte - binary.BigEndian.PutUint32(buf4[:], blockID) - totalLen := len(TrienodeHistoryBlockPrefix) + common.HashLength + len(path) + 4 out := make([]byte, totalLen) @@ -459,7 +450,7 @@ func trienodeHistoryIndexBlockKey(addressHash common.Hash, path []byte, blockID off += copy(out[off:], TrienodeHistoryBlockPrefix) off += copy(out[off:], addressHash.Bytes()) off += copy(out[off:], path) - copy(out[off:], buf4[:]) + binary.BigEndian.PutUint32(out[off:], blockID) return out } diff --git a/triedb/pathdb/history_trienode.go b/triedb/pathdb/history_trienode.go index 28d3027a1a..2a4459d4ad 100644 --- a/triedb/pathdb/history_trienode.go +++ b/triedb/pathdb/history_trienode.go @@ -160,10 +160,7 @@ func newTrienodeHistory(root common.Hash, parent common.Hash, block uint64, node // sharedLen returns the length of the common prefix shared by a and b. func sharedLen(a, b []byte) int { - n := len(a) - if len(b) < n { - n = len(b) - } + n := min(len(a), len(b)) for i := 0; i < n; i++ { if a[i] != b[i] { return i @@ -259,7 +256,8 @@ func (h *trienodeHistory) encode() ([]byte, []byte, []byte, error) { internalValOffset += uint32(len(value)) } - // Encode trailer + // Encode trailer, the number of restart sections is len(restarts))/2, + // as we track the offsets of both key and value sections. var trailer []byte for _, number := range append(restarts, uint32(len(restarts))/2) { binary.BigEndian.PutUint32(buf[:4], number) @@ -341,7 +339,7 @@ func decodeSingle(keySection []byte, onValue func([]byte, int, int) error) ([]st keys []string ) - // Decode restarts + // Decode the number of restart section if len(keySection) < 4 { return nil, fmt.Errorf("key section too short, size: %d", len(keySection)) } diff --git a/triedb/pathdb/history_trienode_test.go b/triedb/pathdb/history_trienode_test.go index b02c0d5380..d6b80f61f5 100644 --- a/triedb/pathdb/history_trienode_test.go +++ b/triedb/pathdb/history_trienode_test.go @@ -43,11 +43,9 @@ func randomTrienodes(n int) (map[common.Hash]map[string][]byte, common.Hash) { nodes[owner] = make(map[string][]byte) for j := 0; j < 10; j++ { - pathLen := rand.Intn(10) - path := testrand.Bytes(pathLen) + path := testrand.Bytes(rand.Intn(10)) for z := 0; z < len(path); z++ { - valLen := rand.Intn(128) - nodes[owner][string(path[:z])] = testrand.Bytes(valLen) + nodes[owner][string(path[:z])] = testrand.Bytes(rand.Intn(128)) } } // zero-size trie node, representing it was non-existent before @@ -65,7 +63,7 @@ func randomTrienodes(n int) (map[common.Hash]map[string][]byte, common.Hash) { return nodes, root } -func makeTrinodeHistory() *trienodeHistory { +func makeTrienodeHistory() *trienodeHistory { nodes, root := randomTrienodes(10) return newTrienodeHistory(root, common.Hash{}, 1, nodes) } @@ -86,7 +84,7 @@ func makeTrienodeHistories(n int) []*trienodeHistory { func TestEncodeDecodeTrienodeHistory(t *testing.T) { var ( dec trienodeHistory - obj = makeTrinodeHistory() + obj = makeTrienodeHistory() ) header, keySection, valueSection, err := obj.encode() if err != nil { @@ -108,6 +106,21 @@ func TestEncodeDecodeTrienodeHistory(t *testing.T) { if !compareMapSet(dec.nodes, obj.nodes) { t.Fatal("trienode content is mismatched") } + + // Re-encode again, ensuring the encoded blob still match + header2, keySection2, valueSection2, err := dec.encode() + if err != nil { + t.Fatalf("Failed to encode trienode history: %v", err) + } + if !bytes.Equal(header, header2) { + t.Fatal("re-encoded header is mismatched") + } + if !bytes.Equal(keySection, keySection2) { + t.Fatal("re-encoded key section is mismatched") + } + if !bytes.Equal(valueSection, valueSection2) { + t.Fatal("re-encoded value section is mismatched") + } } func TestTrienodeHistoryReader(t *testing.T) { @@ -280,7 +293,7 @@ func TestNilNodeValues(t *testing.T) { // TestCorruptedHeader tests error handling for corrupted header data func TestCorruptedHeader(t *testing.T) { - h := makeTrinodeHistory() + h := makeTrienodeHistory() header, keySection, valueSection, _ := h.encode() // Test corrupted version @@ -311,7 +324,7 @@ func TestCorruptedHeader(t *testing.T) { // TestCorruptedKeySection tests error handling for corrupted key section data func TestCorruptedKeySection(t *testing.T) { - h := makeTrinodeHistory() + h := makeTrienodeHistory() header, keySection, valueSection, _ := h.encode() // Test empty key section when header indicates data @@ -345,7 +358,7 @@ func TestCorruptedKeySection(t *testing.T) { // TestCorruptedValueSection tests error handling for corrupted value section data func TestCorruptedValueSection(t *testing.T) { - h := makeTrinodeHistory() + h := makeTrienodeHistory() header, keySection, valueSection, _ := h.encode() // Test truncated value section @@ -368,7 +381,7 @@ func TestCorruptedValueSection(t *testing.T) { // TestInvalidOffsets tests error handling for invalid offsets in encoded data func TestInvalidOffsets(t *testing.T) { - h := makeTrinodeHistory() + h := makeTrienodeHistory() header, keySection, valueSection, _ := h.encode() // Corrupt key offset in header (make it larger than key section) @@ -395,7 +408,7 @@ func TestInvalidOffsets(t *testing.T) { // TestTrienodeHistoryReaderNonExistentPath tests reading non-existent paths func TestTrienodeHistoryReaderNonExistentPath(t *testing.T) { var ( - h = makeTrinodeHistory() + h = makeTrienodeHistory() freezer, _ = rawdb.NewTrienodeFreezer(t.TempDir(), false, false) ) defer freezer.Close() @@ -523,7 +536,7 @@ func TestTrienodeHistoryReaderNilKey(t *testing.T) { // TestTrienodeHistoryReaderIterator tests the iterator functionality func TestTrienodeHistoryReaderIterator(t *testing.T) { - h := makeTrinodeHistory() + h := makeTrienodeHistory() // Count expected entries expectedCount := 0 @@ -614,7 +627,7 @@ func TestSharedLen(t *testing.T) { // TestDecodeHeaderCorruptedData tests decodeHeader with corrupted data func TestDecodeHeaderCorruptedData(t *testing.T) { // Create valid header data first - h := makeTrinodeHistory() + h := makeTrienodeHistory() header, _, _, _ := h.encode() // Test with empty header @@ -661,7 +674,7 @@ func TestDecodeHeaderCorruptedData(t *testing.T) { // TestDecodeSingleCorruptedData tests decodeSingle with corrupted data func TestDecodeSingleCorruptedData(t *testing.T) { - h := makeTrinodeHistory() + h := makeTrienodeHistory() _, keySection, _, _ := h.encode() // Test with empty key section