From 1a5a479c4e4a6d06e56f064ed8a03b635ff0d8c2 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 28 Nov 2023 13:21:11 +0100 Subject: [PATCH] core/state: rewrite trie prefetcher to provide witness for snapshot-based execution --- core/blockchain_test.go | 3 ++- core/state/trie_prefetcher.go | 15 +++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 81ad4fb441..03885472e7 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -4766,7 +4766,8 @@ func testIncrementSlotAcrossManyBlocks(t *testing.T, scheme string) { }) // Import the canonical chain cache := DefaultCacheConfigWithScheme(scheme) - cache.SnapshotLimit = 0 // disable snapshot + cache.SnapshotLimit = 0 // disable snapshot + cache.SnapshotLimit = 500 // enable snapshot chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), cache, gspec, nil, engine, vm.Config{ Tracer: logger.NewJSONLogger(nil, os.Stdout), }, nil, nil) diff --git a/core/state/trie_prefetcher.go b/core/state/trie_prefetcher.go index f6972ad5c8..716969e2c1 100644 --- a/core/state/trie_prefetcher.go +++ b/core/state/trie_prefetcher.go @@ -167,14 +167,13 @@ func (p *triePrefetcher) trie(owner common.Hash, root common.Hash) Trie { p.deliveryMissMeter.Mark(1) return nil } - // Wait for the fether to finish + // Wait for the fetcher to finish fetcher.wait() // safe to do multiple times if fetcher.trie == nil { p.deliveryMissMeter.Mark(1) return nil } - trie := fetcher.db.CopyTrie(fetcher.trie) - return trie + return fetcher.db.CopyTrie(fetcher.trie) } // used marks a batch of state items used to allow creating statistics as to @@ -205,11 +204,11 @@ type subfetcher struct { addr common.Address // Address of the account that the trie belongs to trie Trie // Trie being populated with nodes - tasks [][]byte // Items queued up for retrieval - lock sync.Mutex // Lock protecting the task queue + tasks [][]byte // Items queued up for retrieval + lock sync.Mutex // Lock protecting the task queue + closing bool // set to true if the subfetcher is closing wake chan struct{} // Wake channel if a new task is scheduled - stop chan struct{} // Channel to interrupt processing term chan struct{} // Channel to signal interruption seen map[string]struct{} // Tracks the entries already loaded @@ -249,6 +248,10 @@ func (sf *subfetcher) schedule(keys [][]byte) { func (sf *subfetcher) wait() { // Signal termination by nil tasks sf.lock.Lock() + if sf.closing { + return // already exiting + } + sf.closing = true sf.tasks = nil sf.lock.Unlock() // Notify the prefetcher. The wake-chan is buffered, so this is async.