From 7410413eec63cf8f833600693da5767c92512820 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Thu, 9 Oct 2025 15:09:08 +0800 Subject: [PATCH] core/state, core/tracing: add state read hooks --- core/state/statedb_hooked.go | 33 +++++++++++++++++++++++++++++++++ core/tracing/hooks.go | 15 +++++++++++---- core/tracing/journal_test.go | 9 +++++++-- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go index b693797908..11f43df4b3 100644 --- a/core/state/statedb_hooked.go +++ b/core/state/statedb_hooked.go @@ -53,22 +53,37 @@ func (s *hookedStateDB) CreateContract(addr common.Address) { } func (s *hookedStateDB) GetBalance(addr common.Address) *uint256.Int { + if s.hooks.OnAccountRead != nil { + s.hooks.OnAccountRead(addr) + } return s.inner.GetBalance(addr) } func (s *hookedStateDB) GetNonce(addr common.Address) uint64 { + if s.hooks.OnAccountRead != nil { + s.hooks.OnAccountRead(addr) + } return s.inner.GetNonce(addr) } func (s *hookedStateDB) GetCodeHash(addr common.Address) common.Hash { + if s.hooks.OnAccountRead != nil { + s.hooks.OnAccountRead(addr) + } return s.inner.GetCodeHash(addr) } func (s *hookedStateDB) GetCode(addr common.Address) []byte { + if s.hooks.OnAccountRead != nil { + s.hooks.OnAccountRead(addr) + } return s.inner.GetCode(addr) } func (s *hookedStateDB) GetCodeSize(addr common.Address) int { + if s.hooks.OnAccountRead != nil { + s.hooks.OnAccountRead(addr) + } return s.inner.GetCodeSize(addr) } @@ -85,14 +100,23 @@ func (s *hookedStateDB) GetRefund() uint64 { } func (s *hookedStateDB) GetStateAndCommittedState(addr common.Address, hash common.Hash) (common.Hash, common.Hash) { + if s.hooks.OnStorageRead != nil { + s.hooks.OnStorageRead(addr, hash) + } return s.inner.GetStateAndCommittedState(addr, hash) } func (s *hookedStateDB) GetState(addr common.Address, hash common.Hash) common.Hash { + if s.hooks.OnStorageRead != nil { + s.hooks.OnStorageRead(addr, hash) + } return s.inner.GetState(addr, hash) } func (s *hookedStateDB) GetStorageRoot(addr common.Address) common.Hash { + if s.hooks.OnAccountRead != nil { + s.hooks.OnAccountRead(addr) + } return s.inner.GetStorageRoot(addr) } @@ -105,14 +129,23 @@ func (s *hookedStateDB) SetTransientState(addr common.Address, key, value common } func (s *hookedStateDB) HasSelfDestructed(addr common.Address) bool { + if s.hooks.OnAccountRead != nil { + s.hooks.OnAccountRead(addr) + } return s.inner.HasSelfDestructed(addr) } func (s *hookedStateDB) Exist(addr common.Address) bool { + if s.hooks.OnAccountRead != nil { + s.hooks.OnAccountRead(addr) + } return s.inner.Exist(addr) } func (s *hookedStateDB) Empty(addr common.Address) bool { + if s.hooks.OnAccountRead != nil { + s.hooks.OnAccountRead(addr) + } return s.inner.Empty(addr) } diff --git a/core/tracing/hooks.go b/core/tracing/hooks.go index 3078d607e5..789436c5b8 100644 --- a/core/tracing/hooks.go +++ b/core/tracing/hooks.go @@ -194,6 +194,12 @@ type ( // LogHook is called when a log is emitted. LogHook = func(log *types.Log) + // AccountReadHook is called when the account is accessed. + AccountReadHook = func(addr common.Address) + + // StorageReadHook is called when the storage slot is accessed. + StorageReadHook = func(addr common.Address, slot common.Hash) + // BlockHashReadHook is called when EVM reads the blockhash of a block. BlockHashReadHook = func(blockNumber uint64, hash common.Hash) ) @@ -222,7 +228,7 @@ type Hooks struct { OnPreTxExecutionDone func() // called after pre-tx system contracts are invoked OnBlockFinalization func() // called after post-tx system contracts and consensus finalization are invoked - // State events + // State mutation events OnBalanceChange BalanceChangeHook OnNonceChange NonceChangeHook OnNonceChangeV2 NonceChangeHookV2 @@ -231,9 +237,10 @@ type Hooks struct { OnStorageChange StorageChangeHook OnLog LogHook OnSelfDestructChange SelfDestructHook - //State read events - OnColdStorageRead ColdStorageReadHook - OnColdAccountRead ColdAccountReadHook + + // State access events + OnAccountRead AccountReadHook + OnStorageRead StorageReadHook // Block hash read OnBlockHashRead BlockHashReadHook diff --git a/core/tracing/journal_test.go b/core/tracing/journal_test.go index e00447f5f3..9f9fa27565 100644 --- a/core/tracing/journal_test.go +++ b/core/tracing/journal_test.go @@ -63,7 +63,7 @@ func (t *testTracer) OnCodeChangeV2(addr common.Address, prevCodeHash common.Has } func (t *testTracer) OnStorageChange(addr common.Address, slot common.Hash, prev common.Hash, new common.Hash) { - t.t.Logf("OnStorageCodeChange(%v, %v, %v -> %v)", addr, slot, prev, new) + t.t.Logf("OnStorageChange(%v, %v, %v -> %v)", addr, slot, prev, new) if t.storage == nil { t.storage = make(map[common.Hash]common.Hash) } @@ -76,7 +76,12 @@ func (t *testTracer) OnStorageChange(addr common.Address, slot common.Hash, prev func TestJournalIntegration(t *testing.T) { tr := &testTracer{t: t} - wr, err := WrapWithJournal(&Hooks{OnBalanceChange: tr.OnBalanceChange, OnNonceChange: tr.OnNonceChange, OnCodeChange: tr.OnCodeChange, OnStorageChange: tr.OnStorageChange}) + wr, err := WrapWithJournal(&Hooks{ + OnBalanceChange: tr.OnBalanceChange, + OnNonceChange: tr.OnNonceChange, + OnCodeChange: tr.OnCodeChange, + OnStorageChange: tr.OnStorageChange, + }) if err != nil { t.Fatalf("failed to wrap test tracer: %v", err) }