mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 23:26:44 +00:00
rename tracer methods to On pattern
# Conflicts # core/vm/interpreter.go # eth/tracers/directory/noop.go # eth/tracers/js/goja.go # eth/tracers/live/noop.go # eth/tracers/logger/logger.go # eth/tracers/logger/logger_json.go # eth/tracers/native/4byte.go # eth/tracers/native/call.go # eth/tracers/native/call_flat.go # eth/tracers/native/mux.go
This commit is contained in:
parent
25a3a744c3
commit
03e48ee451
31 changed files with 206 additions and 281 deletions
|
|
@ -50,7 +50,7 @@ func blockTestCmd(ctx *cli.Context) error {
|
||||||
return errors.New("path-to-test argument required")
|
return errors.New("path-to-test argument required")
|
||||||
}
|
}
|
||||||
|
|
||||||
var tracer *tracing.LiveLogger
|
var tracer *tracing.Hooks
|
||||||
// Configure the EVM logger
|
// Configure the EVM logger
|
||||||
if ctx.Bool(MachineFlag.Name) {
|
if ctx.Bool(MachineFlag.Name) {
|
||||||
tracer = logger.NewJSONLogger(&logger.Config{
|
tracer = logger.NewJSONLogger(&logger.Config{
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
if vmConfig.Tracer != nil {
|
if vmConfig.Tracer != nil {
|
||||||
vmConfig.Tracer = tracer.LiveLogger
|
vmConfig.Tracer = tracer.Hooks
|
||||||
}
|
}
|
||||||
statedb.SetTxContext(tx.Hash(), txIndex)
|
statedb.SetTxContext(tx.Hash(), txIndex)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ func Transition(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
logger := logger.NewJSONLogger(logConfig, traceFile).Hooks()
|
logger := logger.NewJSONLogger(logConfig, traceFile).Hooks()
|
||||||
tracer := &directory.Tracer{
|
tracer := &directory.Tracer{
|
||||||
LiveLogger: logger,
|
Hooks: logger,
|
||||||
// JSONLogger streams out result to file.
|
// JSONLogger streams out result to file.
|
||||||
GetResult: func() (json.RawMessage, error) { return nil, nil },
|
GetResult: func() (json.RawMessage, error) { return nil, nil },
|
||||||
Stop: func(err error) {},
|
Stop: func(err error) {},
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tracer *tracing.LiveLogger
|
tracer *tracing.Hooks
|
||||||
debugLogger *logger.StructLogger
|
debugLogger *logger.StructLogger
|
||||||
statedb *state.StateDB
|
statedb *state.StateDB
|
||||||
chainConfig *params.ChainConfig
|
chainConfig *params.ChainConfig
|
||||||
|
|
|
||||||
|
|
@ -266,7 +266,7 @@ type BlockChain struct {
|
||||||
processor Processor // Block transaction processor interface
|
processor Processor // Block transaction processor interface
|
||||||
forker *ForkChoice
|
forker *ForkChoice
|
||||||
vmConfig vm.Config
|
vmConfig vm.Config
|
||||||
logger *tracing.LiveLogger
|
logger *tracing.Hooks
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockChain returns a fully initialised block chain using information
|
// NewBlockChain returns a fully initialised block chain using information
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ type StateDB struct {
|
||||||
prefetcher *triePrefetcher
|
prefetcher *triePrefetcher
|
||||||
trie Trie
|
trie Trie
|
||||||
hasher crypto.KeccakState
|
hasher crypto.KeccakState
|
||||||
logger *tracing.LiveLogger
|
logger *tracing.Hooks
|
||||||
snaps *snapshot.Tree // Nil if snapshot is not available
|
snaps *snapshot.Tree // Nil if snapshot is not available
|
||||||
snap snapshot.Snapshot // Nil if snapshot is not available
|
snap snapshot.Snapshot // Nil if snapshot is not available
|
||||||
|
|
||||||
|
|
@ -175,7 +175,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLogger sets the logger for account update hooks.
|
// SetLogger sets the logger for account update hooks.
|
||||||
func (s *StateDB) SetLogger(l *tracing.LiveLogger) {
|
func (s *StateDB) SetLogger(l *tracing.Hooks) {
|
||||||
s.logger = l
|
s.logger = l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
|
@ -141,7 +142,7 @@ type (
|
||||||
SkippedBlockHook = func(event BlockEvent)
|
SkippedBlockHook = func(event BlockEvent)
|
||||||
|
|
||||||
// GenesisBlockHook is called when the genesis block is being processed.
|
// GenesisBlockHook is called when the genesis block is being processed.
|
||||||
GenesisBlockHook = func(genesis *types.Block, alloc types.GenesisAlloc)
|
GenesisBlockHook = func(genesis *types.Block, alloc core.GenesisAlloc)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
- State events -
|
- State events -
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ func (c *Contract) Caller() common.Address {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseGas attempts the use gas and subtracts it and returns true on success
|
// UseGas attempts the use gas and subtracts it and returns true on success
|
||||||
func (c *Contract) UseGas(gas uint64, logger *tracing.LiveLogger, reason tracing.GasChangeReason) (ok bool) {
|
func (c *Contract) UseGas(gas uint64, logger *tracing.Hooks, reason tracing.GasChangeReason) (ok bool) {
|
||||||
if c.Gas < gas {
|
if c.Gas < gas {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ func ActivePrecompiles(rules params.Rules) []common.Address {
|
||||||
// - the returned bytes,
|
// - the returned bytes,
|
||||||
// - the _remaining_ gas,
|
// - the _remaining_ gas,
|
||||||
// - any error that occurred
|
// - any error that occurred
|
||||||
func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64, logger *tracing.LiveLogger) (ret []byte, remainingGas uint64, err error) {
|
func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64, logger *tracing.Hooks) (ret []byte, remainingGas uint64, err error) {
|
||||||
gasCost := p.RequiredGas(input)
|
gasCost := p.RequiredGas(input)
|
||||||
if suppliedGas < gasCost {
|
if suppliedGas < gasCost {
|
||||||
return nil, 0, ErrOutOfGas
|
return nil, 0, ErrOutOfGas
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import (
|
||||||
|
|
||||||
// Config are the configuration options for the Interpreter
|
// Config are the configuration options for the Interpreter
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Tracer *tracing.LiveLogger
|
Tracer *tracing.Hooks
|
||||||
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
|
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
|
||||||
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
|
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
|
||||||
ExtraEips []int // Additional EIPS that are to be enabled
|
ExtraEips []int // Additional EIPS that are to be enabled
|
||||||
|
|
@ -178,8 +178,8 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||||
res []byte // result of the opcode execution function
|
res []byte // result of the opcode execution function
|
||||||
debug = in.evm.Config.Tracer != nil
|
debug = in.evm.Config.Tracer != nil
|
||||||
)
|
)
|
||||||
// Don't move this deferred function, it's placed before the capturestate-deferred method,
|
// Don't move this deferred function, it's placed before the OnOpcode-deferred method,
|
||||||
// so that it get's executed _after_: the capturestate needs the stacks before
|
// so that it gets executed _after_: the OnOpcode needs the stacks before
|
||||||
// they are returned to the pools
|
// they are returned to the pools
|
||||||
defer func() {
|
defer func() {
|
||||||
returnStack(stack)
|
returnStack(stack)
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ type Config struct {
|
||||||
EnablePreimageRecording bool
|
EnablePreimageRecording bool
|
||||||
|
|
||||||
// Enables VM tracing
|
// Enables VM tracing
|
||||||
VMTracer *tracing.LiveLogger
|
VMTracer *tracing.Hooks
|
||||||
|
|
||||||
// Miscellaneous options
|
// Miscellaneous options
|
||||||
DocRoot string `toml:"-"`
|
DocRoot string `toml:"-"`
|
||||||
|
|
|
||||||
|
|
@ -937,8 +937,8 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *direc
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: big.NewInt(0)}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.LiveLogger, NoBaseFee: true})
|
vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: big.NewInt(0)}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
|
||||||
statedb.SetLogger(tracer.LiveLogger)
|
statedb.SetLogger(tracer.Hooks)
|
||||||
|
|
||||||
// Define a meaningful timeout of a single transaction trace
|
// Define a meaningful timeout of a single transaction trace
|
||||||
if config.Timeout != nil {
|
if config.Timeout != nil {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ctorFunc func(config json.RawMessage) (*tracing.LiveLogger, error)
|
type ctorFunc func(config json.RawMessage) (*tracing.Hooks, error)
|
||||||
|
|
||||||
// Directory is the collection of tracers which can be used
|
// Directory is the collection of tracers which can be used
|
||||||
// during normal block import operations.
|
// during normal block import operations.
|
||||||
|
|
@ -23,7 +23,7 @@ func (d *directory) Register(name string, f ctorFunc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New instantiates a tracer by name.
|
// New instantiates a tracer by name.
|
||||||
func (d *directory) New(name string, config json.RawMessage) (*tracing.LiveLogger, error) {
|
func (d *directory) New(name string, config json.RawMessage) (*tracing.Hooks, error) {
|
||||||
if f, ok := d.elems[name]; ok {
|
if f, ok := d.elems[name]; ok {
|
||||||
return f(config)
|
return f(config)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,15 +38,13 @@ func newNoopTracer(ctx *Context, _ json.RawMessage) (*Tracer, error) {
|
||||||
t := &NoopTracer{}
|
t := &NoopTracer{}
|
||||||
return &Tracer{
|
return &Tracer{
|
||||||
Hooks: &tracing.Hooks{
|
Hooks: &tracing.Hooks{
|
||||||
OnTxStart: t.CaptureTxStart,
|
OnTxStart: t.OnTxStart,
|
||||||
OnTxEnd: t.CaptureTxEnd,
|
OnTxEnd: t.OnTxEnd,
|
||||||
OnStart: t.CaptureStart,
|
OnEnter: t.OnEnter,
|
||||||
OnEnd: t.CaptureEnd,
|
OnExit: t.OnExit,
|
||||||
OnEnter: t.CaptureEnter,
|
OnOpcode: t.OnOpcode,
|
||||||
OnExit: t.CaptureExit,
|
OnFault: t.OnFault,
|
||||||
OnOpcode: t.CaptureState,
|
OnKeccakPreimage: t.OnKeccakPreimage,
|
||||||
OnFault: t.CaptureFault,
|
|
||||||
OnKeccakPreimage: t.CaptureKeccakPreimage,
|
|
||||||
OnGasChange: t.OnGasChange,
|
OnGasChange: t.OnGasChange,
|
||||||
OnBalanceChange: t.OnBalanceChange,
|
OnBalanceChange: t.OnBalanceChange,
|
||||||
OnNonceChange: t.OnNonceChange,
|
OnNonceChange: t.OnNonceChange,
|
||||||
|
|
@ -59,41 +57,26 @@ func newNoopTracer(ctx *Context, _ json.RawMessage) (*Tracer, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
func (t *NoopTracer) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
func (t *NoopTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
func (t *NoopTracer) OnFault(pc uint64, op tracing.OpCode, gas, cost uint64, _ tracing.OpContext, depth int, err error) {
|
||||||
func (t *NoopTracer) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
|
func (t *NoopTracer) OnKeccakPreimage(hash common.Hash, data []byte) {}
|
||||||
func (t *NoopTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaptureFault implements the EVMLogger interface to trace an execution fault.
|
|
||||||
func (t *NoopTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, _ tracing.OpContext, depth int, err error) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaptureKeccakPreimage is called during the KECCAK256 opcode.
|
|
||||||
func (t *NoopTracer) CaptureKeccakPreimage(hash common.Hash, data []byte) {}
|
|
||||||
|
|
||||||
// OnGasChange is called when gas is either consumed or refunded.
|
|
||||||
func (t *NoopTracer) OnGasChange(old, new uint64, reason tracing.GasChangeReason) {}
|
func (t *NoopTracer) OnGasChange(old, new uint64, reason tracing.GasChangeReason) {}
|
||||||
|
|
||||||
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
func (t *NoopTracer) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||||
func (t *NoopTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureExit is called when EVM exits a scope, even if the scope didn't
|
func (t *NoopTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
// execute any code.
|
|
||||||
func (t *NoopTracer) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*NoopTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (*NoopTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*NoopTracer) CaptureTxEnd(receipt *types.Receipt, err error) {}
|
func (*NoopTracer) OnTxEnd(receipt *types.Receipt, err error) {}
|
||||||
|
|
||||||
func (*NoopTracer) OnBalanceChange(a common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
|
func (*NoopTracer) OnBalanceChange(a common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ type Context struct {
|
||||||
// This involves a method to retrieve results and one to
|
// This involves a method to retrieve results and one to
|
||||||
// stop tracing.
|
// stop tracing.
|
||||||
type Tracer struct {
|
type Tracer struct {
|
||||||
*tracing.LiveLogger
|
*tracing.Hooks
|
||||||
GetResult func() (json.RawMessage, error)
|
GetResult func() (json.RawMessage, error)
|
||||||
// Stop terminates execution of the tracer at the first opportune moment.
|
// Stop terminates execution of the tracer at the first opportune moment.
|
||||||
Stop func(err error)
|
Stop func(err error)
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
||||||
t.Fatalf("failed to create call tracer: %v", err)
|
t.Fatalf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
statedb.SetLogger(tracer.LiveLogger)
|
statedb.SetLogger(tracer.Hooks)
|
||||||
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
|
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||||
|
|
@ -251,7 +251,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("failed to create call tracer: %v", err)
|
b.Fatalf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer.LiveLogger})
|
evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
|
||||||
snap := statedb.Snapshot()
|
snap := statedb.Snapshot()
|
||||||
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||||
if _, err = st.TransitionDb(); err != nil {
|
if _, err = st.TransitionDb(); err != nil {
|
||||||
|
|
@ -379,7 +379,7 @@ func TestInternals(t *testing.T) {
|
||||||
},
|
},
|
||||||
}, false, rawdb.HashScheme)
|
}, false, rawdb.HashScheme)
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
statedb.SetLogger(tc.tracer.LiveLogger)
|
statedb.SetLogger(tc.tracer.Hooks)
|
||||||
tx, err := types.SignNewTx(key, signer, &types.LegacyTx{
|
tx, err := types.SignNewTx(key, signer, &types.LegacyTx{
|
||||||
To: &to,
|
To: &to,
|
||||||
Value: big.NewInt(0),
|
Value: big.NewInt(0),
|
||||||
|
|
@ -393,7 +393,7 @@ func TestInternals(t *testing.T) {
|
||||||
Origin: origin,
|
Origin: origin,
|
||||||
GasPrice: tx.GasPrice(),
|
GasPrice: tx.GasPrice(),
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, txContext, statedb, config, vm.Config{Tracer: tc.tracer.LiveLogger})
|
evm := vm.NewEVM(context, txContext, statedb, config, vm.Config{Tracer: tc.tracer.Hooks})
|
||||||
msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0))
|
msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("test %v: failed to create message: %v", tc.name, err)
|
t.Fatalf("test %v: failed to create message: %v", tc.name, err)
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
|
||||||
return fmt.Errorf("failed to create call tracer: %v", err)
|
return fmt.Errorf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
statedb.SetLogger(tracer.LiveLogger)
|
statedb.SetLogger(tracer.Hooks)
|
||||||
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
|
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
|
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
|
||||||
t.Fatalf("failed to create call tracer: %v", err)
|
t.Fatalf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
statedb.SetLogger(tracer.LiveLogger)
|
statedb.SetLogger(tracer.Hooks)
|
||||||
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
|
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -214,23 +214,21 @@ func newJsTracer(code string, ctx *directory.Context, cfg json.RawMessage) (*dir
|
||||||
|
|
||||||
return &directory.Tracer{
|
return &directory.Tracer{
|
||||||
Hooks: &tracing.Hooks{
|
Hooks: &tracing.Hooks{
|
||||||
OnTxStart: t.CaptureTxStart,
|
OnTxStart: t.OnTxStart,
|
||||||
OnTxEnd: t.CaptureTxEnd,
|
OnTxEnd: t.OnTxEnd,
|
||||||
OnStart: t.CaptureStart,
|
OnEnter: t.OnEnter,
|
||||||
OnEnd: t.CaptureEnd,
|
OnExit: t.OnExit,
|
||||||
OnEnter: t.CaptureEnter,
|
OnOpcode: t.OnOpcode,
|
||||||
OnExit: t.CaptureExit,
|
OnFault: t.OnFault,
|
||||||
OnOpcode: t.CaptureState,
|
|
||||||
OnFault: t.CaptureFault,
|
|
||||||
},
|
},
|
||||||
GetResult: t.GetResult,
|
GetResult: t.GetResult,
|
||||||
Stop: t.Stop,
|
Stop: t.Stop,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureTxStart implements the Tracer interface and is invoked at the beginning of
|
// OnTxStart implements the Tracer interface and is invoked at the beginning of
|
||||||
// transaction processing.
|
// transaction processing.
|
||||||
func (t *jsTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (t *jsTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
t.env = env
|
t.env = env
|
||||||
// Need statedb access for db object
|
// Need statedb access for db object
|
||||||
db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf}
|
db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf}
|
||||||
|
|
@ -249,9 +247,9 @@ func (t *jsTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction,
|
||||||
t.ctx["gasPrice"] = gasPriceBig
|
t.ctx["gasPrice"] = gasPriceBig
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureTxEnd implements the Tracer interface and is invoked at the end of
|
// OnTxEnd implements the Tracer interface and is invoked at the end of
|
||||||
// transaction processing.
|
// transaction processing.
|
||||||
func (t *jsTracer) CaptureTxEnd(receipt *types.Receipt, err error) {
|
func (t *jsTracer) OnTxEnd(receipt *types.Receipt, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't override vm error
|
// Don't override vm error
|
||||||
if _, ok := t.ctx["error"]; !ok {
|
if _, ok := t.ctx["error"]; !ok {
|
||||||
|
|
@ -262,8 +260,8 @@ func (t *jsTracer) CaptureTxEnd(receipt *types.Receipt, err error) {
|
||||||
t.ctx["gasUsed"] = t.vm.ToValue(receipt.GasUsed)
|
t.ctx["gasUsed"] = t.vm.ToValue(receipt.GasUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the Tracer interface to initialize the tracing operation.
|
// onStart implements the Tracer interface to initialize the tracing operation.
|
||||||
func (t *jsTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *jsTracer) onStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
cancel := func(err error) {
|
cancel := func(err error) {
|
||||||
t.err = err
|
t.err = err
|
||||||
t.env.VM.Cancel()
|
t.env.VM.Cancel()
|
||||||
|
|
@ -299,8 +297,8 @@ func (t *jsTracer) CaptureStart(from common.Address, to common.Address, create b
|
||||||
t.ctx["value"] = valueBig
|
t.ctx["value"] = valueBig
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState implements the Tracer interface to trace a single step of VM execution.
|
// OnOpcode implements the Tracer interface to trace a single step of VM execution.
|
||||||
func (t *jsTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
func (t *jsTracer) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
if !t.traceStep {
|
if !t.traceStep {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -324,8 +322,8 @@ func (t *jsTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureFault implements the Tracer interface to trace an execution fault
|
// OnFault implements the Tracer interface to trace an execution fault
|
||||||
func (t *jsTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
|
func (t *jsTracer) OnFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
|
||||||
if t.err != nil {
|
if t.err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -336,15 +334,19 @@ func (t *jsTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// onEnd is called after the call finishes to finalize the tracing.
|
||||||
func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) {
|
func (t *jsTracer) onEnd(output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.ctx["error"] = t.vm.ToValue(err.Error())
|
t.ctx["error"] = t.vm.ToValue(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
||||||
func (t *jsTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
func (t *jsTracer) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||||
|
if depth == 0 {
|
||||||
|
t.onStart(from, to, vm.OpCode(typ) == vm.CREATE, input, gas, value)
|
||||||
|
return
|
||||||
|
}
|
||||||
if !t.traceFrame {
|
if !t.traceFrame {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -367,9 +369,13 @@ func (t *jsTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to comm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureExit is called when EVM exits a scope, even if the scope didn't
|
// OnExit is called when EVM exits a scope, even if the scope didn't
|
||||||
// execute any code.
|
// execute any code.
|
||||||
func (t *jsTracer) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) {
|
func (t *jsTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
|
if depth == 0 {
|
||||||
|
t.onEnd(output, gasUsed, err, reverted)
|
||||||
|
return
|
||||||
|
}
|
||||||
if !t.traceFrame {
|
if !t.traceFrame {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ func testCtx() *vmContext {
|
||||||
|
|
||||||
func runTrace(tracer *directory.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) {
|
func runTrace(tracer *directory.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) {
|
||||||
var (
|
var (
|
||||||
env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer.LiveLogger})
|
env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer.Hooks})
|
||||||
gasLimit uint64 = 31000
|
gasLimit uint64 = 31000
|
||||||
startGas uint64 = 10000
|
startGas uint64 = 10000
|
||||||
value = big.NewInt(0)
|
value = big.NewInt(0)
|
||||||
|
|
|
||||||
|
|
@ -21,18 +21,16 @@ func init() {
|
||||||
// as soon as we have a real live tracer.
|
// as soon as we have a real live tracer.
|
||||||
type noop struct{}
|
type noop struct{}
|
||||||
|
|
||||||
func newNoopTracer(_ json.RawMessage) (*tracing.LiveLogger, error) {
|
func newNoopTracer(_ json.RawMessage) (*tracing.Hooks, error) {
|
||||||
t := &noop{}
|
t := &noop{}
|
||||||
return &tracing.Hooks{
|
return &tracing.Hooks{
|
||||||
OnTxStart: t.CaptureTxStart,
|
OnTxStart: t.OnTxStart,
|
||||||
OnTxEnd: t.CaptureTxEnd,
|
OnTxEnd: t.OnTxEnd,
|
||||||
OnStart: t.CaptureStart,
|
OnEnter: t.OnEnter,
|
||||||
OnEnd: t.CaptureEnd,
|
OnExit: t.OnExit,
|
||||||
OnEnter: t.CaptureEnter,
|
OnOpcode: t.OnOpcode,
|
||||||
OnExit: t.CaptureExit,
|
OnFault: t.OnFault,
|
||||||
OnOpcode: t.CaptureState,
|
OnKeccakPreimage: t.OnKeccakPreimage,
|
||||||
OnFault: t.CaptureFault,
|
|
||||||
OnKeccakPreimage: t.CaptureKeccakPreimage,
|
|
||||||
OnGasChange: t.OnGasChange,
|
OnGasChange: t.OnGasChange,
|
||||||
OnBlockchainInit: t.OnBlockchainInit,
|
OnBlockchainInit: t.OnBlockchainInit,
|
||||||
OnBlockStart: t.OnBlockStart,
|
OnBlockStart: t.OnBlockStart,
|
||||||
|
|
@ -47,38 +45,24 @@ func newNoopTracer(_ json.RawMessage) (*tracing.LiveLogger, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
func (t *noop) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
func (t *noop) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
func (t *noop) OnFault(pc uint64, op tracing.OpCode, gas, cost uint64, _ tracing.OpContext, depth int, err error) {
|
||||||
func (t *noop) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
|
func (t *noop) OnKeccakPreimage(hash common.Hash, data []byte) {}
|
||||||
func (t *noop) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
|
||||||
|
func (t *noop) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureFault implements the EVMLogger interface to trace an execution fault.
|
func (t *noop) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
func (t *noop) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, _ tracing.OpContext, depth int, err error) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureKeccakPreimage is called during the KECCAK256 opcode.
|
func (t *noop) OnTxStart(vm *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
func (t *noop) CaptureKeccakPreimage(hash common.Hash, data []byte) {}
|
|
||||||
|
|
||||||
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
|
||||||
func (t *noop) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureExit is called when EVM exits a scope, even if the scope didn't
|
func (t *noop) OnTxEnd(receipt *types.Receipt, err error) {
|
||||||
// execute any code.
|
|
||||||
func (t *noop) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *noop) CaptureTxStart(vm *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *noop) CaptureTxEnd(receipt *types.Receipt, err error) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *noop) OnBlockStart(ev tracing.BlockEvent) {
|
func (t *noop) OnBlockStart(ev tracing.BlockEvent) {
|
||||||
|
|
|
||||||
|
|
@ -135,12 +135,12 @@ func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompi
|
||||||
|
|
||||||
func (a *AccessListTracer) Hooks() *tracing.Hooks {
|
func (a *AccessListTracer) Hooks() *tracing.Hooks {
|
||||||
return &tracing.Hooks{
|
return &tracing.Hooks{
|
||||||
OnOpcode: a.CaptureState,
|
OnOpcode: a.OnOpcode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState captures all opcodes that touch storage or addresses and adds them to the accesslist.
|
// OnOpcode captures all opcodes that touch storage or addresses and adds them to the accesslist.
|
||||||
func (a *AccessListTracer) CaptureState(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
func (a *AccessListTracer) OnOpcode(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
stackData := scope.StackData()
|
stackData := scope.StackData()
|
||||||
stackLen := len(stackData)
|
stackLen := len(stackData)
|
||||||
op := vm.OpCode(opcode)
|
op := vm.OpCode(opcode)
|
||||||
|
|
|
||||||
|
|
@ -135,10 +135,10 @@ func NewStructLogger(cfg *Config) *StructLogger {
|
||||||
|
|
||||||
func (l *StructLogger) Hooks() *tracing.Hooks {
|
func (l *StructLogger) Hooks() *tracing.Hooks {
|
||||||
return &tracing.Hooks{
|
return &tracing.Hooks{
|
||||||
OnTxStart: l.CaptureTxStart,
|
OnTxStart: l.OnTxStart,
|
||||||
OnTxEnd: l.CaptureTxEnd,
|
OnTxEnd: l.OnTxEnd,
|
||||||
OnEnd: l.CaptureEnd,
|
OnExit: l.OnExit,
|
||||||
OnOpcode: l.CaptureState,
|
OnOpcode: l.OnOpcode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,10 +158,10 @@ func (l *StructLogger) Reset() {
|
||||||
l.err = nil
|
l.err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState logs a new structured log message and pushes it out to the environment
|
// OnOpcode logs a new structured log message and pushes it out to the environment
|
||||||
//
|
//
|
||||||
// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
|
// OnOpcode also tracks SLOAD/SSTORE ops to track storage change.
|
||||||
func (l *StructLogger) CaptureState(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
func (l *StructLogger) OnOpcode(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
// If tracing was interrupted, set the error and stop
|
// If tracing was interrupted, set the error and stop
|
||||||
if l.interrupt.Load() {
|
if l.interrupt.Load() {
|
||||||
return
|
return
|
||||||
|
|
@ -226,8 +226,11 @@ func (l *StructLogger) CaptureState(pc uint64, opcode tracing.OpCode, gas, cost
|
||||||
l.logs = append(l.logs, log)
|
l.logs = append(l.logs, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// OnExit is called a call frame finishes processing.
|
||||||
func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) {
|
func (l *StructLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
|
if depth != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
l.output = output
|
l.output = output
|
||||||
l.err = err
|
l.err = err
|
||||||
if l.cfg.Debug {
|
if l.cfg.Debug {
|
||||||
|
|
@ -264,11 +267,11 @@ func (l *StructLogger) Stop(err error) {
|
||||||
l.interrupt.Store(true)
|
l.interrupt.Store(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *StructLogger) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (l *StructLogger) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
l.env = env
|
l.env = env
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *StructLogger) CaptureTxEnd(receipt *types.Receipt, err error) {
|
func (l *StructLogger) OnTxEnd(receipt *types.Receipt, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't override vm error
|
// Don't override vm error
|
||||||
if l.err == nil {
|
if l.err == nil {
|
||||||
|
|
@ -354,19 +357,23 @@ func NewMarkdownLogger(cfg *Config, writer io.Writer) *mdLogger {
|
||||||
|
|
||||||
func (t *mdLogger) Hooks() *tracing.Hooks {
|
func (t *mdLogger) Hooks() *tracing.Hooks {
|
||||||
return &tracing.Hooks{
|
return &tracing.Hooks{
|
||||||
OnTxStart: t.CaptureTxStart,
|
OnTxStart: t.OnTxStart,
|
||||||
OnStart: t.CaptureStart,
|
OnEnter: t.OnEnter,
|
||||||
OnOpcode: t.CaptureState,
|
OnExit: t.OnExit,
|
||||||
OnFault: t.CaptureFault,
|
OnOpcode: t.OnOpcode,
|
||||||
OnEnd: t.CaptureEnd,
|
OnFault: t.OnFault,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *mdLogger) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (t *mdLogger) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
t.env = env
|
t.env = env
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *mdLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *mdLogger) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||||
|
if depth != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
create := vm.OpCode(typ) == vm.CREATE
|
||||||
if !create {
|
if !create {
|
||||||
fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n",
|
fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n",
|
||||||
from.String(), to.String(),
|
from.String(), to.String(),
|
||||||
|
|
@ -383,8 +390,15 @@ func (t *mdLogger) CaptureStart(from common.Address, to common.Address, create b
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
|
func (t *mdLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
func (t *mdLogger) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
if depth == 0 {
|
||||||
|
fmt.Fprintf(t.out, "\nOutput: `%#x`\nConsumed gas: `%d`\nError: `%v`\n",
|
||||||
|
output, gasUsed, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnOpcode also tracks SLOAD/SSTORE ops to track storage change.
|
||||||
|
func (t *mdLogger) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
stack := scope.StackData()
|
stack := scope.StackData()
|
||||||
fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost)
|
fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost)
|
||||||
|
|
||||||
|
|
@ -404,7 +418,7 @@ func (t *mdLogger) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *mdLogger) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
|
func (t *mdLogger) OnFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
|
||||||
fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err)
|
fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,20 +47,19 @@ func NewJSONLogger(cfg *Config, writer io.Writer) *JSONLogger {
|
||||||
|
|
||||||
func (l *JSONLogger) Hooks() *tracing.Hooks {
|
func (l *JSONLogger) Hooks() *tracing.Hooks {
|
||||||
return &tracing.Hooks{
|
return &tracing.Hooks{
|
||||||
OnTxStart: l.CaptureTxStart,
|
OnTxStart: l.OnTxStart,
|
||||||
OnEnd: l.CaptureEnd,
|
OnExit: l.OnExit,
|
||||||
OnOpcode: l.CaptureState,
|
OnOpcode: l.OnOpcode,
|
||||||
OnFault: l.CaptureFault,
|
OnFault: l.OnFault,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) CaptureFault(pc uint64, op tracing.OpCode, gas uint64, cost uint64, scope tracing.OpContext, depth int, err error) {
|
func (l *JSONLogger) OnFault(pc uint64, op tracing.OpCode, gas uint64, cost uint64, scope tracing.OpContext, depth int, err error) {
|
||||||
// TODO: Add rData to this interface as well
|
// TODO: Add rData to this interface as well
|
||||||
l.CaptureState(pc, op, gas, cost, scope, nil, depth, err)
|
l.OnOpcode(pc, op, gas, cost, scope, nil, depth, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState outputs state information on the logger.
|
func (l *JSONLogger) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
func (l *JSONLogger) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
|
||||||
memory := scope.MemoryData()
|
memory := scope.MemoryData()
|
||||||
stack := scope.StackData()
|
stack := scope.StackData()
|
||||||
|
|
||||||
|
|
@ -86,8 +85,10 @@ func (l *JSONLogger) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64
|
||||||
l.encoder.Encode(log)
|
l.encoder.Encode(log)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is triggered at end of execution.
|
func (l *JSONLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) {
|
if depth > 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
type endLog struct {
|
type endLog struct {
|
||||||
Output string `json:"output"`
|
Output string `json:"output"`
|
||||||
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
|
|
@ -100,6 +101,6 @@ func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, err error, revert
|
||||||
l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), errMsg})
|
l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), errMsg})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (l *JSONLogger) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
l.env = env
|
l.env = env
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,7 @@ func TestStoreCapture(t *testing.T) {
|
||||||
)
|
)
|
||||||
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
|
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
|
||||||
var index common.Hash
|
var index common.Hash
|
||||||
logger.CaptureTxStart(env.GetVMContext(), nil, common.Address{})
|
logger.OnTxStart(env.GetVMContext(), nil, common.Address{})
|
||||||
logger.CaptureStart(common.Address{}, contract.Address(), false, nil, 0, nil)
|
|
||||||
_, err := env.Interpreter().Run(contract, []byte{}, false)
|
_, err := env.Interpreter().Run(contract, []byte{}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ type fourByteTracer struct {
|
||||||
ids map[string]int // ids aggregates the 4byte ids found
|
ids map[string]int // ids aggregates the 4byte ids found
|
||||||
interrupt atomic.Bool // Atomic flag to signal execution interruption
|
interrupt atomic.Bool // Atomic flag to signal execution interruption
|
||||||
reason error // Textual reason for the interruption
|
reason error // Textual reason for the interruption
|
||||||
activePrecompiles []common.Address // Updated on CaptureStart based on given rules
|
activePrecompiles []common.Address // Updated on tx start based on given rules
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFourByteTracer returns a native go tracer which collects
|
// newFourByteTracer returns a native go tracer which collects
|
||||||
|
|
@ -63,9 +63,8 @@ func newFourByteTracer(ctx *directory.Context, _ json.RawMessage) (*directory.Tr
|
||||||
}
|
}
|
||||||
return &directory.Tracer{
|
return &directory.Tracer{
|
||||||
Hooks: &tracing.Hooks{
|
Hooks: &tracing.Hooks{
|
||||||
OnTxStart: t.CaptureTxStart,
|
OnTxStart: t.OnTxStart,
|
||||||
OnStart: t.CaptureStart,
|
OnEnter: t.OnEnter,
|
||||||
OnEnter: t.CaptureEnter,
|
|
||||||
},
|
},
|
||||||
GetResult: t.GetResult,
|
GetResult: t.GetResult,
|
||||||
Stop: t.Stop,
|
Stop: t.Stop,
|
||||||
|
|
@ -88,22 +87,14 @@ func (t *fourByteTracer) store(id []byte, size int) {
|
||||||
t.ids[key] += 1
|
t.ids[key] += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *fourByteTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (t *fourByteTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
// Update list of precompiles based on current block
|
// Update list of precompiles based on current block
|
||||||
rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time)
|
rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time)
|
||||||
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
||||||
func (t *fourByteTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *fourByteTracer) OnEnter(depth int, opcode tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||||
// Save the outer calldata
|
|
||||||
if len(input) >= 4 {
|
|
||||||
t.store(input[0:4], len(input)-4)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
|
||||||
func (t *fourByteTracer) CaptureEnter(opcode tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
|
||||||
// Skip if tracing was interrupted
|
// Skip if tracing was interrupted
|
||||||
if t.interrupt.Load() {
|
if t.interrupt.Load() {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -127,27 +127,12 @@ func newCallTracer(ctx *directory.Context, cfg json.RawMessage) (*directory.Trac
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &directory.Tracer{
|
return &directory.Tracer{
|
||||||
<<<<<<< HEAD
|
|
||||||
LiveLogger: &tracing.LiveLogger{
|
|
||||||
CaptureTxStart: t.CaptureTxStart,
|
|
||||||
CaptureTxEnd: t.CaptureTxEnd,
|
|
||||||
CaptureStart: t.CaptureStart,
|
|
||||||
CaptureEnd: t.CaptureEnd,
|
|
||||||
CaptureEnter: t.CaptureEnter,
|
|
||||||
CaptureExit: t.CaptureExit,
|
|
||||||
CaptureState: t.CaptureState,
|
|
||||||
OnLog: t.OnLog,
|
|
||||||
=======
|
|
||||||
Hooks: &tracing.Hooks{
|
Hooks: &tracing.Hooks{
|
||||||
OnTxStart: t.CaptureTxStart,
|
OnTxStart: t.OnTxStart,
|
||||||
OnTxEnd: t.CaptureTxEnd,
|
OnTxEnd: t.OnTxEnd,
|
||||||
OnStart: t.CaptureStart,
|
OnEnter: t.OnEnter,
|
||||||
OnEnd: t.CaptureEnd,
|
OnExit: t.OnExit,
|
||||||
OnEnter: t.CaptureEnter,
|
|
||||||
OnExit: t.CaptureExit,
|
|
||||||
OnOpcode: t.CaptureState,
|
|
||||||
OnLog: t.OnLog,
|
OnLog: t.OnLog,
|
||||||
>>>>>>> 923c180058 (rename Capture hooks to On)
|
|
||||||
},
|
},
|
||||||
GetResult: t.GetResult,
|
GetResult: t.GetResult,
|
||||||
Stop: t.Stop,
|
Stop: t.Stop,
|
||||||
|
|
@ -191,10 +176,10 @@ func (t *callTracer) CaptureEnd(output []byte, gasUsed uint64, err error, revert
|
||||||
func (t *callTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
func (t *callTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
||||||
func (t *callTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
func (t *callTracer) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||||
t.depth++
|
t.depth = depth
|
||||||
if t.config.OnlyTopCall {
|
if t.config.OnlyTopCall && depth > 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Skip if tracing was interrupted
|
// Skip if tracing was interrupted
|
||||||
|
|
@ -214,10 +199,15 @@ func (t *callTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to co
|
||||||
t.callstack = append(t.callstack, call)
|
t.callstack = append(t.callstack, call)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureExit is called when EVM exits a scope, even if the scope didn't
|
// OnExit is called when EVM exits a scope, even if the scope didn't
|
||||||
// execute any code.
|
// execute any code.
|
||||||
func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) {
|
func (t *callTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
t.depth--
|
if depth == 0 {
|
||||||
|
t.captureEnd(output, gasUsed, err, reverted)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.depth = depth - 1
|
||||||
if t.config.OnlyTopCall {
|
if t.config.OnlyTopCall {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -235,11 +225,18 @@ func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error, rever
|
||||||
t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call)
|
t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *callTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (t *callTracer) captureEnd(output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
|
if len(t.callstack) != 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.callstack[0].processOutput(output, err, reverted)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *callTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
t.gasLimit = tx.Gas()
|
t.gasLimit = tx.Gas()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *callTracer) CaptureTxEnd(receipt *types.Receipt, err error) {
|
func (t *callTracer) OnTxEnd(receipt *types.Receipt, err error) {
|
||||||
// Error happened during tx validation.
|
// Error happened during tx validation.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ type flatCallTracer struct {
|
||||||
config flatCallTracerConfig
|
config flatCallTracerConfig
|
||||||
ctx *directory.Context // Holds tracer context data
|
ctx *directory.Context // Holds tracer context data
|
||||||
reason error // Textual reason for the interruption
|
reason error // Textual reason for the interruption
|
||||||
activePrecompiles []common.Address // Updated on CaptureStart based on given rules
|
activePrecompiles []common.Address // Updated on tx start based on given rules
|
||||||
}
|
}
|
||||||
|
|
||||||
type flatCallTracerConfig struct {
|
type flatCallTracerConfig struct {
|
||||||
|
|
@ -142,43 +142,19 @@ func newFlatCallTracer(ctx *directory.Context, cfg json.RawMessage) (*directory.
|
||||||
ft := &flatCallTracer{tracer: t, ctx: ctx, config: config}
|
ft := &flatCallTracer{tracer: t, ctx: ctx, config: config}
|
||||||
return &directory.Tracer{
|
return &directory.Tracer{
|
||||||
Hooks: &tracing.Hooks{
|
Hooks: &tracing.Hooks{
|
||||||
OnTxStart: ft.CaptureTxStart,
|
OnTxStart: ft.OnTxStart,
|
||||||
OnTxEnd: ft.CaptureTxEnd,
|
OnTxEnd: ft.OnTxEnd,
|
||||||
OnStart: ft.CaptureStart,
|
OnEnter: ft.OnEnter,
|
||||||
OnEnd: ft.CaptureEnd,
|
OnExit: ft.OnExit,
|
||||||
OnEnter: ft.CaptureEnter,
|
|
||||||
OnExit: ft.CaptureExit,
|
|
||||||
OnOpcode: ft.CaptureState,
|
|
||||||
OnFault: ft.CaptureFault,
|
|
||||||
},
|
},
|
||||||
Stop: ft.Stop,
|
Stop: ft.Stop,
|
||||||
GetResult: ft.GetResult,
|
GetResult: ft.GetResult,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
||||||
func (t *flatCallTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *flatCallTracer) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||||
t.tracer.CaptureStart(from, to, create, input, gas, value)
|
t.tracer.OnEnter(depth, typ, from, to, input, gas, value)
|
||||||
}
|
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
|
||||||
func (t *flatCallTracer) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) {
|
|
||||||
t.tracer.CaptureEnd(output, gasUsed, err, reverted)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
|
|
||||||
func (t *flatCallTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
|
||||||
t.tracer.CaptureState(pc, op, gas, cost, scope, rData, depth, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaptureFault implements the EVMLogger interface to trace an execution fault.
|
|
||||||
func (t *flatCallTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
|
|
||||||
t.tracer.CaptureFault(pc, op, gas, cost, scope, depth, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
|
||||||
func (t *flatCallTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
|
||||||
t.tracer.CaptureEnter(typ, from, to, input, gas, value)
|
|
||||||
|
|
||||||
// Child calls must have a value, even if it's zero.
|
// Child calls must have a value, even if it's zero.
|
||||||
// Practically speaking, only STATICCALL has nil value. Set it to zero.
|
// Practically speaking, only STATICCALL has nil value. Set it to zero.
|
||||||
|
|
@ -187,10 +163,10 @@ func (t *flatCallTracer) CaptureEnter(typ tracing.OpCode, from common.Address, t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureExit is called when EVM exits a scope, even if the scope didn't
|
// OnExit is called when EVM exits a scope, even if the scope didn't
|
||||||
// execute any code.
|
// execute any code.
|
||||||
func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) {
|
func (t *flatCallTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
t.tracer.CaptureExit(output, gasUsed, err, reverted)
|
t.tracer.OnExit(depth, output, gasUsed, err, reverted)
|
||||||
|
|
||||||
// Parity traces don't include CALL/STATICCALLs to precompiles.
|
// Parity traces don't include CALL/STATICCALLs to precompiles.
|
||||||
// By default we remove them from the callstack.
|
// By default we remove them from the callstack.
|
||||||
|
|
@ -211,15 +187,15 @@ func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error, r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *flatCallTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (t *flatCallTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
t.tracer.CaptureTxStart(env, tx, from)
|
t.tracer.OnTxStart(env, tx, from)
|
||||||
// Update list of precompiles based on current block
|
// Update list of precompiles based on current block
|
||||||
rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time)
|
rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time)
|
||||||
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *flatCallTracer) CaptureTxEnd(receipt *types.Receipt, err error) {
|
func (t *flatCallTracer) OnTxEnd(receipt *types.Receipt, err error) {
|
||||||
t.tracer.CaptureTxEnd(receipt, err)
|
t.tracer.OnTxEnd(receipt, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetResult returns an empty json object.
|
// GetResult returns an empty json object.
|
||||||
|
|
|
||||||
|
|
@ -59,15 +59,13 @@ func newMuxTracer(ctx *directory.Context, cfg json.RawMessage) (*directory.Trace
|
||||||
t := &muxTracer{names: names, tracers: objects}
|
t := &muxTracer{names: names, tracers: objects}
|
||||||
return &directory.Tracer{
|
return &directory.Tracer{
|
||||||
Hooks: &tracing.Hooks{
|
Hooks: &tracing.Hooks{
|
||||||
OnTxStart: t.CaptureTxStart,
|
OnTxStart: t.OnTxStart,
|
||||||
OnTxEnd: t.CaptureTxEnd,
|
OnTxEnd: t.OnTxEnd,
|
||||||
OnStart: t.CaptureStart,
|
OnEnter: t.OnEnter,
|
||||||
OnEnd: t.CaptureEnd,
|
OnExit: t.OnExit,
|
||||||
OnEnter: t.CaptureEnter,
|
OnOpcode: t.OnOpcode,
|
||||||
OnExit: t.CaptureExit,
|
OnFault: t.OnFault,
|
||||||
OnOpcode: t.CaptureState,
|
OnKeccakPreimage: t.OnKeccakPreimage,
|
||||||
OnFault: t.CaptureFault,
|
|
||||||
OnKeccakPreimage: t.CaptureKeccakPreimage,
|
|
||||||
OnGasChange: t.OnGasChange,
|
OnGasChange: t.OnGasChange,
|
||||||
OnBalanceChange: t.OnBalanceChange,
|
OnBalanceChange: t.OnBalanceChange,
|
||||||
OnNonceChange: t.OnNonceChange,
|
OnNonceChange: t.OnNonceChange,
|
||||||
|
|
@ -80,26 +78,7 @@ func newMuxTracer(ctx *directory.Context, cfg json.RawMessage) (*directory.Trace
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
func (t *muxTracer) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
func (t *muxTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
|
||||||
for _, t := range t.tracers {
|
|
||||||
if t.OnStart != nil {
|
|
||||||
t.OnStart(from, to, create, input, gas, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
|
||||||
func (t *muxTracer) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) {
|
|
||||||
for _, t := range t.tracers {
|
|
||||||
if t.OnEnd != nil {
|
|
||||||
t.OnEnd(output, gasUsed, err, reverted)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
|
|
||||||
func (t *muxTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
|
||||||
for _, t := range t.tracers {
|
for _, t := range t.tracers {
|
||||||
if t.OnOpcode != nil {
|
if t.OnOpcode != nil {
|
||||||
t.OnOpcode(pc, op, gas, cost, scope, rData, depth, err)
|
t.OnOpcode(pc, op, gas, cost, scope, rData, depth, err)
|
||||||
|
|
@ -107,8 +86,7 @@ func (t *muxTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureFault implements the EVMLogger interface to trace an execution fault.
|
func (t *muxTracer) OnFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
|
||||||
func (t *muxTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
|
|
||||||
for _, t := range t.tracers {
|
for _, t := range t.tracers {
|
||||||
if t.OnFault != nil {
|
if t.OnFault != nil {
|
||||||
t.OnFault(pc, op, gas, cost, scope, depth, err)
|
t.OnFault(pc, op, gas, cost, scope, depth, err)
|
||||||
|
|
@ -116,8 +94,7 @@ func (t *muxTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureKeccakPreimage is called during the KECCAK256 opcode.
|
func (t *muxTracer) OnKeccakPreimage(hash common.Hash, data []byte) {
|
||||||
func (t *muxTracer) CaptureKeccakPreimage(hash common.Hash, data []byte) {
|
|
||||||
for _, t := range t.tracers {
|
for _, t := range t.tracers {
|
||||||
if t.OnKeccakPreimage != nil {
|
if t.OnKeccakPreimage != nil {
|
||||||
t.OnKeccakPreimage(hash, data)
|
t.OnKeccakPreimage(hash, data)
|
||||||
|
|
@ -125,7 +102,6 @@ func (t *muxTracer) CaptureKeccakPreimage(hash common.Hash, data []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureGasConsumed is called when gas is consumed.
|
|
||||||
func (t *muxTracer) OnGasChange(old, new uint64, reason tracing.GasChangeReason) {
|
func (t *muxTracer) OnGasChange(old, new uint64, reason tracing.GasChangeReason) {
|
||||||
for _, t := range t.tracers {
|
for _, t := range t.tracers {
|
||||||
if t.OnGasChange != nil {
|
if t.OnGasChange != nil {
|
||||||
|
|
@ -134,8 +110,7 @@ func (t *muxTracer) OnGasChange(old, new uint64, reason tracing.GasChangeReason)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
func (t *muxTracer) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||||
func (t *muxTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
|
||||||
for _, t := range t.tracers {
|
for _, t := range t.tracers {
|
||||||
if t.OnEnter != nil {
|
if t.OnEnter != nil {
|
||||||
t.OnEnter(typ, from, to, input, gas, value)
|
t.OnEnter(typ, from, to, input, gas, value)
|
||||||
|
|
@ -143,9 +118,7 @@ func (t *muxTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to com
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureExit is called when EVM exits a scope, even if the scope didn't
|
func (t *muxTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||||
// execute any code.
|
|
||||||
func (t *muxTracer) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) {
|
|
||||||
for _, t := range t.tracers {
|
for _, t := range t.tracers {
|
||||||
if t.OnExit != nil {
|
if t.OnExit != nil {
|
||||||
t.OnExit(output, gasUsed, err, reverted)
|
t.OnExit(output, gasUsed, err, reverted)
|
||||||
|
|
@ -153,7 +126,7 @@ func (t *muxTracer) CaptureExit(output []byte, gasUsed uint64, err error, revert
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *muxTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (t *muxTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
for _, t := range t.tracers {
|
for _, t := range t.tracers {
|
||||||
if t.OnTxStart != nil {
|
if t.OnTxStart != nil {
|
||||||
t.OnTxStart(env, tx, from)
|
t.OnTxStart(env, tx, from)
|
||||||
|
|
@ -161,7 +134,7 @@ func (t *muxTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *muxTracer) CaptureTxEnd(receipt *types.Receipt, err error) {
|
func (t *muxTracer) OnTxEnd(receipt *types.Receipt, err error) {
|
||||||
for _, t := range t.tracers {
|
for _, t := range t.tracers {
|
||||||
if t.OnTxEnd != nil {
|
if t.OnTxEnd != nil {
|
||||||
t.OnTxEnd(receipt, err)
|
t.OnTxEnd(receipt, err)
|
||||||
|
|
|
||||||
|
|
@ -90,17 +90,17 @@ func newPrestateTracer(ctx *directory.Context, cfg json.RawMessage) (*directory.
|
||||||
}
|
}
|
||||||
return &directory.Tracer{
|
return &directory.Tracer{
|
||||||
Hooks: &tracing.Hooks{
|
Hooks: &tracing.Hooks{
|
||||||
OnTxStart: t.CaptureTxStart,
|
OnTxStart: t.OnTxStart,
|
||||||
OnTxEnd: t.CaptureTxEnd,
|
OnTxEnd: t.OnTxEnd,
|
||||||
OnOpcode: t.CaptureState,
|
OnOpcode: t.OnOpcode,
|
||||||
},
|
},
|
||||||
GetResult: t.GetResult,
|
GetResult: t.GetResult,
|
||||||
Stop: t.Stop,
|
Stop: t.Stop,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
|
// OnOpcode implements the EVMLogger interface to trace a single step of VM execution.
|
||||||
func (t *prestateTracer) CaptureState(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
func (t *prestateTracer) OnOpcode(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -146,7 +146,7 @@ func (t *prestateTracer) CaptureState(pc uint64, opcode tracing.OpCode, gas, cos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *prestateTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (t *prestateTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
t.env = env
|
t.env = env
|
||||||
if tx.To() == nil {
|
if tx.To() == nil {
|
||||||
t.to = crypto.CreateAddress(from, env.StateDB.GetNonce(from))
|
t.to = crypto.CreateAddress(from, env.StateDB.GetNonce(from))
|
||||||
|
|
@ -160,7 +160,7 @@ func (t *prestateTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transa
|
||||||
t.lookupAccount(env.Coinbase)
|
t.lookupAccount(env.Coinbase)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *prestateTracer) CaptureTxEnd(receipt *types.Receipt, err error) {
|
func (t *prestateTracer) OnTxEnd(receipt *types.Receipt, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ type btHeaderMarshaling struct {
|
||||||
ExcessBlobGas *math.HexOrDecimal64
|
ExcessBlobGas *math.HexOrDecimal64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *BlockTest) Run(snapshotter bool, scheme string, tracer *tracing.LiveLogger) error {
|
func (t *BlockTest) Run(snapshotter bool, scheme string, tracer *tracing.Hooks) error {
|
||||||
config, ok := Forks[t.json.Network]
|
config, ok := Forks[t.json.Network]
|
||||||
if !ok {
|
if !ok {
|
||||||
return UnsupportedForkError{t.json.Network}
|
return UnsupportedForkError{t.json.Network}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue