Skip to content

Commit

Permalink
Implement trace_block EP and conversion logic
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaliyb committed Nov 21, 2024
1 parent e5caf13 commit b861940
Show file tree
Hide file tree
Showing 8 changed files with 32,159 additions and 3 deletions.
9,797 changes: 9,797 additions & 0 deletions packages/evm/jsonrpc/debug_trace_block_sample.json

Large diffs are not rendered by default.

55 changes: 52 additions & 3 deletions packages/evm/jsonrpc/evmchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ func (e *EVMChain) traceTransaction(
return tracer.GetResult()
}

func (e *EVMChain) traceBlock(config *tracers.TraceConfig, block *types.Block) (any, error) {
func (e *EVMChain) debugTraceBlock(config *tracers.TraceConfig, block *types.Block) (any, error) {
iscBlock, iscRequestsInBlock, err := e.iscRequestsInBlock(block.NumberU64())
if err != nil {
return nil, err
Expand Down Expand Up @@ -791,7 +791,7 @@ func (e *EVMChain) TraceBlockByHash(blockHash common.Hash, config *tracers.Trace
return nil, fmt.Errorf("block not found: %s", blockHash.String())
}

return e.traceBlock(config, block)
return e.debugTraceBlock(config, block)
}

func (e *EVMChain) TraceBlockByNumber(blockNumber uint64, config *tracers.TraceConfig) (any, error) {
Expand All @@ -802,7 +802,7 @@ func (e *EVMChain) TraceBlockByNumber(blockNumber uint64, config *tracers.TraceC
return nil, fmt.Errorf("block not found: %d", blockNumber)
}

return e.traceBlock(config, block)
return e.debugTraceBlock(config, block)
}

func (e *EVMChain) getBlockByNumberOrHash(blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
Expand Down Expand Up @@ -851,6 +851,55 @@ func (e *EVMChain) GetBlockReceipts(blockNrOrHash rpc.BlockNumberOrHash) ([]*typ
return db.GetReceiptsByBlockNumber(block.NumberU64()), db.GetTransactionsByBlockNumber(block.NumberU64()), nil
}

func (e *EVMChain) TraceBlock(bn rpc.BlockNumber) (any, error) {
e.log.Debugf("TraceBlock(blockNumber=%v)", bn)

block, err := e.getBlockByNumberOrHash(rpc.BlockNumberOrHashWithNumber(bn))
if err != nil {
return nil, err
}
iscBlock, iscRequestsInBlock, err := e.iscRequestsInBlock(block.NumberU64())
if err != nil {
return nil, err
}

blockTxs, err := e.txsByBlockNumber(new(big.Int).SetUint64(block.NumberU64()))
if err != nil {
return nil, err
}

results := TraceBlock{
Jsonrpc: "2.0",
Result: make([]*Trace, 0),
ID: 1,
}

for i, tx := range blockTxs {
debugResultJSON, err := e.traceTransaction(
&tracers.TraceConfig{},
iscBlock,
iscRequestsInBlock,
tx,
uint64(i),
block.Hash(),
)

if err == nil {
var debugResult CallFrame
err = json.Unmarshal(debugResultJSON, &debugResult)
if err != nil {
return nil, err
}

blockHash := block.Hash()
txHash := tx.Hash()
results.Result = append(results.Result, convertToTrace(debugResult, &blockHash, block.NumberU64(), &txHash, uint64(i))...)
}
}

return results, nil
}

var maxUint32 = big.NewInt(math.MaxUint32)

// the first EVM block (number 0) is "minted" at ISC block index 0 (init chain)
Expand Down
69 changes: 69 additions & 0 deletions packages/evm/jsonrpc/jsonrpctest/jsonrpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package jsonrpctest

import (
"context"
"encoding/hex"
"encoding/json"
"math/big"
"slices"
Expand Down Expand Up @@ -791,6 +792,74 @@ func TestRPCTraceBlock(t *testing.T) {
require.NotEmpty(t, p)
}
})
t.Run("trace_block", func(t *testing.T) {
var res json.RawMessage
err = env.RawClient.CallContext(
context.Background(),
&res,
"trace_block",
rpc.BlockNumber(env.BlockNumber()),
)
require.NoError(t, err)

var result jsonrpc.TraceBlock
err = json.Unmarshal(res, &result)
require.NoError(t, err)
require.Len(t, result.Result, 4)

traceTx1Index := slices.IndexFunc(result.Result, func(v *jsonrpc.Trace) bool {
return *v.TransactionHash == tx1.Hash()
})
traceTx2Index := slices.IndexFunc(result.Result, func(v *jsonrpc.Trace) bool {
return *v.TransactionHash == tx2.Hash()
})

call11 := result.Result[traceTx1Index]
call12 := result.Result[traceTx1Index+1]
call21 := result.Result[traceTx2Index]
call22 := result.Result[traceTx2Index+1]

call11Action := call11.Action.(map[string]interface{})
call12Action := call12.Action.(map[string]interface{})
call21Action := call21.Action.(map[string]interface{})
call22Action := call22.Action.(map[string]interface{})

require.Equal(t, strings.ToLower(creatorAddress.String()), strings.ToLower(call11Action["from"].(string)))
require.Equal(t, strings.ToLower(contractAddress.String()), strings.ToLower(call11Action["to"].(string)))
require.Equal(t, "0x7b", call11Action["value"].(string))
expectedInput, err := contractABI.Pack("sendTo", common.Address{0x1}, big.NewInt(2)) //nolint:govet

Check failure on line 830 in packages/evm/jsonrpc/jsonrpctest/jsonrpc_test.go

View workflow job for this annotation

GitHub Actions / Lint

directive `//nolint:govet` is unused for linter "govet" (nolintlint)
require.NoError(t, err)
require.Equal(t, hex.EncodeToString(expectedInput), call11Action["input"].(string)[2:])
require.Empty(t, call11.Error)
require.Equal(t, 1, call11.Subtraces)
require.Equal(t, []int{}, call11.TraceAddress)

require.Equal(t, strings.ToLower(contractAddress.String()), strings.ToLower(call12Action["from"].(string)))
require.Equal(t, common.Address{0x1}.String(), strings.ToLower(call12Action["to"].(string)))
require.Equal(t, "0x2", call12Action["value"].(string))
require.Equal(t, "0x", call12Action["input"])
require.Empty(t, call12.Error)
require.Equal(t, 0, call12.Subtraces)
require.Equal(t, []int{0}, call12.TraceAddress)

require.Equal(t, strings.ToLower(creatorAddress2.String()), strings.ToLower(call21Action["from"].(string)))
require.Equal(t, strings.ToLower(contractAddress.String()), strings.ToLower(call21Action["to"].(string)))
require.Equal(t, "0x141", call21Action["value"].(string))
expectedInput, err = contractABI.Pack("sendTo", common.Address{0x2}, big.NewInt(3)) //nolint:govet

Check failure on line 848 in packages/evm/jsonrpc/jsonrpctest/jsonrpc_test.go

View workflow job for this annotation

GitHub Actions / Lint

directive `//nolint:govet` is unused for linter "govet" (nolintlint)
require.NoError(t, err)
require.Equal(t, hex.EncodeToString(expectedInput), call21Action["input"].(string)[2:])
require.Empty(t, call21.Error)
require.Equal(t, 1, call21.Subtraces)
require.Equal(t, []int{}, call21.TraceAddress)

require.Equal(t, strings.ToLower(contractAddress.String()), strings.ToLower(call22Action["from"].(string)))
require.Equal(t, common.Address{0x2}.String(), strings.ToLower(call22Action["to"].(string)))
require.Equal(t, "0x3", call22Action["value"].(string))
require.Equal(t, "0x", call22Action["input"])
require.Empty(t, call22.Error)
require.Equal(t, 0, call22.Subtraces)
require.Equal(t, []int{0}, call22.TraceAddress)
})
}

func TestRPCTraceBlockSingleCall(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions packages/evm/jsonrpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func NewServer(
{"debug", NewDebugService(evmChain, metrics)},
{"txpool", NewTxPoolService()},
{"evm", NewEVMService(evmChain)},
{"trace", NewTraceService(evmChain, metrics)},
} {
err := rpcsrv.RegisterName(srv.namespace, srv.service)
if err != nil {
Expand Down
19 changes: 19 additions & 0 deletions packages/evm/jsonrpc/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,25 @@ func (d *DebugService) GetRawBlock(blockNrOrHash rpc.BlockNumberOrHash) (interfa
})
}

type TraceService struct {
evmChain *EVMChain
metrics *metrics.ChainWebAPIMetrics
}

func NewTraceService(evmChain *EVMChain, metrics *metrics.ChainWebAPIMetrics) *TraceService {
return &TraceService{
evmChain: evmChain,
metrics: metrics,
}
}

// Block implements the `trace_block` RPC.
func (d *TraceService) Block(bn rpc.BlockNumber) (interface{}, error) {
return withMetrics(d.metrics, "trace_block", func() (interface{}, error) {
return d.evmChain.TraceBlock(bn)
})
}

type EVMService struct {
evmChain *EVMChain
}
Expand Down
Loading

0 comments on commit b861940

Please sign in to comment.