Skip to content

Commit

Permalink
Merge pull request onflow#6299 from onflow/ramtin/evm-patch-tracer
Browse files Browse the repository at this point in the history
[Flow EVM] improve debug tracing
  • Loading branch information
ramtinms authored Aug 8, 2024
2 parents 29ec7b8 + 762d8bb commit 1dd0921
Show file tree
Hide file tree
Showing 8 changed files with 296 additions and 117 deletions.
274 changes: 157 additions & 117 deletions fvm/evm/debug/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,29 +32,39 @@ type EVMTracer interface {
var _ EVMTracer = &CallTracer{}

type CallTracer struct {
logger zerolog.Logger
tracer *tracers.Tracer
uploader Uploader
blockID flow.Identifier
logger zerolog.Logger
tracer *tracers.Tracer
tracerConfig []byte
uploader Uploader
blockID flow.Identifier
}

func NewEVMCallTracer(uploader Uploader, logger zerolog.Logger) (*CallTracer, error) {
tracer, err := tracers.DefaultDirectory.New(tracerName, &tracers.Context{}, json.RawMessage(tracerConfig))
tracerConfig := json.RawMessage(tracerConfig)

tracer, err := tracers.DefaultDirectory.New(tracerName, &tracers.Context{}, tracerConfig)
if err != nil {
return nil, err
}

return &CallTracer{
logger: logger.With().Str("module", "evm-tracer").Logger(),
tracer: tracer,
uploader: uploader,
logger: logger.With().Str("module", "evm-tracer").Logger(),
tracer: tracer,
tracerConfig: tracerConfig,
uploader: uploader,
}, nil
}

func (t *CallTracer) TxTracer() *tracers.Tracer {
return NewSafeTxTracer(t)
}

func (t *CallTracer) ResetTracer() error {
var err error
t.tracer, err = tracers.DefaultDirectory.New(tracerName, &tracers.Context{}, json.RawMessage(tracerConfig))
return err
}

func (t *CallTracer) WithBlockID(id flow.Identifier) {
t.blockID = id
}
Expand Down Expand Up @@ -88,6 +98,14 @@ func (t *CallTracer) Collect(txID gethCommon.Hash) {
l.Error().Err(err).Msg("failed to produce trace results")
}

// reset tracing to have fresh state
if err := t.ResetTracer(); err != nil {
l.Error().Err(err).
Str("traces", string(res)).
Msg("failed to reset trace")
return
}

if err = t.uploader.Upload(TraceID(txID, t.blockID), res); err != nil {
l.Error().Err(err).
Str("traces", string(res)).
Expand All @@ -97,6 +115,7 @@ func (t *CallTracer) Collect(txID gethCommon.Hash) {

l.Debug().Msg("evm traces uploaded successfully")
}()

}

var NopTracer = &nopTracer{}
Expand Down Expand Up @@ -126,134 +145,155 @@ func NewSafeTxTracer(ct *CallTracer) *tracers.Tracer {
Str("block-id", ct.blockID.String()).
Logger()

wrapped.OnTxStart = func(
vm *tracing.VMContext,
tx *types.Transaction,
from gethCommon.Address,
) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
if ct.tracer.OnTxStart != nil {
wrapped.OnTxStart = func(
vm *tracing.VMContext,
tx *types.Transaction,
from gethCommon.Address,
) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
}
l.Err(err).
Stack().
Msg("OnTxStart trace collection failed")
}
l.Err(err).
Stack().
Msg("OnTxStart trace collection failed")
}
}()
ct.tracer.OnTxStart(vm, tx, from)
}()
ct.tracer.OnTxStart(vm, tx, from)
l.Debug().Msg("tracing OnTxStart is called")
}
}

wrapped.OnTxEnd = func(receipt *types.Receipt, err error) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
if ct.tracer.OnTxEnd != nil {
wrapped.OnTxEnd = func(receipt *types.Receipt, err error) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
}
l.Err(err).
Stack().
Msg("OnTxEnd trace collection failed")
}
l.Err(err).
Stack().
Msg("OnTxEnd trace collection failed")
}
}()
ct.tracer.OnTxEnd(receipt, err)
}()
ct.tracer.OnTxEnd(receipt, err)
l.Debug().Msg("tracing OnTxEnd is called")
}
}

wrapped.OnEnter = func(
depth int,
typ byte,
from, to gethCommon.Address,
input []byte,
gas uint64,
value *big.Int,
) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
if ct.tracer.OnEnter != nil {
wrapped.OnEnter = func(
depth int,
typ byte,
from, to gethCommon.Address,
input []byte,
gas uint64,
value *big.Int,
) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
}
l.Err(err).
Stack().
Msg("OnEnter trace collection failed")
}
l.Err(err).
Stack().
Msg("OnEnter trace collection failed")
}
}()
ct.tracer.OnEnter(depth, typ, from, to, input, gas, value)
}()
ct.tracer.OnEnter(depth, typ, from, to, input, gas, value)
l.Debug().Int("depth", depth).Msg("tracing OnEnter is called")
}
}

wrapped.OnExit = func(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
if ct.tracer.OnExit != nil {
wrapped.OnExit = func(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
}
l.Err(err).
Stack().
Msg("OnExit trace collection failed")
}
l.Err(err).
Stack().
Msg("OnExit trace collection failed")
}
}()
ct.tracer.OnExit(depth, output, gasUsed, err, reverted)
}()
ct.tracer.OnExit(depth, output, gasUsed, err, reverted)
l.Debug().Int("depth", depth).Msg("tracing OnExit is called")
}
}

wrapped.OnOpcode = func(
pc uint64,
op byte,
gas, cost uint64,
scope tracing.OpContext,
rData []byte,
depth int,
err error,
) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
if ct.tracer.OnOpcode != nil {
wrapped.OnOpcode = func(
pc uint64,
op byte,
gas, cost uint64,
scope tracing.OpContext,
rData []byte,
depth int,
err error,
) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
}
l.Err(err).
Stack().
Msg("OnOpcode trace collection failed")
}
l.Err(err).
Stack().
Msg("OnOpcode trace collection failed")
}
}()
ct.tracer.OnOpcode(pc, op, gas, cost, scope, rData, depth, err)
}()
ct.tracer.OnOpcode(pc, op, gas, cost, scope, rData, depth, err)
l.Debug().Msg("tracing OnOpcode is called")
}
}

wrapped.OnFault = func(
pc uint64,
op byte,
gas, cost uint64,
scope tracing.OpContext,
depth int,
err error) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
if ct.tracer.OnFault != nil {
wrapped.OnFault = func(
pc uint64,
op byte,
gas, cost uint64,
scope tracing.OpContext,
depth int,
err error) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
}
l.Err(err).
Stack().
Msg("OnFault trace collection failed")
}
l.Err(err).
Stack().
Msg("OnFault trace collection failed")
}
}()
ct.tracer.OnFault(pc, op, gas, cost, scope, depth, err)
}()
ct.tracer.OnFault(pc, op, gas, cost, scope, depth, err)
l.Debug().Msg("tracing OnFault is called")
}
}

wrapped.OnGasChange = func(old, new uint64, reason tracing.GasChangeReason) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
if ct.tracer.OnGasChange != nil {
wrapped.OnGasChange = func(old, new uint64, reason tracing.GasChangeReason) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("panic: %v", r)
}
l.Err(err).
Stack().
Msg("OnGasChange trace collection failed")
}
l.Err(err).
Stack().
Msg("OnGasChange trace collection failed")
}
}()
ct.tracer.OnGasChange(old, new, reason)
}()
ct.tracer.OnGasChange(old, new, reason)
l.Debug().Msg("tracing OnGasChange is called")
}
}

wrapped.GetResult = ct.tracer.GetResult
Expand Down
1 change: 1 addition & 0 deletions fvm/evm/debug/tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func Test_CallTracer(t *testing.T) {
tx := gethTypes.NewTransaction(nonce, to, amount, 100, big.NewInt(10), data)
tr.OnTxStart(nil, tx, from)
tr.OnEnter(1, byte(vm.ADD), from, to, data, 20, big.NewInt(2))
tr.OnExit(1, nil, 10, nil, false)
tr.OnTxEnd(&gethTypes.Receipt{}, nil)
tr.OnExit(0, []byte{0x02}, 200, nil, false)

Expand Down
Loading

0 comments on commit 1dd0921

Please sign in to comment.