mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
parent
28550526ba
commit
98f6825514
2 changed files with 71 additions and 0 deletions
|
|
@ -429,6 +429,71 @@ func (api *API) TraceBlockFromFile(ctx context.Context, file string, config *Tra
|
|||
return api.TraceBlock(ctx, blob, config)
|
||||
}
|
||||
|
||||
// IntermediateRoots executes a block (bad- or canon- or side-), and returns a list
|
||||
// of intermediate roots: the stateroot after each transaction.
|
||||
func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) {
|
||||
block, _ := api.blockByHash(ctx, hash)
|
||||
if block == nil {
|
||||
return nil, fmt.Errorf("block %#x not found", hash)
|
||||
}
|
||||
if block.NumberU64() == 0 {
|
||||
return nil, errors.New("genesis is not traceable")
|
||||
}
|
||||
parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reexec := defaultTraceReexec
|
||||
if config != nil && config.Reexec != nil {
|
||||
reexec = *config.Reexec
|
||||
}
|
||||
statedb, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var (
|
||||
roots []common.Hash
|
||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
|
||||
chainConfig = api.backend.ChainConfig()
|
||||
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
|
||||
)
|
||||
feeCapacity := state.GetTRC21FeeCapacityFromState(statedb)
|
||||
for i, tx := range block.Transactions() {
|
||||
var balance *big.Int
|
||||
if tx.To() != nil {
|
||||
// Bypass the validation for trading and lending transactions as their nonce are not incremented
|
||||
if tx.IsSkipNonceTransaction() {
|
||||
continue
|
||||
}
|
||||
if value, ok := feeCapacity[*tx.To()]; ok {
|
||||
balance = value
|
||||
}
|
||||
}
|
||||
var (
|
||||
msg, _ = tx.AsMessage(signer, balance, block.Number(), block.BaseFee())
|
||||
txContext = core.NewEVMTxContext(msg)
|
||||
vmenv = vm.NewEVM(vmctx, txContext, statedb, nil, chainConfig, vm.Config{})
|
||||
)
|
||||
statedb.SetTxContext(tx.Hash(), i)
|
||||
owner := common.Address{}
|
||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), owner); err != nil {
|
||||
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
||||
// We intentionally don't return the error here: if we do, then the RPC server will not
|
||||
// return the roots. Most likely, the caller already knows that a certain transaction fails to
|
||||
// be included, but still want the intermediate roots that led to that point.
|
||||
// It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be
|
||||
// executable.
|
||||
// N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
|
||||
return roots, nil
|
||||
}
|
||||
// calling IntermediateRoot will internally call Finalize on the state
|
||||
// so any modifications are written to the trie
|
||||
roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects))
|
||||
}
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
// traceBlock configures a new tracer according to the provided configuration, and
|
||||
// executes all the transactions contained within. The return value will be one item
|
||||
// per transaction, dependent on the requestd tracer.
|
||||
|
|
|
|||
|
|
@ -420,6 +420,12 @@ web3._extend({
|
|||
params: 2,
|
||||
inputFormatter: [null, null]
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'intermediateRoots',
|
||||
call: 'debug_intermediateRoots',
|
||||
params: 2,
|
||||
inputFormatter: [null, null]
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'traceBlockByNumber',
|
||||
call: 'debug_traceBlockByNumber',
|
||||
|
|
|
|||
Loading…
Reference in a new issue