Skip to content

Commit

Permalink
feat(zkevm_api): move trace method to debug api closes erigontech#1228 (
Browse files Browse the repository at this point in the history
  • Loading branch information
revitteth authored Sep 25, 2024
1 parent d5d1d43 commit 701f4d2
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 122 deletions.
2 changes: 1 addition & 1 deletion cmd/rpcdaemon/commands/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func APIList(db kv.RoDB, borDb kv.RoDB, eth rpchelper.ApiBackend, txPool txpool.
erigonImpl := NewErigonAPI(base, db, eth)
txpoolImpl := NewTxPoolAPI(base, db, txPool, rawPool, rpcUrl)
netImpl := NewNetAPIImpl(eth)
debugImpl := NewPrivateDebugAPI(base, db, cfg.Gascap)
debugImpl := NewPrivateDebugAPI(base, db, cfg.Gascap, ethCfg)
traceImpl := NewTraceAPI(base, db, &cfg)
web3Impl := NewWeb3APIImpl(eth)
dbImpl := NewDBAPIImpl() /* deprecated */
Expand Down
6 changes: 5 additions & 1 deletion cmd/rpcdaemon/commands/debug_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/ledgerwatch/erigon/rpc"
"github.com/ledgerwatch/erigon/turbo/adapter/ethapi"
"github.com/ledgerwatch/erigon/turbo/transactions"
"github.com/ledgerwatch/erigon/eth/ethconfig"
)

// AccountRangeMaxResults is the maximum number of results to be returned per call
Expand All @@ -37,21 +38,24 @@ type PrivateDebugAPI interface {
GetModifiedAccountsByHash(_ context.Context, startHash common.Hash, endHash *common.Hash) ([]common.Address, error)
TraceCall(ctx context.Context, args ethapi.CallArgs, blockNrOrHash rpc.BlockNumberOrHash, config *tracers.TraceConfig_ZkEvm, stream *jsoniter.Stream) error
AccountAt(ctx context.Context, blockHash common.Hash, txIndex uint64, account common.Address) (*AccountResult, error)
TraceTransactionCounters(ctx context.Context, hash common.Hash, config *tracers.TraceConfig_ZkEvm, stream *jsoniter.Stream) error
}

// PrivateDebugAPIImpl is implementation of the PrivateDebugAPI interface based on remote Db access
type PrivateDebugAPIImpl struct {
*BaseAPI
db kv.RoDB
GasCap uint64
config *ethconfig.Config
}

// NewPrivateDebugAPI returns PrivateDebugAPIImpl instance
func NewPrivateDebugAPI(base *BaseAPI, db kv.RoDB, gascap uint64) *PrivateDebugAPIImpl {
func NewPrivateDebugAPI(base *BaseAPI, db kv.RoDB, gascap uint64, config *ethconfig.Config) *PrivateDebugAPIImpl {
return &PrivateDebugAPIImpl{
BaseAPI: base,
db: db,
GasCap: gascap,
config: config,
}
}

Expand Down
115 changes: 115 additions & 0 deletions cmd/rpcdaemon/commands/tracing_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,118 @@ func (api *PrivateDebugAPIImpl) TraceCallMany(ctx context.Context, bundles []Bun
stream.WriteArrayEnd()
return nil
}

// TraceTransaction implements debug_traceTransaction. Returns Geth style transaction traces.
func (api *PrivateDebugAPIImpl) TraceTransactionCounters(ctx context.Context, hash common.Hash, config *tracers.TraceConfig_ZkEvm, stream *jsoniter.Stream) error {
tx, err := api.db.BeginRo(ctx)
if err != nil {
stream.WriteNil()
return err
}
defer tx.Rollback()
chainConfig, err := api.chainConfig(tx)
if err != nil {
stream.WriteNil()
return err
}
// Retrieve the transaction and assemble its EVM context
blockNum, ok, err := api.txnLookup(ctx, tx, hash)
if err != nil {
stream.WriteNil()
return err
}
if !ok {
stream.WriteNil()
return nil
}

// check pruning to ensure we have history at this block level
if err = api.BaseAPI.checkPruneHistory(tx, blockNum); err != nil {
stream.WriteNil()
return err
}

// Private API returns 0 if transaction is not found.
if blockNum == 0 && chainConfig.Bor != nil {
blockNumPtr, err := rawdb.ReadBorTxLookupEntry(tx, hash)
if err != nil {
stream.WriteNil()
return err
}
if blockNumPtr == nil {
stream.WriteNil()
return nil
}
blockNum = *blockNumPtr
}
block, err := api.blockByNumberWithSenders(tx, blockNum)
if err != nil {
stream.WriteNil()
return err
}
if block == nil {
stream.WriteNil()
return nil
}
var txnIndex uint64
var txn types.Transaction
for i, transaction := range block.Transactions() {
if transaction.Hash() == hash {
txnIndex = uint64(i)
txn = transaction
break
}
}
if txn == nil {
borTx, _, _, _, err := rawdb.ReadBorTransaction(tx, hash)
if err != nil {
stream.WriteNil()
return err
}

if borTx != nil {
stream.WriteNil()
return nil
}
stream.WriteNil()
return fmt.Errorf("transaction %#x not found", hash)
}
engine := api.engine()

txEnv, err := transactions.ComputeTxEnv_ZkEvm(ctx, engine, block, chainConfig, api._blockReader, tx, int(txnIndex), api.historyV3(tx))
if err != nil {
stream.WriteNil()
return err
}

// counters work
hermezDb := hermez_db.NewHermezDbReader(tx)
forkId, err := hermezDb.GetForkIdByBlockNum(blockNum)
if err != nil {
stream.WriteNil()
return err
}

smtDepth, err := getSmtDepth(hermezDb, blockNum, config)
if err != nil {
stream.WriteNil()
return err
}

txCounters := vm.NewTransactionCounter(txn, int(smtDepth), uint16(forkId), api.config.Zk.VirtualCountersSmtReduction, false)
batchCounters := vm.NewBatchCounterCollector(int(smtDepth), uint16(forkId), api.config.Zk.VirtualCountersSmtReduction, false, nil)

if _, err = batchCounters.AddNewTransactionCounters(txCounters); err != nil {
stream.WriteNil()
return err
}

// set tracer to counter tracer
if config == nil {
config = &tracers.TraceConfig_ZkEvm{}
}
config.CounterCollector = txCounters

// Trace the transaction and return
return transactions.TraceTx(ctx, txEnv.Msg, txEnv.BlockContext, txEnv.TxContext, txEnv.Ibs, config, chainConfig, stream, api.evmCallTimeout)
}
3 changes: 0 additions & 3 deletions cmd/rpcdaemon/commands/zkevm_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/gateway-fm/cdk-erigon-lib/common/hexutility"
"github.com/gateway-fm/cdk-erigon-lib/kv"
"github.com/gateway-fm/cdk-erigon-lib/kv/memdb"
jsoniter "github.com/json-iterator/go"
zktypes "github.com/ledgerwatch/erigon/zk/types"
"github.com/ledgerwatch/log/v3"

Expand All @@ -26,7 +25,6 @@ import (
"github.com/ledgerwatch/erigon/eth/ethconfig"
"github.com/ledgerwatch/erigon/eth/stagedsync"
"github.com/ledgerwatch/erigon/eth/stagedsync/stages"
"github.com/ledgerwatch/erigon/eth/tracers"
"github.com/ledgerwatch/erigon/rpc"
smtDb "github.com/ledgerwatch/erigon/smt/pkg/db"
smt "github.com/ledgerwatch/erigon/smt/pkg/smt"
Expand Down Expand Up @@ -70,7 +68,6 @@ type ZkEvmAPI interface {
GetExitRootsByGER(ctx context.Context, globalExitRoot common.Hash) (*ZkExitRoots, error)
GetL2BlockInfoTree(ctx context.Context, blockNum rpc.BlockNumberOrHash) (json.RawMessage, error)
EstimateCounters(ctx context.Context, argsOrNil *zkevmRPCTransaction) (json.RawMessage, error)
TraceTransactionCounters(ctx context.Context, hash common.Hash, config *tracers.TraceConfig_ZkEvm, stream *jsoniter.Stream) error
GetBatchCountersByNumber(ctx context.Context, batchNumRpc rpc.BlockNumber) (res json.RawMessage, err error)
GetExitRootTable(ctx context.Context) ([]l1InfoTreeData, error)
GetVersionHistory(ctx context.Context) (json.RawMessage, error)
Expand Down
117 changes: 0 additions & 117 deletions cmd/rpcdaemon/commands/zkevm_counters.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/gateway-fm/cdk-erigon-lib/common/hexutility"
"github.com/gateway-fm/cdk-erigon-lib/kv"
"github.com/holiman/uint256"
jsoniter "github.com/json-iterator/go"
"github.com/ledgerwatch/erigon/chain"
"github.com/ledgerwatch/erigon/common/hexutil"
"github.com/ledgerwatch/erigon/eth/tracers"
Expand All @@ -24,7 +23,6 @@ import (
"github.com/ledgerwatch/erigon/core/vm"
"github.com/ledgerwatch/erigon/core/vm/evmtypes"
"github.com/ledgerwatch/erigon/turbo/rpchelper"
"github.com/ledgerwatch/erigon/turbo/transactions"
"github.com/ledgerwatch/erigon/zk/hermez_db"
)

Expand Down Expand Up @@ -301,121 +299,6 @@ func populateCounters(collected *vm.Counters, execResult *core.ExecutionResult,
return resJson, nil
}

// TraceTransaction implements debug_traceTransaction. Returns Geth style transaction traces.
func (api *ZkEvmAPIImpl) TraceTransactionCounters(ctx context.Context, hash common.Hash, config *tracers.TraceConfig_ZkEvm, stream *jsoniter.Stream) error {
tx, err := api.db.BeginRo(ctx)
if err != nil {
stream.WriteNil()
return err
}
defer tx.Rollback()
chainConfig, err := api.ethApi.chainConfig(tx)
if err != nil {
stream.WriteNil()
return err
}
// Retrieve the transaction and assemble its EVM context
blockNum, ok, err := api.ethApi.txnLookup(ctx, tx, hash)
if err != nil {
stream.WriteNil()
return err
}
if !ok {
stream.WriteNil()
return nil
}

// check pruning to ensure we have history at this block level
if err = api.ethApi.BaseAPI.checkPruneHistory(tx, blockNum); err != nil {
stream.WriteNil()
return err
}

// Private API returns 0 if transaction is not found.
if blockNum == 0 && chainConfig.Bor != nil {
blockNumPtr, err := rawdb.ReadBorTxLookupEntry(tx, hash)
if err != nil {
stream.WriteNil()
return err
}
if blockNumPtr == nil {
stream.WriteNil()
return nil
}
blockNum = *blockNumPtr
}
block, err := api.ethApi.blockByNumberWithSenders(tx, blockNum)
if err != nil {
stream.WriteNil()
return err
}
if block == nil {
stream.WriteNil()
return nil
}
var txnIndex uint64
var txn types.Transaction
for i, transaction := range block.Transactions() {
if transaction.Hash() == hash {
txnIndex = uint64(i)
txn = transaction
break
}
}
if txn == nil {
borTx, _, _, _, err := rawdb.ReadBorTransaction(tx, hash)
if err != nil {
stream.WriteNil()
return err
}

if borTx != nil {
stream.WriteNil()
return nil
}
stream.WriteNil()
return fmt.Errorf("transaction %#x not found", hash)
}
engine := api.ethApi.engine()

txEnv, err := transactions.ComputeTxEnv_ZkEvm(ctx, engine, block, chainConfig, api.ethApi._blockReader, tx, int(txnIndex), api.ethApi.historyV3(tx))
if err != nil {
stream.WriteNil()
return err
}

// counters work
hermezDb := hermez_db.NewHermezDbReader(tx)
forkId, err := hermezDb.GetForkIdByBlockNum(blockNum)
if err != nil {
stream.WriteNil()
return err
}

smtDepth, err := getSmtDepth(hermezDb, blockNum, config)
if err != nil {
stream.WriteNil()
return err
}

txCounters := vm.NewTransactionCounter(txn, int(smtDepth), uint16(forkId), api.config.Zk.VirtualCountersSmtReduction, false)
batchCounters := vm.NewBatchCounterCollector(int(smtDepth), uint16(forkId), api.config.Zk.VirtualCountersSmtReduction, false, nil)

if _, err = batchCounters.AddNewTransactionCounters(txCounters); err != nil {
stream.WriteNil()
return err
}

// set tracer to counter tracer
if config == nil {
config = &tracers.TraceConfig_ZkEvm{}
}
config.CounterCollector = txCounters

// Trace the transaction and return
return transactions.TraceTx(ctx, txEnv.Msg, txEnv.BlockContext, txEnv.TxContext, txEnv.Ibs, config, chainConfig, stream, api.ethApi.evmCallTimeout)
}

func getSmtDepth(hermezDb *hermez_db.HermezDbReader, blockNum uint64, config *tracers.TraceConfig_ZkEvm) (int, error) {
var smtDepth int
if config != nil && config.SmtDepth != nil {
Expand Down

0 comments on commit 701f4d2

Please sign in to comment.