Skip to content

Commit

Permalink
trace API: commit state changes from InitializeBlockExecution (#12567)
Browse files Browse the repository at this point in the history
Duplicate #12559 into `main`
  • Loading branch information
yperbasis authored Nov 1, 2024
1 parent 244d1f4 commit eb1f470
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 44 deletions.
65 changes: 36 additions & 29 deletions turbo/jsonrpc/trace_adhoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1147,17 +1147,35 @@ func (api *TraceAPIImpl) CallMany(ctx context.Context, calls json.RawMessage, pa
return nil, fmt.Errorf("convert callParam to msg: %w", err)
}
}
results, _, err := api.doCallMany(ctx, dbtx, msgs, callParams, parentNrOrHash, nil, true /* gasBailout */, -1 /* all txn indices */, traceConfig)
return results, err

chainConfig, err := api.chainConfig(ctx, dbtx)
if err != nil {
return nil, err
}
stateReader, err := rpchelper.CreateStateReader(ctx, dbtx, api._blockReader, *parentNrOrHash, 0, api.filters, api.stateCache, chainConfig.ChainName)
if err != nil {
return nil, err
}
stateCache := shards.NewStateCache(
32, 0 /* no limit */) // this cache living only during current RPC call, but required to store state writes
cachedReader := state.NewCachedReader(stateReader, stateCache)
noop := state.NewNoopWriter()
cachedWriter := state.NewCachedWriter(noop, stateCache)
ibs := state.New(cachedReader)

return api.doCallMany(ctx, dbtx, stateReader, stateCache, cachedWriter, ibs,
msgs, callParams, parentNrOrHash, nil, true /* gasBailout */, -1 /* all txn indices */, traceConfig)
}

func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []types.Message, callParams []TraceCallParam,
func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, stateReader state.StateReader,
stateCache *shards.StateCache, cachedWriter state.StateWriter, ibs *state.IntraBlockState,
msgs []types.Message, callParams []TraceCallParam,
parentNrOrHash *rpc.BlockNumberOrHash, header *types.Header, gasBailout bool, txIndexNeeded int,
traceConfig *config.TraceConfig,
) ([]*TraceCallResult, *state.IntraBlockState, error) {
) ([]*TraceCallResult, error) {
chainConfig, err := api.chainConfig(ctx, dbtx)
if err != nil {
return nil, nil, err
return nil, err
}
engine := api.engine()

Expand All @@ -1167,27 +1185,16 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
}
blockNumber, hash, _, err := rpchelper.GetBlockNumber(ctx, *parentNrOrHash, dbtx, api._blockReader, api.filters)
if err != nil {
return nil, nil, err
}
stateReader, err := rpchelper.CreateStateReader(ctx, dbtx, api._blockReader, *parentNrOrHash, 0, api.filters, api.stateCache, chainConfig.ChainName)
if err != nil {
return nil, nil, err
return nil, err
}
stateCache := shards.NewStateCache(
32, 0 /* no limit */) // this cache living only during current RPC call, but required to store state writes
//cachedReader := stateReader
cachedReader := state.NewCachedReader(stateReader, stateCache)
noop := state.NewNoopWriter()
//cachedWriter := noop
cachedWriter := state.NewCachedWriter(noop, stateCache)
ibs := state.New(cachedReader)

parentHeader, err := api.headerByRPCNumber(ctx, rpc.BlockNumber(blockNumber), dbtx)
if err != nil {
return nil, nil, err
return nil, err
}
if parentHeader == nil {
return nil, nil, fmt.Errorf("parent header %d(%x) not found", blockNumber, hash)
return nil, fmt.Errorf("parent header %d(%x) not found", blockNumber, hash)
}

// Setup context so it may be cancelled the call has completed
Expand Down Expand Up @@ -1223,7 +1230,7 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
historicalStateReader.SetTxNum(baseTxNum + uint64(txIndex))
}
if err := libcommon.Stopped(ctx.Done()); err != nil {
return nil, nil, err
return nil, err
}

var traceTypeTrace, traceTypeStateDiff, traceTypeVmTrace bool
Expand All @@ -1237,7 +1244,7 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
case TraceTypeVmTrace:
traceTypeVmTrace = true
default:
return nil, nil, fmt.Errorf("unrecognized trace type: %s", traceType)
return nil, fmt.Errorf("unrecognized trace type: %s", traceType)
}
}

Expand All @@ -1247,7 +1254,7 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
var ot OeTracer
ot.config, err = parseOeTracerConfig(traceConfig)
if err != nil {
return nil, nil, err
return nil, err
}
ot.compat = api.compatibility
ot.r = traceResult
Expand Down Expand Up @@ -1296,7 +1303,7 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
var stateSyncEvents []*types.Message
stateSyncEvents, err = api.stateSyncEvents(ctx, dbtx, header.Hash(), blockNumber, chainConfig)
if err != nil {
return nil, nil, err
return nil, err
}

execResult, err = tracer.TraceBorStateSyncTxnTraceAPI(
Expand All @@ -1320,7 +1327,7 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
execResult, err = core.ApplyMessage(evm, msg, gp, true /* refunds */, gasBailout /*gasBailout*/)
}
if err != nil {
return nil, nil, fmt.Errorf("first run for txIndex %d error: %w", txIndex, err)
return nil, fmt.Errorf("first run for txIndex %d error: %w", txIndex, err)
}

chainRules := chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Time)
Expand All @@ -1329,21 +1336,21 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
initialIbs := state.New(cloneReader)
if !txFinalized {
if err = ibs.FinalizeTx(chainRules, sd); err != nil {
return nil, nil, err
return nil, err
}
}
sd.CompareStates(initialIbs, ibs)
if err = ibs.CommitBlock(chainRules, cachedWriter); err != nil {
return nil, nil, err
return nil, err
}
} else {
if !txFinalized {
if err = ibs.FinalizeTx(chainRules, noop); err != nil {
return nil, nil, err
return nil, err
}
}
if err = ibs.CommitBlock(chainRules, cachedWriter); err != nil {
return nil, nil, err
return nil, err
}
}
if !traceTypeTrace {
Expand All @@ -1357,7 +1364,7 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
}
}

return results, ibs, nil
return results, nil
}

// RawTransaction implements trace_rawTransaction.
Expand Down
36 changes: 21 additions & 15 deletions turbo/jsonrpc/trace_filtering.go
Original file line number Diff line number Diff line change
Expand Up @@ -757,24 +757,35 @@ func (api *TraceAPIImpl) callManyTransactions(
}

callParams := make([]TraceCallParam, 0, len(txs))
txNumsReader := rawdbv3.TxNums.WithCustomReadTxNumFunc(freezeblocks.ReadTxNumFuncFromBlockReader(ctx, api._blockReader))
reader, err := rpchelper.CreateHistoryStateReader(dbtx, txNumsReader, blockNumber, txIndex, cfg.ChainName)
if err != nil {
return nil, nil, err

parentHash := block.ParentHash()
parentNrOrHash := rpc.BlockNumberOrHash{
BlockNumber: &parentNo,
BlockHash: &parentHash,
RequireCanonical: true,
}

initialState := state.New(reader)
stateReader, err := rpchelper.CreateStateReader(ctx, dbtx, api._blockReader, parentNrOrHash, 0, api.filters, api.stateCache, cfg.ChainName)
if err != nil {
return nil, nil, err
}
stateCache := shards.NewStateCache(
32, 0 /* no limit */) // this cache living only during current RPC call, but required to store state writes
cachedReader := state.NewCachedReader(stateReader, stateCache)
noop := state.NewNoopWriter()
cachedWriter := state.NewCachedWriter(noop, stateCache)
ibs := state.New(cachedReader)

engine := api.engine()
consensusHeaderReader := consensuschain.NewReader(cfg, dbtx, nil, nil)
logger := log.New("trace_filtering")
err = core.InitializeBlockExecution(engine.(consensus.Engine), consensusHeaderReader, block.HeaderNoCopy(), cfg, initialState, logger, nil)
err = core.InitializeBlockExecution(engine.(consensus.Engine), consensusHeaderReader, block.HeaderNoCopy(), cfg, ibs, logger, nil)
if err != nil {
return nil, nil, err
}
if err = ibs.CommitBlock(rules, cachedWriter); err != nil {
return nil, nil, err
}

msgs := make([]types.Message, len(txs))
for i, txn := range txs {
Expand All @@ -795,7 +806,7 @@ func (api *TraceAPIImpl) callManyTransactions(
// gnosis might have a fee free account here
if msg.FeeCap().IsZero() && engine != nil {
syscall := func(contract common.Address, data []byte) ([]byte, error) {
return core.SysCallContract(contract, data, cfg, initialState, header, engine, true /* constCall */)
return core.SysCallContract(contract, data, cfg, ibs, header, engine, true /* constCall */)
}
msg.SetIsFree(engine.IsServiceTransaction(msg.From(), syscall))
}
Expand All @@ -810,20 +821,15 @@ func (api *TraceAPIImpl) callManyTransactions(
msgs[i] = msg
}

parentHash := block.ParentHash()

traces, lastState, cmErr := api.doCallMany(ctx, dbtx, msgs, callParams, &rpc.BlockNumberOrHash{
BlockNumber: &parentNo,
BlockHash: &parentHash,
RequireCanonical: true,
}, header, gasBailOut /* gasBailout */, txIndex, traceConfig)
traces, cmErr := api.doCallMany(ctx, dbtx, stateReader, stateCache, cachedWriter, ibs, msgs, callParams,
&parentNrOrHash, header, gasBailOut /* gasBailout */, txIndex, traceConfig)

if cmErr != nil {
return nil, nil, cmErr
}

syscall := func(contract common.Address, data []byte) ([]byte, error) {
return core.SysCallContract(contract, data, cfg, lastState, header, engine, false /* constCall */)
return core.SysCallContract(contract, data, cfg, ibs, header, engine, false /* constCall */)
}

return traces, syscall, nil
Expand Down

0 comments on commit eb1f470

Please sign in to comment.