erigon-pulse/cmd/rpcdaemon/commands/otterscan_generic_tracer.go

76 lines
2.2 KiB
Go

package commands
import (
"context"
"github.com/ledgerwatch/erigon-lib/chain"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/log/v3"
"github.com/ledgerwatch/erigon/core"
"github.com/ledgerwatch/erigon/core/state"
"github.com/ledgerwatch/erigon/core/systemcontracts"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/core/vm"
"github.com/ledgerwatch/erigon/turbo/shards"
)
type GenericTracer interface {
vm.EVMLogger
SetTransaction(tx types.Transaction)
Found() bool
}
func (api *OtterscanAPIImpl) genericTracer(dbtx kv.Tx, ctx context.Context, blockNum uint64, chainConfig *chain.Config, tracer GenericTracer) error {
block, err := api.blockByNumberWithSenders(dbtx, blockNum)
if err != nil {
return err
}
if block == nil {
return nil
}
reader := state.NewPlainState(dbtx, blockNum, systemcontracts.SystemContractCodeLookup[chainConfig.ChainName])
stateCache := shards.NewStateCache(32, 0 /* no limit */)
cachedReader := state.NewCachedReader(reader, stateCache)
noop := state.NewNoopWriter()
cachedWriter := state.NewCachedWriter(noop, stateCache)
ibs := state.New(cachedReader)
signer := types.MakeSigner(chainConfig, blockNum)
getHeader := func(hash libcommon.Hash, number uint64) *types.Header {
h, e := api._blockReader.Header(ctx, dbtx, hash, number)
if e != nil {
log.Error("getHeader error", "number", number, "hash", hash, "err", e)
}
return h
}
engine := api.engine()
header := block.Header()
rules := chainConfig.Rules(block.NumberU64(), header.Time)
for idx, tx := range block.Transactions() {
ibs.Prepare(tx.Hash(), block.Hash(), idx)
msg, _ := tx.AsMessage(*signer, header.BaseFee, rules)
BlockContext := core.NewEVMBlockContext(header, core.GetHashFn(header, getHeader), engine, nil)
TxContext := core.NewEVMTxContext(msg)
vmenv := vm.NewEVM(BlockContext, TxContext, ibs, chainConfig, vm.Config{Debug: true, Tracer: tracer})
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.GetGas()), true /* refunds */, false /* gasBailout */); err != nil {
return err
}
_ = ibs.FinalizeTx(rules, cachedWriter)
if tracer.Found() {
tracer.SetTransaction(tx)
return nil
}
}
return nil
}