Skip to content

Commit

Permalink
Fix fake tx tracing
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaliyb committed Jan 15, 2025
1 parent 8a1ba76 commit 917e3db
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 14 deletions.
19 changes: 19 additions & 0 deletions packages/evm/evmutil/tx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package evmutil

import (
"slices"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)

func IsFakeTransaction(tx *types.Transaction) bool {
sender, err := GetSender(tx)

// the error will fire when the transaction is invalid. This is most of the time a fake evm tx we use for internal calls, therefore it's fine to assume both.
if slices.Equal(sender.Bytes(), common.Address{}.Bytes()) || err != nil {
return true
}

return false
}
16 changes: 10 additions & 6 deletions packages/evm/jsonrpc/evmchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ func (e *EVMChain) traceTransaction(
BlockNumber: new(big.Int).SetUint64(blockNumber),
TxIndex: int(txIndex),
TxHash: tx.Hash(),
}, config.TracerConfig, false)
}, config.TracerConfig, false, nil)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -736,18 +736,22 @@ func (e *EVMChain) debugTraceBlock(config *tracers.TraceConfig, block *types.Blo

blockNumber := uint64(iscBlock.BlockIndex())

blockTxs := block.Transactions()
fakeTxs := make([]*types.Transaction, 0, len(blockTxs))
for _, tx := range blockTxs {
if e.isFakeTransaction(tx) {
fakeTxs = append(fakeTxs, tx)
}
}

tracer, err := newTracer(tracerType, &tracers.Context{
BlockHash: block.Hash(),
BlockNumber: new(big.Int).SetUint64(blockNumber),
}, config.TracerConfig, true)
}, config.TracerConfig, true, types.Transactions(fakeTxs))
if err != nil {
return nil, err
}

// if e.isFakeTransaction(tx) {
// return tracer.TraceFakeTx(tx)
// }

err = e.backend.EVMTrace(
iscBlock.PreviousAliasOutput,
iscBlock.Timestamp,
Expand Down
6 changes: 3 additions & 3 deletions packages/evm/jsonrpc/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ type Tracer struct {
TraceFakeTx func(tx *types.Transaction) (json.RawMessage, error)
}

type tracerFactory func(traceCtx *tracers.Context, cfg json.RawMessage, traceBlock bool) (*Tracer, error)
type tracerFactory func(traceCtx *tracers.Context, cfg json.RawMessage, traceBlock bool, initValue any) (*Tracer, error)

var allTracers = map[string]tracerFactory{}

func registerTracer(tracerType string, fn tracerFactory) {
allTracers[tracerType] = fn
}

func newTracer(tracerType string, ctx *tracers.Context, cfg json.RawMessage, traceBlock bool) (*Tracer, error) {
func newTracer(tracerType string, ctx *tracers.Context, cfg json.RawMessage, traceBlock bool, initValue any) (*Tracer, error) {
fn := allTracers[tracerType]
if fn == nil {
return nil, fmt.Errorf("unsupported tracer type: %s", tracerType)
}
return fn(ctx, cfg, traceBlock)
return fn(ctx, cfg, traceBlock, initValue)
}
31 changes: 27 additions & 4 deletions packages/evm/jsonrpc/tracer_call.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package jsonrpc
import (
"encoding/json"
"errors"
"fmt"
"math/big"
"strings"
"sync/atomic"
Expand Down Expand Up @@ -127,6 +128,7 @@ type callTracer struct {
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
traceBlock bool
fakeTxs []*types.Transaction
}

type callTracerConfig struct {
Expand All @@ -136,8 +138,21 @@ type callTracerConfig struct {

// newCallTracer returns a native go tracer which tracks
// call frames of a tx, and implements vm.EVMLogger.
func newCallTracer(ctx *tracers.Context, cfg json.RawMessage, traceBlock bool) (*Tracer, error) {
t, err := newCallTracerObject(ctx, cfg, traceBlock)
func newCallTracer(ctx *tracers.Context, cfg json.RawMessage, traceBlock bool, initValue any) (*Tracer, error) {
var fakeTxs types.Transactions

if initValue == nil && traceBlock {
return nil, fmt.Errorf("initValue with block transactions is required for block tracing")
}

if initValue != nil {
var ok bool
fakeTxs, ok = initValue.(types.Transactions)
if !ok {
return nil, fmt.Errorf("invalid init value type for calltracer: %T", initValue)
}
}
t, err := newCallTracerObject(ctx, cfg, traceBlock, fakeTxs)
if err != nil {
return nil, err
}
Expand All @@ -157,7 +172,7 @@ func newCallTracer(ctx *tracers.Context, cfg json.RawMessage, traceBlock bool) (
}, nil
}

func newCallTracerObject(_ *tracers.Context, cfg json.RawMessage, traceBlock bool) (*callTracer, error) {
func newCallTracerObject(_ *tracers.Context, cfg json.RawMessage, traceBlock bool, fakeTxs []*types.Transaction) (*callTracer, error) {
var config callTracerConfig
if cfg != nil {
if err := json.Unmarshal(cfg, &config); err != nil {
Expand All @@ -166,7 +181,7 @@ func newCallTracerObject(_ *tracers.Context, cfg json.RawMessage, traceBlock boo
}
// First callframe contains tx context info
// and is populated on start and end.
return &callTracer{txToStack: make(map[common.Hash][]CallFrame), currentTx: common.Hash{}, config: config, traceBlock: traceBlock}, nil
return &callTracer{txToStack: make(map[common.Hash][]CallFrame), currentTx: common.Hash{}, config: config, traceBlock: traceBlock, fakeTxs: fakeTxs}, nil
}

// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct).
Expand Down Expand Up @@ -290,6 +305,14 @@ func (t *callTracer) GetResult() (json.RawMessage, error) {
})
}

for _, tx := range t.fakeTxs {
csJSON, err := t.TraceFakeTx(tx)
if err != nil {
return nil, err
}
results = append(results, TxTraceResult{TxHash: tx.Hash(), Result: csJSON})
}

res, err := json.Marshal(results)
if err != nil {
return nil, err
Expand Down
35 changes: 34 additions & 1 deletion packages/evm/jsonrpc/tracer_prestate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package jsonrpc
import (
"bytes"
"encoding/json"
"fmt"
"sync/atomic"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -57,13 +58,27 @@ type prestateTracer struct {
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
traceBlock bool
fakeTxs types.Transactions
}

type prestateTracerConfig struct {
DiffMode bool `json:"diffMode"` // If true, this tracer will return state modifications
}

func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage, traceBlock bool) (*Tracer, error) {
func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage, traceBlock bool, initValue any) (*Tracer, error) {
var fakeTxs types.Transactions

if initValue == nil && traceBlock {
return nil, fmt.Errorf("initValue with block transactions is required for block tracing")
}

if initValue != nil {
var ok bool
fakeTxs, ok = initValue.(types.Transactions)
if !ok {
return nil, fmt.Errorf("invalid init value type for prestateTracer: %T", initValue)
}
}
var config prestateTracerConfig
if err := json.Unmarshal(cfg, &config); err != nil {
return nil, err
Expand All @@ -72,6 +87,7 @@ func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage, traceBlock boo
config: config,
traceBlock: traceBlock,
states: make(map[common.Hash]*PrestateTxValue),
fakeTxs: fakeTxs,
}
return &Tracer{
Tracer: &tracers.Tracer{
Expand Down Expand Up @@ -192,6 +208,14 @@ func (t *prestateTracer) GetResult() (json.RawMessage, error) {
return nil, err
}
result = append(result, TxTraceResult{TxHash: txHash, Result: diffResult})

for _, tx := range t.fakeTxs {
csJSON, err := t.TraceFakeTx(tx)
if err != nil {
return nil, err
}
result = append(result, TxTraceResult{TxHash: tx.Hash(), Result: csJSON})
}
}
res, err = json.Marshal(result)
} else {
Expand All @@ -203,6 +227,15 @@ func (t *prestateTracer) GetResult() (json.RawMessage, error) {
}
result = append(result, TxTraceResult{TxHash: txHash, Result: preState})
}

for _, tx := range t.fakeTxs {
csJSON, err := t.TraceFakeTx(tx)

Check failure on line 232 in packages/evm/jsonrpc/tracer_prestate.go

View workflow job for this annotation

GitHub Actions / Lint

shadow: declaration of "err" shadows declaration at line 201 (govet)
if err != nil {
return nil, err
}
result = append(result, TxTraceResult{TxHash: tx.Hash(), Result: csJSON})
}

res, err = json.Marshal(result)
}
} else {
Expand Down

0 comments on commit 917e3db

Please sign in to comment.