Skip to content

Commit 98f6825

Browse files
authored
eth/tracers: implement debug.intermediateRoots ethereum#23594 (#1260)
1 parent 2855052 commit 98f6825

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

eth/tracers/api.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,71 @@ func (api *API) TraceBlockFromFile(ctx context.Context, file string, config *Tra
429429
return api.TraceBlock(ctx, blob, config)
430430
}
431431

432+
// IntermediateRoots executes a block (bad- or canon- or side-), and returns a list
433+
// of intermediate roots: the stateroot after each transaction.
434+
func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) {
435+
block, _ := api.blockByHash(ctx, hash)
436+
if block == nil {
437+
return nil, fmt.Errorf("block %#x not found", hash)
438+
}
439+
if block.NumberU64() == 0 {
440+
return nil, errors.New("genesis is not traceable")
441+
}
442+
parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
443+
if err != nil {
444+
return nil, err
445+
}
446+
reexec := defaultTraceReexec
447+
if config != nil && config.Reexec != nil {
448+
reexec = *config.Reexec
449+
}
450+
statedb, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true)
451+
if err != nil {
452+
return nil, err
453+
}
454+
var (
455+
roots []common.Hash
456+
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
457+
chainConfig = api.backend.ChainConfig()
458+
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
459+
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
460+
)
461+
feeCapacity := state.GetTRC21FeeCapacityFromState(statedb)
462+
for i, tx := range block.Transactions() {
463+
var balance *big.Int
464+
if tx.To() != nil {
465+
// Bypass the validation for trading and lending transactions as their nonce are not incremented
466+
if tx.IsSkipNonceTransaction() {
467+
continue
468+
}
469+
if value, ok := feeCapacity[*tx.To()]; ok {
470+
balance = value
471+
}
472+
}
473+
var (
474+
msg, _ = tx.AsMessage(signer, balance, block.Number(), block.BaseFee())
475+
txContext = core.NewEVMTxContext(msg)
476+
vmenv = vm.NewEVM(vmctx, txContext, statedb, nil, chainConfig, vm.Config{})
477+
)
478+
statedb.SetTxContext(tx.Hash(), i)
479+
owner := common.Address{}
480+
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), owner); err != nil {
481+
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
482+
// We intentionally don't return the error here: if we do, then the RPC server will not
483+
// return the roots. Most likely, the caller already knows that a certain transaction fails to
484+
// be included, but still want the intermediate roots that led to that point.
485+
// It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be
486+
// executable.
487+
// N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
488+
return roots, nil
489+
}
490+
// calling IntermediateRoot will internally call Finalize on the state
491+
// so any modifications are written to the trie
492+
roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects))
493+
}
494+
return roots, nil
495+
}
496+
432497
// traceBlock configures a new tracer according to the provided configuration, and
433498
// executes all the transactions contained within. The return value will be one item
434499
// per transaction, dependent on the requestd tracer.

internal/web3ext/web3ext.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,12 @@ web3._extend({
420420
params: 2,
421421
inputFormatter: [null, null]
422422
}),
423+
new web3._extend.Method({
424+
name: 'intermediateRoots',
425+
call: 'debug_intermediateRoots',
426+
params: 2,
427+
inputFormatter: [null, null]
428+
}),
423429
new web3._extend.Method({
424430
name: 'traceBlockByNumber',
425431
call: 'debug_traceBlockByNumber',

0 commit comments

Comments
 (0)