use struct for tracing events

# Conflicts:
#	core/blockchain.go
#	core/state/state_object.go
#	core/state/statedb.go
This commit is contained in:
Sina Mahmoodi 2024-02-16 11:20:56 +01:00 committed by Matthieu Vachon
parent 8ec4560e17
commit 4df6904051
10 changed files with 83 additions and 34 deletions

View file

@ -192,7 +192,8 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
utils.Fatalf("Failed to create tracer %q: %v", name, err)
}
cfg.Eth.VMTracer = t
cfg.Eth.VMTracer = t.VMLogger
cfg.Eth.LiveLogger = t
}
}

View file

@ -2207,7 +2207,8 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
if err != nil {
Fatalf("Failed to create tracer %q: %v", name, err)
}
vmcfg.Tracer = t
vmcfg.LiveLogger = t
vmcfg.Tracer = t.VMLogger
}
}
// Disable transaction indexing/unindexing by default.

View file

@ -39,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/directory/live"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/syncx"
@ -284,7 +285,7 @@ type BlockChain struct {
processor Processor // Block transaction processor interface
forker *ForkChoice
vmConfig vm.Config
logger BlockchainLogger
logger *live.LiveLogger
}
// NewBlockChain returns a fully initialised block chain using information
@ -296,15 +297,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
}
// Open trie database with provided config
triedb := trie.NewDatabase(db, cacheConfig.triedbConfig())
var logger BlockchainLogger
if vmConfig.Tracer != nil {
l, ok := vmConfig.Tracer.(BlockchainLogger)
if ok {
logger = l
} else {
log.Warn("only extended tracers are supported for live mode")
}
}
// Setup the genesis block, commit the provided genesis specification
// to database if the genesis block is not present yet, or load the
// stored one from database.
@ -336,7 +329,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
futureBlocks: lru.NewCache[common.Hash, *types.Block](maxFutureBlocks),
engine: engine,
vmConfig: vmConfig,
logger: logger,
logger: vmConfig.LiveLogger,
}
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
bc.forker = NewForkChoice(bc, shouldPreserve)
@ -463,7 +456,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
}
}
if bc.logger != nil {
if bc.logger != nil && bc.logger.OnGenesisBlock != nil {
if block := bc.CurrentBlock(); block.Number.Uint64() == 0 {
alloc, err := getGenesisState(bc.db, block.Hash())
if err != nil {
@ -514,7 +507,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
}
rawdb.WriteChainConfig(db, genesisHash, chainConfig)
}
if bc.logger != nil {
if bc.logger != nil && bc.logger.OnBlockchainInit != nil {
bc.logger.OnBlockchainInit(chainConfig)
}
// Start tx indexer/unindexer if required.
@ -1819,7 +1812,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
return it.index, err
}
stats.processed++
if bc.logger != nil {
if bc.logger != nil && bc.logger.OnSkippedBlock != nil {
bc.logger.OnSkippedBlock(BlockEvent{
Block: block,
TD: bc.GetTd(block.ParentHash(), block.NumberU64()-1),
@ -1951,7 +1944,7 @@ type blockProcessingResult struct {
// processBlock executes and validates the given block. If there was no error
// it writes the block and associated state to database.
func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, start time.Time, setHead bool) (_ *blockProcessingResult, blockEndErr error) {
if bc.logger != nil {
if bc.logger != nil && bc.logger.OnBlockStart != nil {
td := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
bc.logger.OnBlockStart(BlockEvent{
Block: block,
@ -1959,6 +1952,8 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
Finalized: bc.CurrentFinalBlock(),
Safe: bc.CurrentSafeBlock(),
})
}
if bc.logger != nil && bc.logger.OnBlockEnd != nil {
defer func() {
bc.logger.OnBlockEnd(blockEndErr)
}()

View file

@ -239,7 +239,7 @@ func (s *stateObject) SetState(key, value common.Hash) {
key: key,
prevalue: prev,
})
if s.db.logger != nil {
if s.db.logger != nil && s.db.logger.OnStorageChange != nil {
s.db.logger.OnStorageChange(s.address, key, prev, value)
}
s.setState(key, value)
@ -430,7 +430,7 @@ func (s *stateObject) SetBalance(amount *big.Int, reason BalanceChangeReason) {
account: &s.address,
prev: new(big.Int).Set(s.data.Balance),
})
if s.db.logger != nil {
if s.db.logger != nil && s.db.logger.OnBalanceChange != nil {
s.db.logger.OnBalanceChange(s.address, s.Balance(), amount, reason)
}
s.setBalance(amount)
@ -510,7 +510,7 @@ func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
prevhash: s.CodeHash(),
prevcode: prevcode,
})
if s.db.logger != nil {
if s.db.logger != nil && s.db.logger.OnCodeChange != nil {
s.db.logger.OnCodeChange(s.address, common.BytesToHash(s.CodeHash()), prevcode, codeHash, code)
}
s.setCode(codeHash, code)
@ -527,7 +527,7 @@ func (s *stateObject) SetNonce(nonce uint64) {
account: &s.address,
prev: s.data.Nonce,
})
if s.db.logger != nil {
if s.db.logger != nil && s.db.logger.OnNonceChange != nil {
s.db.logger.OnNonceChange(s.address, s.data.Nonce, nonce)
}
s.setNonce(nonce)

View file

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers/directory/live"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
@ -77,7 +78,7 @@ type StateDB struct {
prefetcher *triePrefetcher
trie Trie
hasher crypto.KeccakState
logger StateLogger
logger *live.LiveLogger
snaps *snapshot.Tree // Nil if snapshot is not available
snap snapshot.Snapshot // Nil if snapshot is not available
@ -188,7 +189,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
}
// SetLogger sets the logger for account update hooks.
func (s *StateDB) SetLogger(l StateLogger) {
func (s *StateDB) SetLogger(l *live.LiveLogger) {
s.logger = l
}
@ -232,7 +233,7 @@ func (s *StateDB) AddLog(log *types.Log) {
log.TxHash = s.thash
log.TxIndex = uint(s.txIndex)
log.Index = s.logSize
if s.logger != nil {
if s.logger != nil && s.logger.OnLog != nil {
s.logger.OnLog(log)
}
s.logs[s.thash] = append(s.logs[s.thash], log)
@ -479,7 +480,7 @@ func (s *StateDB) SelfDestruct(addr common.Address) {
prev: stateObject.selfDestructed,
prevbalance: new(big.Int).Set(stateObject.Balance()),
})
if s.logger != nil && prev.Sign() > 0 {
if s.logger != nil && s.logger.OnBalanceChange != nil && prev.Sign() > 0 {
s.logger.OnBalanceChange(addr, prev, n, BalanceDecreaseSelfdestruct)
}
stateObject.markSelfdestructed()
@ -868,7 +869,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
obj.deleted = true
// If ether was sent to account post-selfdestruct it is burnt.
if bal := obj.Balance(); s.logger != nil && obj.selfDestructed && bal.Sign() != 0 {
if bal := obj.Balance(); s.logger != nil && s.logger.OnBalanceChange != nil && obj.selfDestructed && bal.Sign() != 0 {
s.logger.OnBalanceChange(obj.address, bal, new(big.Int), BalanceDecreaseSelfdestructBurn)
}
// We need to maintain account deletions explicitly (will remain

View file

@ -20,15 +20,17 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers/directory/live"
"github.com/ethereum/go-ethereum/log"
)
// Config are the configuration options for the Interpreter
type Config struct {
Tracer EVMLogger // Opcode logger
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
ExtraEips []int // Additional EIPS that are to be enabled
LiveLogger *live.LiveLogger
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
ExtraEips []int // Additional EIPS that are to be enabled
}
// ScopeContext contains the things that are per-call, such as stack and memory,

View file

@ -193,6 +193,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
vmConfig = vm.Config{
EnablePreimageRecording: config.EnablePreimageRecording,
Tracer: config.VMTracer,
LiveLogger: config.LiveLogger,
}
cacheConfig = &core.CacheConfig{
TrieCleanLimit: config.TrieCleanCache,

View file

@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/eth/tracers/directory/live"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/params"
@ -153,7 +154,8 @@ type Config struct {
EnablePreimageRecording bool
// Enables VM tracing
VMTracer vm.EVMLogger
VMTracer vm.EVMLogger
LiveLogger *live.LiveLogger
// Miscellaneous options
DocRoot string `toml:"-"`

View file

@ -3,11 +3,44 @@ package live
import (
"encoding/json"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
)
type ctorFunc func(config json.RawMessage) (core.BlockchainLogger, error)
type LiveLogger struct {
VMLogger vm.EVMLogger
/*
- Chain events -
*/
OnBlockchainInit func(chainConfig *params.ChainConfig)
// OnBlockStart is called before executing `block`.
// `td` is the total difficulty prior to `block`.
OnBlockStart func(event core.BlockEvent)
OnBlockEnd func(err error)
// OnSkippedBlock indicates a block was skipped during processing
// due to it being known previously. This can happen e.g. when recovering
// from a crash.
OnSkippedBlock func(event core.BlockEvent)
OnGenesisBlock func(genesis *types.Block, alloc core.GenesisAlloc)
/*
- State events -
*/
OnBalanceChange func(addr common.Address, prev, new *big.Int, reason state.BalanceChangeReason)
OnNonceChange func(addr common.Address, prev, new uint64)
OnCodeChange func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte)
OnStorageChange func(addr common.Address, slot common.Hash, prev, new common.Hash)
OnLog func(log *types.Log)
}
type ctorFunc func(config json.RawMessage) (*LiveLogger, error)
// Directory is the collection of tracers which can be used
// during normal block import operations.
@ -23,7 +56,7 @@ func (d *directory) Register(name string, f ctorFunc) {
}
// New instantiates a tracer by name.
func (d *directory) New(name string, config json.RawMessage) (core.BlockchainLogger, error) {
func (d *directory) New(name string, config json.RawMessage) (*LiveLogger, error) {
if f, ok := d.elems[name]; ok {
return f(config)
}

View file

@ -23,8 +23,21 @@ func init() {
// as soon as we have a real live tracer.
type noop struct{}
func newNoopTracer(_ json.RawMessage) (core.BlockchainLogger, error) {
return &noop{}, nil
func newNoopTracer(_ json.RawMessage) (*live.LiveLogger, error) {
t := &noop{}
return &live.LiveLogger{
VMLogger: t,
OnBlockchainInit: t.OnBlockchainInit,
OnBlockStart: t.OnBlockStart,
OnBlockEnd: t.OnBlockEnd,
OnSkippedBlock: t.OnSkippedBlock,
OnGenesisBlock: t.OnGenesisBlock,
OnBalanceChange: t.OnBalanceChange,
OnNonceChange: t.OnNonceChange,
OnCodeChange: t.OnCodeChange,
OnStorageChange: t.OnStorageChange,
OnLog: t.OnLog,
}, nil
}
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.