From 8f9c277fe96227d95eefb5219fda4ab2f39cdb3c Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Tue, 27 May 2025 11:45:49 +0800 Subject: [PATCH] triedb/pathdb: update --- triedb/pathdb/lookup.go | 8 ++++++++ triedb/pathdb/reader.go | 16 +++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/triedb/pathdb/lookup.go b/triedb/pathdb/lookup.go index 5326989f47..d4ec6493c6 100644 --- a/triedb/pathdb/lookup.go +++ b/triedb/pathdb/lookup.go @@ -202,6 +202,10 @@ func (l *lookup) removeLayer(diff *diffLayer) error { for i := 0; i < len(list); i++ { if list[i] == state { if i == 0 { + // Remove the first element by shifting the slice forward. + // Pros: zero-copy. + // Cons: may retain large backing array, causing memory leaks. + // Mitigation: release the array if capacity exceeds threshold. list = list[1:] if cap(list) > 1024 { list = append(make([]common.Hash, 0, len(list)), list...) @@ -241,6 +245,10 @@ func (l *lookup) removeLayer(diff *diffLayer) error { for i := 0; i < len(list); i++ { if list[i] == state { if i == 0 { + // Remove the first element by shifting the slice forward. + // Pros: zero-copy. + // Cons: may retain large backing array, causing memory leaks. + // Mitigation: release the array if capacity exceeds threshold. list = list[1:] if cap(list) > 1024 { list = append(make([]common.Hash, 0, len(list)), list...) diff --git a/triedb/pathdb/reader.go b/triedb/pathdb/reader.go index 9a8b970cc9..bc72db34e3 100644 --- a/triedb/pathdb/reader.go +++ b/triedb/pathdb/reader.go @@ -103,7 +103,12 @@ func (r *reader) AccountRLP(hash common.Hash) ([]byte, error) { } // If the located layer is stale, fall back to the slow path to retrieve // the account data. This is an edge case where the located layer is the - // disk layer, and it becomes stale within a very short time window. + // disk layer (e.g., the requested account was not changed in all the diff + // layers), and it becomes stale within a very short time window. + // + // This fallback mechanism is essential, because the traversal starts from + // the entry point layer and goes down, the staleness of the disk layer does + // not affect the result unless the entry point layer is also stale. blob, err := l.account(hash, 0) if errors.Is(err, errSnapshotStale) { return r.layer.account(hash, 0) @@ -146,8 +151,13 @@ func (r *reader) Storage(accountHash, storageHash common.Hash) ([]byte, error) { return nil, err } // If the located layer is stale, fall back to the slow path to retrieve - // the account data. This is an edge case where the located layer is the - // disk layer, and it becomes stale within a very short time window. + // the storage data. This is an edge case where the located layer is the + // disk layer (e.g., the requested account was not changed in all the diff + // layers), and it becomes stale within a very short time window. + // + // This fallback mechanism is essential, because the traversal starts from + // the entry point layer and goes down, the staleness of the disk layer does + // not affect the result unless the entry point layer is also stale. blob, err := l.storage(accountHash, storageHash, 0) if errors.Is(err, errSnapshotStale) { return r.layer.storage(accountHash, storageHash, 0)