core, triedb: address comments from marius

This commit is contained in:
Gary Rong 2025-10-09 11:10:48 +08:00
parent 507c50d572
commit 6ab502d302
3 changed files with 34 additions and 32 deletions

View file

@ -416,25 +416,19 @@ func trienodeHistoryIndexKey(addressHash common.Hash, path []byte) []byte {
// accountHistoryIndexBlockKey = StateHistoryAccountBlockPrefix + addressHash + blockID // accountHistoryIndexBlockKey = StateHistoryAccountBlockPrefix + addressHash + blockID
func accountHistoryIndexBlockKey(addressHash common.Hash, blockID uint32) []byte { func accountHistoryIndexBlockKey(addressHash common.Hash, blockID uint32) []byte {
var buf4 [4]byte
binary.BigEndian.PutUint32(buf4[:], blockID)
totalLen := len(StateHistoryAccountBlockPrefix) + common.HashLength + 4 totalLen := len(StateHistoryAccountBlockPrefix) + common.HashLength + 4
out := make([]byte, totalLen) out := make([]byte, totalLen)
off := 0 off := 0
off += copy(out[off:], StateHistoryAccountBlockPrefix) off += copy(out[off:], StateHistoryAccountBlockPrefix)
off += copy(out[off:], addressHash.Bytes()) off += copy(out[off:], addressHash.Bytes())
copy(out[off:], buf4[:]) binary.BigEndian.PutUint32(out[off:], blockID)
return out return out
} }
// storageHistoryIndexBlockKey = StateHistoryStorageBlockPrefix + addressHash + storageHash + blockID // storageHistoryIndexBlockKey = StateHistoryStorageBlockPrefix + addressHash + storageHash + blockID
func storageHistoryIndexBlockKey(addressHash common.Hash, storageHash common.Hash, blockID uint32) []byte { 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 totalLen := len(StateHistoryStorageBlockPrefix) + 2*common.HashLength + 4
out := make([]byte, totalLen) 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:], StateHistoryStorageBlockPrefix)
off += copy(out[off:], addressHash.Bytes()) off += copy(out[off:], addressHash.Bytes())
off += copy(out[off:], storageHash.Bytes()) off += copy(out[off:], storageHash.Bytes())
copy(out[off:], buf4[:]) binary.BigEndian.PutUint32(out[off:], blockID)
return out return out
} }
// trienodeHistoryIndexBlockKey = TrienodeHistoryBlockPrefix + addressHash + trienode path + blockID // trienodeHistoryIndexBlockKey = TrienodeHistoryBlockPrefix + addressHash + trienode path + blockID
func trienodeHistoryIndexBlockKey(addressHash common.Hash, path []byte, blockID uint32) []byte { 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 totalLen := len(TrienodeHistoryBlockPrefix) + common.HashLength + len(path) + 4
out := make([]byte, totalLen) 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:], TrienodeHistoryBlockPrefix)
off += copy(out[off:], addressHash.Bytes()) off += copy(out[off:], addressHash.Bytes())
off += copy(out[off:], path) off += copy(out[off:], path)
copy(out[off:], buf4[:]) binary.BigEndian.PutUint32(out[off:], blockID)
return out return out
} }

View file

@ -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. // sharedLen returns the length of the common prefix shared by a and b.
func sharedLen(a, b []byte) int { func sharedLen(a, b []byte) int {
n := len(a) n := min(len(a), len(b))
if len(b) < n {
n = len(b)
}
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
if a[i] != b[i] { if a[i] != b[i] {
return i return i
@ -259,7 +256,8 @@ func (h *trienodeHistory) encode() ([]byte, []byte, []byte, error) {
internalValOffset += uint32(len(value)) 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 var trailer []byte
for _, number := range append(restarts, uint32(len(restarts))/2) { for _, number := range append(restarts, uint32(len(restarts))/2) {
binary.BigEndian.PutUint32(buf[:4], number) binary.BigEndian.PutUint32(buf[:4], number)
@ -341,7 +339,7 @@ func decodeSingle(keySection []byte, onValue func([]byte, int, int) error) ([]st
keys []string keys []string
) )
// Decode restarts // Decode the number of restart section
if len(keySection) < 4 { if len(keySection) < 4 {
return nil, fmt.Errorf("key section too short, size: %d", len(keySection)) return nil, fmt.Errorf("key section too short, size: %d", len(keySection))
} }

View file

@ -43,11 +43,9 @@ func randomTrienodes(n int) (map[common.Hash]map[string][]byte, common.Hash) {
nodes[owner] = make(map[string][]byte) nodes[owner] = make(map[string][]byte)
for j := 0; j < 10; j++ { for j := 0; j < 10; j++ {
pathLen := rand.Intn(10) path := testrand.Bytes(rand.Intn(10))
path := testrand.Bytes(pathLen)
for z := 0; z < len(path); z++ { for z := 0; z < len(path); z++ {
valLen := rand.Intn(128) nodes[owner][string(path[:z])] = testrand.Bytes(rand.Intn(128))
nodes[owner][string(path[:z])] = testrand.Bytes(valLen)
} }
} }
// zero-size trie node, representing it was non-existent before // 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 return nodes, root
} }
func makeTrinodeHistory() *trienodeHistory { func makeTrienodeHistory() *trienodeHistory {
nodes, root := randomTrienodes(10) nodes, root := randomTrienodes(10)
return newTrienodeHistory(root, common.Hash{}, 1, nodes) return newTrienodeHistory(root, common.Hash{}, 1, nodes)
} }
@ -86,7 +84,7 @@ func makeTrienodeHistories(n int) []*trienodeHistory {
func TestEncodeDecodeTrienodeHistory(t *testing.T) { func TestEncodeDecodeTrienodeHistory(t *testing.T) {
var ( var (
dec trienodeHistory dec trienodeHistory
obj = makeTrinodeHistory() obj = makeTrienodeHistory()
) )
header, keySection, valueSection, err := obj.encode() header, keySection, valueSection, err := obj.encode()
if err != nil { if err != nil {
@ -108,6 +106,21 @@ func TestEncodeDecodeTrienodeHistory(t *testing.T) {
if !compareMapSet(dec.nodes, obj.nodes) { if !compareMapSet(dec.nodes, obj.nodes) {
t.Fatal("trienode content is mismatched") 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) { func TestTrienodeHistoryReader(t *testing.T) {
@ -280,7 +293,7 @@ func TestNilNodeValues(t *testing.T) {
// TestCorruptedHeader tests error handling for corrupted header data // TestCorruptedHeader tests error handling for corrupted header data
func TestCorruptedHeader(t *testing.T) { func TestCorruptedHeader(t *testing.T) {
h := makeTrinodeHistory() h := makeTrienodeHistory()
header, keySection, valueSection, _ := h.encode() header, keySection, valueSection, _ := h.encode()
// Test corrupted version // Test corrupted version
@ -311,7 +324,7 @@ func TestCorruptedHeader(t *testing.T) {
// TestCorruptedKeySection tests error handling for corrupted key section data // TestCorruptedKeySection tests error handling for corrupted key section data
func TestCorruptedKeySection(t *testing.T) { func TestCorruptedKeySection(t *testing.T) {
h := makeTrinodeHistory() h := makeTrienodeHistory()
header, keySection, valueSection, _ := h.encode() header, keySection, valueSection, _ := h.encode()
// Test empty key section when header indicates data // 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 // TestCorruptedValueSection tests error handling for corrupted value section data
func TestCorruptedValueSection(t *testing.T) { func TestCorruptedValueSection(t *testing.T) {
h := makeTrinodeHistory() h := makeTrienodeHistory()
header, keySection, valueSection, _ := h.encode() header, keySection, valueSection, _ := h.encode()
// Test truncated value section // Test truncated value section
@ -368,7 +381,7 @@ func TestCorruptedValueSection(t *testing.T) {
// TestInvalidOffsets tests error handling for invalid offsets in encoded data // TestInvalidOffsets tests error handling for invalid offsets in encoded data
func TestInvalidOffsets(t *testing.T) { func TestInvalidOffsets(t *testing.T) {
h := makeTrinodeHistory() h := makeTrienodeHistory()
header, keySection, valueSection, _ := h.encode() header, keySection, valueSection, _ := h.encode()
// Corrupt key offset in header (make it larger than key section) // 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 // TestTrienodeHistoryReaderNonExistentPath tests reading non-existent paths
func TestTrienodeHistoryReaderNonExistentPath(t *testing.T) { func TestTrienodeHistoryReaderNonExistentPath(t *testing.T) {
var ( var (
h = makeTrinodeHistory() h = makeTrienodeHistory()
freezer, _ = rawdb.NewTrienodeFreezer(t.TempDir(), false, false) freezer, _ = rawdb.NewTrienodeFreezer(t.TempDir(), false, false)
) )
defer freezer.Close() defer freezer.Close()
@ -523,7 +536,7 @@ func TestTrienodeHistoryReaderNilKey(t *testing.T) {
// TestTrienodeHistoryReaderIterator tests the iterator functionality // TestTrienodeHistoryReaderIterator tests the iterator functionality
func TestTrienodeHistoryReaderIterator(t *testing.T) { func TestTrienodeHistoryReaderIterator(t *testing.T) {
h := makeTrinodeHistory() h := makeTrienodeHistory()
// Count expected entries // Count expected entries
expectedCount := 0 expectedCount := 0
@ -614,7 +627,7 @@ func TestSharedLen(t *testing.T) {
// TestDecodeHeaderCorruptedData tests decodeHeader with corrupted data // TestDecodeHeaderCorruptedData tests decodeHeader with corrupted data
func TestDecodeHeaderCorruptedData(t *testing.T) { func TestDecodeHeaderCorruptedData(t *testing.T) {
// Create valid header data first // Create valid header data first
h := makeTrinodeHistory() h := makeTrienodeHistory()
header, _, _, _ := h.encode() header, _, _, _ := h.encode()
// Test with empty header // Test with empty header
@ -661,7 +674,7 @@ func TestDecodeHeaderCorruptedData(t *testing.T) {
// TestDecodeSingleCorruptedData tests decodeSingle with corrupted data // TestDecodeSingleCorruptedData tests decodeSingle with corrupted data
func TestDecodeSingleCorruptedData(t *testing.T) { func TestDecodeSingleCorruptedData(t *testing.T) {
h := makeTrinodeHistory() h := makeTrienodeHistory()
_, keySection, _, _ := h.encode() _, keySection, _, _ := h.encode()
// Test with empty key section // Test with empty key section