core/state, core/tracing: add state read hooks

This commit is contained in:
Gary Rong 2025-10-09 15:09:08 +08:00 committed by Jared Wasinger
parent af34c01b90
commit 7410413eec
3 changed files with 51 additions and 6 deletions

View file

@ -53,22 +53,37 @@ func (s *hookedStateDB) CreateContract(addr common.Address) {
} }
func (s *hookedStateDB) GetBalance(addr common.Address) *uint256.Int { func (s *hookedStateDB) GetBalance(addr common.Address) *uint256.Int {
if s.hooks.OnAccountRead != nil {
s.hooks.OnAccountRead(addr)
}
return s.inner.GetBalance(addr) return s.inner.GetBalance(addr)
} }
func (s *hookedStateDB) GetNonce(addr common.Address) uint64 { func (s *hookedStateDB) GetNonce(addr common.Address) uint64 {
if s.hooks.OnAccountRead != nil {
s.hooks.OnAccountRead(addr)
}
return s.inner.GetNonce(addr) return s.inner.GetNonce(addr)
} }
func (s *hookedStateDB) GetCodeHash(addr common.Address) common.Hash { func (s *hookedStateDB) GetCodeHash(addr common.Address) common.Hash {
if s.hooks.OnAccountRead != nil {
s.hooks.OnAccountRead(addr)
}
return s.inner.GetCodeHash(addr) return s.inner.GetCodeHash(addr)
} }
func (s *hookedStateDB) GetCode(addr common.Address) []byte { func (s *hookedStateDB) GetCode(addr common.Address) []byte {
if s.hooks.OnAccountRead != nil {
s.hooks.OnAccountRead(addr)
}
return s.inner.GetCode(addr) return s.inner.GetCode(addr)
} }
func (s *hookedStateDB) GetCodeSize(addr common.Address) int { func (s *hookedStateDB) GetCodeSize(addr common.Address) int {
if s.hooks.OnAccountRead != nil {
s.hooks.OnAccountRead(addr)
}
return s.inner.GetCodeSize(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) { 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) return s.inner.GetStateAndCommittedState(addr, hash)
} }
func (s *hookedStateDB) GetState(addr common.Address, hash common.Hash) common.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) return s.inner.GetState(addr, hash)
} }
func (s *hookedStateDB) GetStorageRoot(addr common.Address) common.Hash { func (s *hookedStateDB) GetStorageRoot(addr common.Address) common.Hash {
if s.hooks.OnAccountRead != nil {
s.hooks.OnAccountRead(addr)
}
return s.inner.GetStorageRoot(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 { func (s *hookedStateDB) HasSelfDestructed(addr common.Address) bool {
if s.hooks.OnAccountRead != nil {
s.hooks.OnAccountRead(addr)
}
return s.inner.HasSelfDestructed(addr) return s.inner.HasSelfDestructed(addr)
} }
func (s *hookedStateDB) Exist(addr common.Address) bool { func (s *hookedStateDB) Exist(addr common.Address) bool {
if s.hooks.OnAccountRead != nil {
s.hooks.OnAccountRead(addr)
}
return s.inner.Exist(addr) return s.inner.Exist(addr)
} }
func (s *hookedStateDB) Empty(addr common.Address) bool { func (s *hookedStateDB) Empty(addr common.Address) bool {
if s.hooks.OnAccountRead != nil {
s.hooks.OnAccountRead(addr)
}
return s.inner.Empty(addr) return s.inner.Empty(addr)
} }

View file

@ -194,6 +194,12 @@ type (
// LogHook is called when a log is emitted. // LogHook is called when a log is emitted.
LogHook = func(log *types.Log) 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 is called when EVM reads the blockhash of a block.
BlockHashReadHook = func(blockNumber uint64, hash common.Hash) BlockHashReadHook = func(blockNumber uint64, hash common.Hash)
) )
@ -222,7 +228,7 @@ type Hooks struct {
OnPreTxExecutionDone func() // called after pre-tx system contracts are invoked OnPreTxExecutionDone func() // called after pre-tx system contracts are invoked
OnBlockFinalization func() // called after post-tx system contracts and consensus finalization are invoked OnBlockFinalization func() // called after post-tx system contracts and consensus finalization are invoked
// State events // State mutation events
OnBalanceChange BalanceChangeHook OnBalanceChange BalanceChangeHook
OnNonceChange NonceChangeHook OnNonceChange NonceChangeHook
OnNonceChangeV2 NonceChangeHookV2 OnNonceChangeV2 NonceChangeHookV2
@ -231,9 +237,10 @@ type Hooks struct {
OnStorageChange StorageChangeHook OnStorageChange StorageChangeHook
OnLog LogHook OnLog LogHook
OnSelfDestructChange SelfDestructHook OnSelfDestructChange SelfDestructHook
//State read events
OnColdStorageRead ColdStorageReadHook // State access events
OnColdAccountRead ColdAccountReadHook OnAccountRead AccountReadHook
OnStorageRead StorageReadHook
// Block hash read // Block hash read
OnBlockHashRead BlockHashReadHook OnBlockHashRead BlockHashReadHook

View file

@ -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) { 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 { if t.storage == nil {
t.storage = make(map[common.Hash]common.Hash) 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) { func TestJournalIntegration(t *testing.T) {
tr := &testTracer{t: 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 { if err != nil {
t.Fatalf("failed to wrap test tracer: %v", err) t.Fatalf("failed to wrap test tracer: %v", err)
} }