@@ -445,12 +445,11 @@ func (api *API) TraceBlockFromFile(ctx context.Context, file string, config *Tra
445
445
// EVM against a block pulled from the pool of bad ones and returns them as a JSON
446
446
// object.
447
447
func (api * API ) TraceBadBlock (ctx context.Context , hash common.Hash , config * TraceConfig ) ([]* txTraceResult , error ) {
448
- for _ , block := range rawdb .ReadAllBadBlocks (api .backend .ChainDb ()) {
449
- if block .Hash () == hash {
450
- return api .traceBlock (ctx , block , config )
451
- }
448
+ block := rawdb .ReadBadBlock (api .backend .ChainDb (), hash )
449
+ if block == nil {
450
+ return nil , fmt .Errorf ("bad block %#x not found" , hash )
452
451
}
453
- return nil , fmt . Errorf ( "bad block %#x not found" , hash )
452
+ return api . traceBlock ( ctx , block , config )
454
453
}
455
454
456
455
// StandardTraceBlockToFile dumps the structured logs created during the
@@ -464,16 +463,72 @@ func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash,
464
463
return api .standardTraceBlockToFile (ctx , block , config )
465
464
}
466
465
466
+ // IntermediateRoots executes a block (bad- or canon- or side-), and returns a list
467
+ // of intermediate roots: the stateroot after each transaction.
468
+ func (api * API ) IntermediateRoots (ctx context.Context , hash common.Hash , config * TraceConfig ) ([]common.Hash , error ) {
469
+ block , _ := api .blockByHash (ctx , hash )
470
+ if block == nil {
471
+ // Check in the bad blocks
472
+ block = rawdb .ReadBadBlock (api .backend .ChainDb (), hash )
473
+ }
474
+ if block == nil {
475
+ return nil , fmt .Errorf ("block %#x not found" , hash )
476
+ }
477
+ if block .NumberU64 () == 0 {
478
+ return nil , errors .New ("genesis is not traceable" )
479
+ }
480
+ parent , err := api .blockByNumberAndHash (ctx , rpc .BlockNumber (block .NumberU64 ()- 1 ), block .ParentHash ())
481
+ if err != nil {
482
+ return nil , err
483
+ }
484
+ reexec := defaultTraceReexec
485
+ if config != nil && config .Reexec != nil {
486
+ reexec = * config .Reexec
487
+ }
488
+ statedb , err := api .backend .StateAtBlock (ctx , parent , reexec , nil , true )
489
+ if err != nil {
490
+ return nil , err
491
+ }
492
+ var (
493
+ roots []common.Hash
494
+ signer = types .MakeSigner (api .backend .ChainConfig (), block .Number ())
495
+ chainConfig = api .backend .ChainConfig ()
496
+ vmctx = core .NewEVMBlockContext (block .Header (), api .chainContext (ctx ), nil )
497
+ deleteEmptyObjects = chainConfig .IsEIP158 (block .Number ())
498
+ )
499
+ for i , tx := range block .Transactions () {
500
+ var (
501
+ msg , _ = tx .AsMessage (signer , block .BaseFee ())
502
+ txContext = core .NewEVMTxContext (msg )
503
+ vmenv = vm .NewEVM (vmctx , txContext , statedb , chainConfig , vm.Config {})
504
+ )
505
+ statedb .Prepare (tx .Hash (), i )
506
+ if _ , err := core .ApplyMessage (vmenv , msg , new (core.GasPool ).AddGas (msg .Gas ())); err != nil {
507
+ log .Warn ("Tracing intermediate roots did not complete" , "txindex" , i , "txhash" , tx .Hash (), "err" , err )
508
+ // We intentionally don't return the error here: if we do, then the RPC server will not
509
+ // return the roots. Most likely, the caller already knows that a certain transaction fails to
510
+ // be included, but still want the intermediate roots that led to that point.
511
+ // It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be
512
+ // executable.
513
+ // N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
514
+ return roots , nil
515
+ }
516
+ // calling IntermediateRoot will internally call Finalize on the state
517
+ // so any modifications are written to the trie
518
+ roots = append (roots , statedb .IntermediateRoot (deleteEmptyObjects ))
519
+ }
520
+ return roots , nil
521
+ }
522
+
467
523
// StandardTraceBadBlockToFile dumps the structured logs created during the
468
524
// execution of EVM against a block pulled from the pool of bad ones to the
469
525
// local file system and returns a list of files to the caller.
470
526
func (api * API ) StandardTraceBadBlockToFile (ctx context.Context , hash common.Hash , config * StdTraceConfig ) ([]string , error ) {
471
- for _ , block := range rawdb .ReadAllBadBlocks (api .backend .ChainDb ()) {
472
- if block .Hash () == hash {
473
- return api .standardTraceBlockToFile (ctx , block , config )
474
- }
527
+ block := rawdb .ReadBadBlock (api .backend .ChainDb (), hash )
528
+ if block == nil {
529
+ return nil , fmt .Errorf ("bad block %#x not found" , hash )
475
530
}
476
- return nil , fmt . Errorf ( "bad block %#x not found" , hash )
531
+ return api . standardTraceBlockToFile ( ctx , block , config )
477
532
}
478
533
479
534
// traceBlock configures a new tracer according to the provided configuration, and
0 commit comments