From 379b21f8258fcb13dacce0da5e97fe524828e0ac Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Mon, 4 Nov 2024 17:39:56 +0700 Subject: [PATCH] Gas used assert (#12596) --- erigon-lib/common/dbg/dbg_assert.go | 3 +++ polygon/tracer/trace_bor_state_sync_txn.go | 14 +++++++---- turbo/jsonrpc/tracing.go | 28 +++++++++++++++++----- turbo/transactions/tracing.go | 14 +++++++---- 4 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 erigon-lib/common/dbg/dbg_assert.go diff --git a/erigon-lib/common/dbg/dbg_assert.go b/erigon-lib/common/dbg/dbg_assert.go new file mode 100644 index 00000000000..618bebce464 --- /dev/null +++ b/erigon-lib/common/dbg/dbg_assert.go @@ -0,0 +1,3 @@ +package dbg + +var AssertEnabled = EnvBool("ERIGON_ASSERT", true) diff --git a/polygon/tracer/trace_bor_state_sync_txn.go b/polygon/tracer/trace_bor_state_sync_txn.go index a08372e847c..b87b481cab2 100644 --- a/polygon/tracer/trace_bor_state_sync_txn.go +++ b/polygon/tracer/trace_bor_state_sync_txn.go @@ -48,12 +48,12 @@ func TraceBorStateSyncTxnDebugAPI( stream *jsoniter.Stream, callTimeout time.Duration, msgs []*types.Message, -) error { +) (usedGas uint64, err error) { txCtx := initStateSyncTxContext(blockNum, blockHash) tracer, streaming, cancel, err := transactions.AssembleTracer(ctx, traceConfig, txCtx.TxHash, stream, callTimeout) if err != nil { stream.WriteNil() - return err + return usedGas, err } defer cancel() @@ -62,10 +62,16 @@ func TraceBorStateSyncTxnDebugAPI( rules := chainConfig.Rules(blockNum, blockTime) stateWriter := state.NewNoopWriter() execCb := func(evm *vm.EVM, refunds bool) (*evmtypes.ExecutionResult, error) { - return traceBorStateSyncTxn(ctx, ibs, stateWriter, msgs, evm, rules, txCtx, refunds) + res, err := traceBorStateSyncTxn(ctx, ibs, stateWriter, msgs, evm, rules, txCtx, refunds) + if err != nil { + return res, err + } + usedGas = res.UsedGas + return res, nil } - return transactions.ExecuteTraceTx(blockCtx, txCtx, ibs, traceConfig, chainConfig, stream, tracer, streaming, execCb) + err = transactions.ExecuteTraceTx(blockCtx, txCtx, ibs, traceConfig, chainConfig, stream, tracer, streaming, execCb) + return usedGas, err } func TraceBorStateSyncTxnTraceAPI( diff --git a/turbo/jsonrpc/tracing.go b/turbo/jsonrpc/tracing.go index 2a52dabb2b6..d8cfaaae2f7 100644 --- a/turbo/jsonrpc/tracing.go +++ b/turbo/jsonrpc/tracing.go @@ -22,6 +22,7 @@ import ( "fmt" "time" + "github.com/erigontech/erigon-lib/common/dbg" "github.com/holiman/uint256" jsoniter "github.com/json-iterator/go" @@ -113,6 +114,7 @@ func (api *PrivateDebugAPIImpl) traceBlock(ctx context.Context, blockNrOrHash rp stream.WriteArrayStart() txns := block.Transactions() + var borStateSyncTxn types.Transaction if *config.BorTraceEnabled { borStateSyncTxHash := bortypes.ComputeBorTxHash(block.NumberU64(), block.Hash()) @@ -133,6 +135,7 @@ func (api *PrivateDebugAPIImpl) traceBlock(ctx context.Context, blockNrOrHash rp } } + var usedGas uint64 for idx, txn := range txns { isBorStateSyncTxn := borStateSyncTxn == txn var txnHash common.Hash @@ -179,7 +182,8 @@ func (api *PrivateDebugAPIImpl) traceBlock(ctx context.Context, blockNrOrHash rp return err } - err = polygontracer.TraceBorStateSyncTxnDebugAPI( + var _usedGas uint64 + _usedGas, err = polygontracer.TraceBorStateSyncTxnDebugAPI( ctx, chainConfig, config, @@ -192,8 +196,11 @@ func (api *PrivateDebugAPIImpl) traceBlock(ctx context.Context, blockNrOrHash rp api.evmCallTimeout, stateSyncEvents, ) + usedGas += _usedGas } else { - err = transactions.TraceTx(ctx, msg, blockCtx, txCtx, ibs, config, chainConfig, stream, api.evmCallTimeout) + var _usedGas uint64 + _usedGas, err = transactions.TraceTx(ctx, msg, blockCtx, txCtx, ibs, config, chainConfig, stream, api.evmCallTimeout) + usedGas += _usedGas } if err == nil { err = ibs.FinalizeTx(rules, state.NewNoopWriter()) @@ -215,6 +222,12 @@ func (api *PrivateDebugAPIImpl) traceBlock(ctx context.Context, blockNrOrHash rp } } + if dbg.AssertEnabled { + if block.GasUsed() != usedGas { + panic(fmt.Errorf("assert: block.GasUsed() %d != usedGas %d. blockNum=%d", block.GasUsed(), usedGas, blockNumber)) + } + } + stream.WriteArrayEnd() if err := stream.Flush(); err != nil { return err @@ -321,7 +334,7 @@ func (api *PrivateDebugAPIImpl) TraceTransaction(ctx context.Context, hash commo return err } - return polygontracer.TraceBorStateSyncTxnDebugAPI( + _, err = polygontracer.TraceBorStateSyncTxnDebugAPI( ctx, chainConfig, config, @@ -334,6 +347,7 @@ func (api *PrivateDebugAPIImpl) TraceTransaction(ctx context.Context, hash commo api.evmCallTimeout, stateSyncEvents, ) + return err } msg, txCtx, err := transactions.ComputeTxContext(ibs, engine, rules, signer, block, chainConfig, txnIndex) @@ -343,7 +357,8 @@ func (api *PrivateDebugAPIImpl) TraceTransaction(ctx context.Context, hash commo } // Trace the transaction and return - return transactions.TraceTx(ctx, msg, blockCtx, txCtx, ibs, config, chainConfig, stream, api.evmCallTimeout) + _, err = transactions.TraceTx(ctx, msg, blockCtx, txCtx, ibs, config, chainConfig, stream, api.evmCallTimeout) + return err } // TraceCall implements debug_traceCall. Returns Geth style call traces. @@ -411,7 +426,8 @@ func (api *PrivateDebugAPIImpl) TraceCall(ctx context.Context, args ethapi.CallA blockCtx := transactions.NewEVMBlockContext(engine, header, blockNrOrHash.RequireCanonical, dbtx, api._blockReader, chainConfig) txCtx := core.NewEVMTxContext(msg) // Trace the transaction and return - return transactions.TraceTx(ctx, msg, blockCtx, txCtx, ibs, config, chainConfig, stream, api.evmCallTimeout) + _, err = transactions.TraceTx(ctx, msg, blockCtx, txCtx, ibs, config, chainConfig, stream, api.evmCallTimeout) + return err } func (api *PrivateDebugAPIImpl) TraceCallMany(ctx context.Context, bundles []Bundle, simulateContext StateContext, config *tracersConfig.TraceConfig, stream *jsoniter.Stream) error { @@ -574,7 +590,7 @@ func (api *PrivateDebugAPIImpl) TraceCallMany(ctx context.Context, bundles []Bun } txCtx = core.NewEVMTxContext(msg) ibs.SetTxContext(txnIndex) - err = transactions.TraceTx(ctx, msg, blockCtx, txCtx, evm.IntraBlockState(), config, chainConfig, stream, api.evmCallTimeout) + _, err = transactions.TraceTx(ctx, msg, blockCtx, txCtx, evm.IntraBlockState(), config, chainConfig, stream, api.evmCallTimeout) if err != nil { stream.WriteArrayEnd() stream.WriteArrayEnd() diff --git a/turbo/transactions/tracing.go b/turbo/transactions/tracing.go index 89d065836f8..96c75f0735e 100644 --- a/turbo/transactions/tracing.go +++ b/turbo/transactions/tracing.go @@ -107,21 +107,27 @@ func TraceTx( chainConfig *chain.Config, stream *jsoniter.Stream, callTimeout time.Duration, -) error { +) (usedGas uint64, err error) { tracer, streaming, cancel, err := AssembleTracer(ctx, config, txCtx.TxHash, stream, callTimeout) if err != nil { stream.WriteNil() - return err + return 0, err } defer cancel() execCb := func(evm *vm.EVM, refunds bool) (*evmtypes.ExecutionResult, error) { gp := new(core.GasPool).AddGas(message.Gas()).AddBlobGas(message.BlobGas()) - return core.ApplyMessage(evm, message, gp, refunds, false /* gasBailout */) + res, err := core.ApplyMessage(evm, message, gp, refunds, false /* gasBailout */) + if err != nil { + return res, err + } + usedGas = res.UsedGas + return res, nil } - return ExecuteTraceTx(blockCtx, txCtx, ibs, config, chainConfig, stream, tracer, streaming, execCb) + err = ExecuteTraceTx(blockCtx, txCtx, ibs, config, chainConfig, stream, tracer, streaming, execCb) + return usedGas, err } func AssembleTracer(