@@ -574,6 +574,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
574574 if block .NumberU64 () == 0 {
575575 return nil , errors .New ("genesis is not traceable" )
576576 }
577+ // Prepare base state
577578 parent , err := api .blockByNumberAndHash (ctx , rpc .BlockNumber (block .NumberU64 ()- 1 ), block .ParentHash ())
578579 if err != nil {
579580 return nil , err
@@ -588,21 +589,72 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
588589 }
589590 defer release ()
590591
592+ // JS tracers have high overhead. In this case run a parallel
593+ // process that generates states in one thread and traces txes
594+ // in separate worker threads.
595+ if config != nil && config .Tracer != nil && * config .Tracer != "" {
596+ if isJS := DefaultDirectory .IsJS (* config .Tracer ); isJS {
597+ return api .traceBlockParallel (ctx , block , statedb , config )
598+ }
599+ }
600+ // Native tracers have low overhead
601+ var (
602+ txs = block .Transactions ()
603+ blockHash = block .Hash ()
604+ is158 = api .backend .ChainConfig ().IsEIP158 (block .Number ())
605+ blockCtx = core .NewEVMBlockContext (block .Header (), api .chainContext (ctx ), nil )
606+ signer = types .MakeSigner (api .backend .ChainConfig (), block .Number ())
607+ results = make ([]* txTraceResult , len (txs ))
608+ )
609+ feeCapacity := state .GetTRC21FeeCapacityFromState (statedb )
610+ for i , tx := range txs {
611+ var balance * big.Int
612+ if tx .To () != nil {
613+ if tx .IsSkipNonceTransaction () {
614+ continue
615+ }
616+ if value , ok := feeCapacity [* tx .To ()]; ok {
617+ balance = value
618+ }
619+ }
620+ // Generate the next state snapshot fast without tracing
621+ msg , _ := tx .AsMessage (signer , balance , block .Number (), block .BaseFee ())
622+ txctx := & Context {
623+ BlockHash : blockHash ,
624+ TxIndex : i ,
625+ TxHash : tx .Hash (),
626+ }
627+ res , err := api .traceTx (ctx , msg , txctx , blockCtx , statedb , config )
628+ if err != nil {
629+ return nil , err
630+ }
631+ results [i ] = & txTraceResult {Result : res }
632+ // Finalize the state so any modifications are written to the trie
633+ // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
634+ statedb .Finalise (is158 )
635+ }
636+ return results , nil
637+ }
638+
639+ // traceBlockParallel is for tracers that have a high overhead (read JS tracers). One thread
640+ // runs along and executes txes without tracing enabled to generate their prestate.
641+ // Worker threads take the tasks and the prestate and trace them.
642+ func (api * API ) traceBlockParallel (ctx context.Context , block * types.Block , statedb * state.StateDB , config * TraceConfig ) ([]* txTraceResult , error ) {
591643 // Execute all the transaction contained within the block concurrently
592644 var (
593- signer = types .MakeSigner (api .backend .ChainConfig (), block .Number ())
594- txs = block .Transactions ()
595- results = make ([]* txTraceResult , len (txs ))
596- pend sync.WaitGroup
645+ txs = block .Transactions ()
646+ blockHash = block .Hash ()
647+ blockCtx = core .NewEVMBlockContext (block .Header (), api .chainContext (ctx ), nil )
648+ signer = types .MakeSigner (api .backend .ChainConfig (), block .Number ())
649+ results = make ([]* txTraceResult , len (txs ))
650+ pend sync.WaitGroup
597651 )
598652 threads := runtime .NumCPU ()
599653 if threads > len (txs ) {
600654 threads = len (txs )
601655 }
602656 jobs := make (chan * txTraceTask , threads )
603- blockHash := block .Hash ()
604657 for th := 0 ; th < threads ; th ++ {
605- blockCtx := core .NewEVMBlockContext (block .Header (), api .chainContext (ctx ), nil )
606658 pend .Add (1 )
607659 go func () {
608660 defer pend .Done ()
@@ -635,7 +687,6 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
635687 // Feed the transactions into the tracers and return
636688 feeCapacity := state .GetTRC21FeeCapacityFromState (statedb )
637689 var failed error
638- blockCtx := core .NewEVMBlockContext (block .Header (), api .chainContext (ctx ), nil )
639690txloop:
640691 for i , tx := range txs {
641692 // Send the trace task over for execution
@@ -795,7 +846,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex
795846 // Default tracer is the struct logger
796847 tracer = logger .NewStructLogger (config .Config )
797848 if config .Tracer != nil {
798- tracer , err = New (* config .Tracer , txctx , config .TracerConfig )
849+ tracer , err = DefaultDirectory . New (* config .Tracer , txctx , config .TracerConfig )
799850 if err != nil {
800851 return nil , err
801852 }
0 commit comments