mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 20:56:42 +00:00
core: track system contract executions separately
Extend the unique code execution tracking to distinguish between system contract calls (EIP-4788 beacon root, EIP-2935 history storage, EIP-7002 withdrawal queue, EIP-7251 consolidation queue) and user contract calls. The MarkCodeExecuted method now takes an isSystem parameter to track system contracts separately. This is useful for understanding block execution statistics, as system contracts are called automatically by the protocol at the start of each block. The slow block log now shows "Contracts executed: N (M system)" to make it clear how many of the executed contracts were system calls.
This commit is contained in:
parent
be2d43090c
commit
b9a50aeadb
6 changed files with 26 additions and 11 deletions
|
|
@ -2192,6 +2192,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
|
|||
stats.UniqueAccountsAccessed = statedb.UniqueAccountsAccessed()
|
||||
stats.UniqueStorageAccessed = statedb.UniqueStorageAccessed()
|
||||
stats.UniqueCodeExecuted = statedb.UniqueCodeExecuted()
|
||||
stats.SystemCodeExecuted = statedb.SystemCodeExecuted()
|
||||
|
||||
stats.Execution = ptime - (statedb.AccountReads + statedb.StorageReads + statedb.CodeReads) // The time spent on EVM processing
|
||||
stats.Validation = vtime - (statedb.AccountHashes + statedb.AccountUpdates + statedb.StorageUpdates) // The time spent on block validation
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ type ExecuteStats struct {
|
|||
UniqueAccountsAccessed int // Number of unique accounts accessed
|
||||
UniqueStorageAccessed int // Number of unique storage slots accessed
|
||||
UniqueCodeExecuted int // Number of unique contracts executed
|
||||
SystemCodeExecuted int // Number of unique system contracts executed (subset of UniqueCodeExecuted)
|
||||
|
||||
Execution time.Duration // Time spent on the EVM execution
|
||||
Validation time.Duration // Time spent on the block validation
|
||||
|
|
@ -132,7 +133,7 @@ State read: %v
|
|||
Unique state access:
|
||||
Accounts: %d
|
||||
Storage slots: %d
|
||||
Contracts executed: %d
|
||||
Contracts executed: %d (%d system)
|
||||
|
||||
State hash: %v
|
||||
Account hash: %v
|
||||
|
|
@ -158,7 +159,7 @@ DB write: %v
|
|||
// Unique state access
|
||||
s.UniqueAccountsAccessed,
|
||||
s.UniqueStorageAccessed,
|
||||
s.UniqueCodeExecuted,
|
||||
s.UniqueCodeExecuted, s.SystemCodeExecuted,
|
||||
|
||||
// State hash
|
||||
common.PrettyDuration(s.AccountHashes+s.AccountUpdates+s.StorageUpdates+max(s.AccountCommits, s.StorageCommits)),
|
||||
|
|
|
|||
|
|
@ -163,7 +163,8 @@ type StateDB struct {
|
|||
CodeBytesRead int64 // Total bytes of contract code read during the state transition
|
||||
|
||||
// Unique contracts executed tracking (set of code hashes executed during the state transition)
|
||||
executedCodes map[common.Hash]struct{}
|
||||
executedCodes map[common.Hash]struct{}
|
||||
systemExecutedCodes map[common.Hash]struct{} // Subset of executedCodes that are system calls
|
||||
}
|
||||
|
||||
// New creates a new state from a given trie.
|
||||
|
|
@ -191,6 +192,7 @@ func NewWithReader(root common.Hash, db Database, reader Reader) (*StateDB, erro
|
|||
accessList: newAccessList(),
|
||||
transientStorage: newTransientStorage(),
|
||||
executedCodes: make(map[common.Hash]struct{}),
|
||||
systemExecutedCodes: make(map[common.Hash]struct{}),
|
||||
}
|
||||
if db.TrieDB().IsVerkle() {
|
||||
sdb.accessEvents = NewAccessEvents(db.PointCache())
|
||||
|
|
@ -386,7 +388,8 @@ func (s *StateDB) GetCodeHash(addr common.Address) common.Hash {
|
|||
|
||||
// MarkCodeExecuted records that a contract's code was executed.
|
||||
// This is used for metrics tracking to count unique contracts executed.
|
||||
func (s *StateDB) MarkCodeExecuted(codeHash common.Hash) {
|
||||
// The isSystem parameter indicates if this is a system call (e.g., EIP-4788 beacon root).
|
||||
func (s *StateDB) MarkCodeExecuted(codeHash common.Hash, isSystem bool) {
|
||||
if codeHash == types.EmptyCodeHash || codeHash == (common.Hash{}) {
|
||||
return
|
||||
}
|
||||
|
|
@ -394,6 +397,9 @@ func (s *StateDB) MarkCodeExecuted(codeHash common.Hash) {
|
|||
return // Skip tracking for state copies (e.g., prefetcher)
|
||||
}
|
||||
s.executedCodes[codeHash] = struct{}{}
|
||||
if isSystem {
|
||||
s.systemExecutedCodes[codeHash] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// UniqueCodeExecuted returns the number of unique contract codes executed.
|
||||
|
|
@ -401,6 +407,12 @@ func (s *StateDB) UniqueCodeExecuted() int {
|
|||
return len(s.executedCodes)
|
||||
}
|
||||
|
||||
// SystemCodeExecuted returns the number of unique system contract codes executed
|
||||
// (e.g., EIP-4788 beacon root, EIP-2935 history storage, etc.).
|
||||
func (s *StateDB) SystemCodeExecuted() int {
|
||||
return len(s.systemExecutedCodes)
|
||||
}
|
||||
|
||||
// UniqueAccountsAccessed returns the number of unique accounts accessed during the state transition.
|
||||
func (s *StateDB) UniqueAccountsAccessed() int {
|
||||
return len(s.stateObjects)
|
||||
|
|
|
|||
|
|
@ -298,6 +298,6 @@ func (s *hookedStateDB) Inner() *StateDB {
|
|||
}
|
||||
|
||||
// MarkCodeExecuted records that a contract's code was executed.
|
||||
func (s *hookedStateDB) MarkCodeExecuted(codeHash common.Hash) {
|
||||
s.inner.MarkCodeExecuted(codeHash)
|
||||
func (s *hookedStateDB) MarkCodeExecuted(codeHash common.Hash, isSystem bool) {
|
||||
s.inner.MarkCodeExecuted(codeHash, isSystem)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
|||
codeHash := evm.resolveCodeHash(addr)
|
||||
contract.SetCallCode(codeHash, code)
|
||||
// Track unique contract execution for metrics
|
||||
evm.StateDB.MarkCodeExecuted(codeHash)
|
||||
evm.StateDB.MarkCodeExecuted(codeHash, contract.IsSystemCall)
|
||||
ret, err = evm.Run(contract, input, false)
|
||||
gas = contract.Gas
|
||||
}
|
||||
|
|
@ -358,7 +358,7 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
|
|||
codeHash := evm.resolveCodeHash(addr)
|
||||
contract.SetCallCode(codeHash, evm.resolveCode(addr))
|
||||
// Track unique contract execution for metrics
|
||||
evm.StateDB.MarkCodeExecuted(codeHash)
|
||||
evm.StateDB.MarkCodeExecuted(codeHash, isSystemCall(caller))
|
||||
ret, err = evm.Run(contract, input, false)
|
||||
gas = contract.Gas
|
||||
}
|
||||
|
|
@ -405,7 +405,7 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
|
|||
codeHash := evm.resolveCodeHash(addr)
|
||||
contract.SetCallCode(codeHash, evm.resolveCode(addr))
|
||||
// Track unique contract execution for metrics
|
||||
evm.StateDB.MarkCodeExecuted(codeHash)
|
||||
evm.StateDB.MarkCodeExecuted(codeHash, isSystemCall(originCaller))
|
||||
ret, err = evm.Run(contract, input, false)
|
||||
gas = contract.Gas
|
||||
}
|
||||
|
|
@ -459,7 +459,7 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
|
|||
codeHash := evm.resolveCodeHash(addr)
|
||||
contract.SetCallCode(codeHash, evm.resolveCode(addr))
|
||||
// Track unique contract execution for metrics
|
||||
evm.StateDB.MarkCodeExecuted(codeHash)
|
||||
evm.StateDB.MarkCodeExecuted(codeHash, isSystemCall(caller))
|
||||
|
||||
// When an error was returned by the EVM or when setting the creation code
|
||||
// above we revert to the snapshot and consume any gas remaining. Additionally
|
||||
|
|
|
|||
|
|
@ -104,5 +104,6 @@ type StateDB interface {
|
|||
|
||||
// MarkCodeExecuted records that a contract's code was executed.
|
||||
// Used for metrics tracking to count unique contracts executed.
|
||||
MarkCodeExecuted(codeHash common.Hash)
|
||||
// The isSystem parameter indicates if this is a system call (e.g., EIP-4788).
|
||||
MarkCodeExecuted(codeHash common.Hash, isSystem bool)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue