Skip to content

Commit

Permalink
Remove parallel procesing for debug_traceBlock
Browse files Browse the repository at this point in the history
Because of preparing data for replaying transaction with EVM which is
slower with javascript tracer execution, deep copy of stateDB is created
and every transaction is replayed twice. So this is contra productive.
  • Loading branch information
jenikd committed Oct 31, 2023
1 parent c8590b9 commit c142a59
Showing 1 changed file with 14 additions and 57 deletions.
71 changes: 14 additions & 57 deletions ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ import (
"fmt"
"math/big"
"math/rand"
"runtime"
"strings"
"sync"
"time"

"github.com/Fantom-foundation/lachesis-base/hash"
Expand Down Expand Up @@ -2180,6 +2178,9 @@ func (api *PublicDebugAPI) traceTx(ctx context.Context, message evmcore.Message,
return nil, fmt.Errorf("tracing failed: %w", err)
}

// Finalize the state so any modifications are written to the trie
statedb.Finalise(vmenv.ChainConfig().IsByzantium(vmctx.BlockNumber) || vmenv.ChainConfig().IsEIP158(vmctx.BlockNumber))

// Depending on the tracer type, format and return the output.
switch tracer := tracer.(type) {
case *vm.StructLogger:
Expand Down Expand Up @@ -2222,13 +2223,6 @@ type txTraceResult struct {
Error string `json:"error,omitempty"` // Trace failure produced by the tracer
}

// txTraceTask represents a single transaction trace task when an entire block
// is being traced.
type txTraceTask struct {
statedb *state.StateDB // Intermediate state prepped for tracing
index int // Transaction offset in the block
}

// TraceBlockByNumber returns the structured logs created during the execution of
// EVM and returns them as a JSON object.
func (api *PublicDebugAPI) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*txTraceResult, error) {
Expand Down Expand Up @@ -2291,64 +2285,27 @@ func (api *PublicDebugAPI) traceBlock(ctx context.Context, block *evmcore.EvmBlo
signer = types.MakeSigner(api.b.ChainConfig(), block.Number)
txs = block.Transactions
results = make([]*txTraceResult, len(txs))

pend = new(sync.WaitGroup)
jobs = make(chan *txTraceTask, len(txs))
)
threads := runtime.NumCPU()
if threads > len(txs) {
threads = len(txs)
}

blockHeader := block.Header()
blockHash := block.Hash
for th := 0; th < threads; th++ {
pend.Add(1)
go func() {
defer pend.Done()
blockCtx := api.b.GetBlockContext(blockHeader)

// Fetch and execute the next transaction trace tasks
for task := range jobs {
msg, _ := txs[task.index].AsMessage(signer, block.BaseFee)
txctx := &tracers.Context{
BlockHash: blockHash,
TxIndex: task.index,
TxHash: txs[task.index].Hash(),
}
res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
if err != nil {
results[task.index] = &txTraceResult{Error: err.Error()}
continue
}
results[task.index] = &txTraceResult{Result: res}
}
}()
}

// Feed the transactions into the tracers and return
blockCtx := api.b.GetBlockContext(blockHeader)
var failed error
for i, tx := range txs {
// Send the trace task over for execution
jobs <- &txTraceTask{statedb: statedb.Copy(), index: i}

// Generate the next state snapshot fast without tracing
txctx := &tracers.Context{
BlockHash: blockHash,
TxIndex: i,
TxHash: txs[i].Hash(),
}
msg, _ := tx.AsMessage(signer, block.BaseFee)
statedb.Prepare(tx.Hash(), i)
vmenv := vm.NewEVM(blockCtx, evmcore.NewEVMTxContext(msg), statedb, api.b.ChainConfig(), opera.DefaultVMConfig)
if _, err := evmcore.ApplyMessage(vmenv, msg, new(evmcore.GasPool).AddGas(msg.Gas())); err != nil {
failed = err
break
res, err := api.traceTx(ctx, msg, txctx, blockCtx, statedb, config)
if err != nil {
results[i] = &txTraceResult{Error: err.Error()}
continue
}
// Finalize the state so any modifications are written to the trie
statedb.Finalise(vmenv.ChainConfig().IsByzantium(block.Number) || vmenv.ChainConfig().IsEIP158(block.Number))
}
close(jobs)
pend.Wait()

// If execution failed in between, abort
if failed != nil {
return nil, failed
results[i] = &txTraceResult{Result: res}
}
return results, nil
}
Expand Down

0 comments on commit c142a59

Please sign in to comment.