diff --git a/core/state/reader_eip_7928.go b/core/state/reader_eip_7928.go index 4af72959a7..ff315ac5eb 100644 --- a/core/state/reader_eip_7928.go +++ b/core/state/reader_eip_7928.go @@ -16,6 +16,14 @@ package state +import ( + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/types/bal" +) + // The EIP27928 reader utilizes a hierarchical architecture to optimize state // access during block execution: // @@ -37,14 +45,7 @@ package state // for the entire block. // // The architecture can be illustrated by the diagram below: - -// [ Block Level Read List ] <────────────────┐ -// ▲ │ ( Aggregate ) -// │ │ -// ┌───────┴───────┐ ┌───────┴───────┐ -// │ readerTracker │ │ readerTracker │ (State read tracking) -// └───────┬───────┘ └───────┬───────┘ -// │ │ +// // ┌──────────────┴──────────────┐ ┌──────────────┴──────────────┐ // │ ReaderWithBlockLevelAL │ │ ReaderWithBlockLevelAL │ // │ (Pre-state + Mutations) │ │ (Pre-state + Mutations) │ @@ -68,15 +69,6 @@ package state // Instead, it directly utilizes the readerTracker, wrapped around the // base reader, to construct the access list. -import ( - "maps" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/types/bal" -) - type fetchTask struct { addr common.Address slots []common.Hash @@ -94,6 +86,7 @@ type prefetchStateReader struct { closeOnce sync.Once } +// nolint:unused func newPrefetchStateReader(reader StateReader, accessList map[common.Address][]common.Hash, nThreads int) *prefetchStateReader { tasks := make([]*fetchTask, 0, len(accessList)) for addr, slots := range accessList { @@ -252,75 +245,3 @@ func (r *ReaderWithBlockLevelAccessList) Code(addr common.Address, codeHash comm func (r *ReaderWithBlockLevelAccessList) CodeSize(addr common.Address, codeHash common.Hash) (int, error) { panic("implement me") } - -// StorageAccessList represents a set of storage slots accessed within an account. -type StorageAccessList map[common.Hash]struct{} - -// StateAccessList maps account addresses to their respective accessed storage slots. -type StateAccessList map[common.Address]StorageAccessList - -// Merge merges the entries from the other StateAccessList into the receiver. -func (s StateAccessList) Merge(other StateAccessList) { - for addr, otherSlots := range other { - slots, exists := s[addr] - if !exists { - s[addr] = otherSlots - continue - } - maps.Copy(slots, otherSlots) - } -} - -// StateReaderTracker defines the capability to retrieve the access footprint -// recorded during state reading operations. -type StateReaderTracker interface { - GetStateAccessList() StateAccessList -} - -type readerTracker struct { - Reader - access StateAccessList - lock sync.RWMutex -} - -func newReaderTracker(reader Reader) *readerTracker { - return &readerTracker{ - Reader: reader, - access: make(StateAccessList), - } -} - -// Account implements StateReader, tracking the accessed address locally. -func (r *readerTracker) Account(addr common.Address) (*types.StateAccount, error) { - r.lock.Lock() - defer r.lock.Unlock() - - _, exists := r.access[addr] - if !exists { - r.access[addr] = make(StorageAccessList) - } - return r.Reader.Account(addr) -} - -// Storage implements StateReader, tracking the accessed slot identifier locally. -func (r *readerTracker) Storage(addr common.Address, slot common.Hash) (common.Hash, error) { - r.lock.Lock() - defer r.lock.Unlock() - - list, exists := r.access[addr] - if !exists { - list = make(StorageAccessList) - r.access[addr] = list - } - list[slot] = struct{}{} - - return r.Reader.Storage(addr, slot) -} - -// GetStateAccessList implements StateReaderTracker, returning the access footprint. -func (r *readerTracker) GetStateAccessList() StateAccessList { - r.lock.RLock() - defer r.lock.RUnlock() - - return r.access -} diff --git a/core/state/reader_eip_7928_test.go b/core/state/reader_eip_7928_test.go index 409f50a347..b2d432258c 100644 --- a/core/state/reader_eip_7928_test.go +++ b/core/state/reader_eip_7928_test.go @@ -18,7 +18,6 @@ package state import ( "fmt" - "maps" "math/rand" "sync" "testing" @@ -144,58 +143,3 @@ func TestPrefetchReader(t *testing.T) { } } } - -func makeFakeSlots(n int) map[common.Hash]struct{} { - slots := make(map[common.Hash]struct{}) - for i := 0; i < n; i++ { - slots[testrand.Hash()] = struct{}{} - } - return slots -} - -type noopStateReader struct{} - -func (r *noopStateReader) Account(addr common.Address) (*types.StateAccount, error) { return nil, nil } -func (r *noopStateReader) Storage(addr common.Address, slot common.Hash) (common.Hash, error) { - return common.Hash{}, nil -} - -type noopCodeReader struct{} - -func (r *noopCodeReader) Has(addr common.Address, codeHash common.Hash) bool { return false } - -func (r *noopCodeReader) Code(addr common.Address, codeHash common.Hash) []byte { - return nil -} - -func (r *noopCodeReader) CodeSize(addr common.Address, codeHash common.Hash) int { - return 0 -} - -func TestReaderWithTracker(t *testing.T) { - var r Reader = newReaderTracker(newReader(&noopCodeReader{}, &noopStateReader{})) - - accesses := map[common.Address]map[common.Hash]struct{}{ - testrand.Address(): makeFakeSlots(10), - testrand.Address(): makeFakeSlots(0), - } - for addr, slots := range accesses { - r.Account(addr) - for slot := range slots { - r.Storage(addr, slot) - } - } - got := r.(StateReaderTracker).GetStateAccessList() - if len(got) != len(accesses) { - t.Fatalf("Unexpected access list, want: %d, got: %d", len(accesses), len(got)) - } - for addr, slots := range got { - entry, ok := accesses[addr] - if !ok { - t.Fatal("Unexpected access list") - } - if !maps.Equal(slots, entry) { - t.Fatal("Unexpected slots") - } - } -}