mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-12 01:41:36 +00:00
core/state: remove the reader tracker
This commit is contained in:
parent
91b3543b61
commit
121607dfab
2 changed files with 10 additions and 145 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue