2021-01-25 07:36:39 -06:00
// Copyright 2021 The go-ethereum Authors
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
2021-01-25 07:36:39 -06:00
package tracers
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
import (
2018-10-15 05:28:44 -05:00
"bufio"
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
"bytes"
"context"
"errors"
"fmt"
2018-10-15 05:28:44 -05:00
"os"
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
"runtime"
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
2021-01-25 07:36:39 -06:00
"github.com/ethereum/go-ethereum/consensus"
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
"github.com/ethereum/go-ethereum/core"
2018-05-07 06:35:06 -05:00
"github.com/ethereum/go-ethereum/core/rawdb"
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
2021-11-25 06:17:09 -06:00
"github.com/ethereum/go-ethereum/eth/tracers/logger"
2021-01-25 07:36:39 -06:00
"github.com/ethereum/go-ethereum/ethdb"
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
2020-10-23 01:26:57 -05:00
"github.com/ethereum/go-ethereum/params"
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
)
const (
// defaultTraceTimeout is the amount of time a single transaction can execute
// by default before being forcefully aborted.
defaultTraceTimeout = 5 * time . Second
// defaultTraceReexec is the number of blocks the tracer is willing to go back
// and reexecute to produce missing historical state necessary to run a specific
// trace.
defaultTraceReexec = uint64 ( 128 )
2021-11-04 12:54:00 -05:00
// defaultTracechainMemLimit is the size of the triedb, at which traceChain
// switches over and tries to use a disk-backed database instead of building
// on top of memory.
// For non-archive nodes, this limit _will_ be overblown, as disk-backed tries
// will only be found every ~15K blocks or so.
defaultTracechainMemLimit = common . StorageSize ( 500 * 1024 * 1024 )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
)
2021-01-25 07:36:39 -06:00
// Backend interface provides the common API services (that are provided by
// both full and light clients) with access to necessary functions.
type Backend interface {
HeaderByHash ( ctx context . Context , hash common . Hash ) ( * types . Header , error )
HeaderByNumber ( ctx context . Context , number rpc . BlockNumber ) ( * types . Header , error )
BlockByHash ( ctx context . Context , hash common . Hash ) ( * types . Block , error )
BlockByNumber ( ctx context . Context , number rpc . BlockNumber ) ( * types . Block , error )
GetTransaction ( ctx context . Context , txHash common . Hash ) ( * types . Transaction , common . Hash , uint64 , uint64 , error )
RPCGasCap ( ) uint64
ChainConfig ( ) * params . ChainConfig
Engine ( ) consensus . Engine
ChainDb ( ) ethdb . Database
2021-11-04 12:54:00 -05:00
// StateAtBlock returns the state corresponding to the stateroot of the block.
// N.B: For executing transactions on block N, the required stateRoot is block N-1,
// so this method should be called with the parent.
StateAtBlock ( ctx context . Context , block * types . Block , reexec uint64 , base * state . StateDB , checkLive , preferDisk bool ) ( * state . StateDB , error )
2021-04-07 02:30:26 -05:00
StateAtTransaction ( ctx context . Context , block * types . Block , txIndex int , reexec uint64 ) ( core . Message , vm . BlockContext , * state . StateDB , error )
2021-01-25 07:36:39 -06:00
}
// API is the collection of tracing APIs exposed over the private debugging endpoint.
type API struct {
backend Backend
}
// NewAPI creates a new API definition for the tracing methods of the Ethereum service.
func NewAPI ( backend Backend ) * API {
return & API { backend : backend }
}
type chainContext struct {
api * API
ctx context . Context
}
func ( context * chainContext ) Engine ( ) consensus . Engine {
return context . api . backend . Engine ( )
}
func ( context * chainContext ) GetHeader ( hash common . Hash , number uint64 ) * types . Header {
header , err := context . api . backend . HeaderByNumber ( context . ctx , rpc . BlockNumber ( number ) )
if err != nil {
return nil
}
if header . Hash ( ) == hash {
return header
}
header , err = context . api . backend . HeaderByHash ( context . ctx , hash )
if err != nil {
return nil
}
return header
}
// chainContext construts the context reader which is used by the evm for reading
// the necessary chain context.
func ( api * API ) chainContext ( ctx context . Context ) core . ChainContext {
return & chainContext { api : api , ctx : ctx }
}
// blockByNumber is the wrapper of the chain access function offered by the backend.
// It will return an error if the block is not found.
func ( api * API ) blockByNumber ( ctx context . Context , number rpc . BlockNumber ) ( * types . Block , error ) {
block , err := api . backend . BlockByNumber ( ctx , number )
if err != nil {
return nil , err
}
if block == nil {
return nil , fmt . Errorf ( "block #%d not found" , number )
}
return block , nil
}
// blockByHash is the wrapper of the chain access function offered by the backend.
// It will return an error if the block is not found.
func ( api * API ) blockByHash ( ctx context . Context , hash common . Hash ) ( * types . Block , error ) {
block , err := api . backend . BlockByHash ( ctx , hash )
if err != nil {
return nil , err
}
if block == nil {
return nil , fmt . Errorf ( "block %s not found" , hash . Hex ( ) )
}
return block , nil
}
// blockByNumberAndHash is the wrapper of the chain access function offered by
// the backend. It will return an error if the block is not found.
//
// Note this function is friendly for the light client which can only retrieve the
// historical(before the CHT) header/block by number.
func ( api * API ) blockByNumberAndHash ( ctx context . Context , number rpc . BlockNumber , hash common . Hash ) ( * types . Block , error ) {
block , err := api . blockByNumber ( ctx , number )
if err != nil {
return nil , err
}
if block . Hash ( ) == hash {
return block , nil
}
return api . blockByHash ( ctx , hash )
}
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// TraceConfig holds extra parameters to trace functions.
type TraceConfig struct {
2021-11-25 06:17:09 -06:00
* logger . Config
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
Tracer * string
Timeout * string
Reexec * uint64
}
2021-04-21 02:21:22 -05:00
// TraceCallConfig is the config for traceCall API. It holds one more
// field to override the state for tracing.
type TraceCallConfig struct {
2021-11-25 06:17:09 -06:00
* logger . Config
2021-04-21 02:21:22 -05:00
Tracer * string
Timeout * string
Reexec * uint64
StateOverrides * ethapi . StateOverride
2022-06-02 04:39:36 -05:00
BlockOverrides * ethapi . BlockOverrides
2021-04-21 02:21:22 -05:00
}
2018-10-15 05:28:44 -05:00
// StdTraceConfig holds extra parameters to standard-json trace functions.
type StdTraceConfig struct {
2021-11-25 06:17:09 -06:00
logger . Config
2018-10-15 05:28:44 -05:00
Reexec * uint64
2018-12-10 04:32:40 -06:00
TxHash common . Hash
2018-10-15 05:28:44 -05:00
}
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// txTraceResult is the result of a single transaction trace.
type txTraceResult struct {
Result interface { } ` json:"result,omitempty" ` // Trace results produced by the tracer
Error string ` json:"error,omitempty" ` // Trace failure produced by the tracer
}
// blockTraceTask represents a single block trace task when an entire chain is
// being traced.
type blockTraceTask struct {
statedb * state . StateDB // Intermediate state prepped for tracing
block * types . Block // Block to trace the transactions from
2021-04-07 02:30:26 -05:00
rootref common . Hash // Trie root reference held for this task
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
results [ ] * txTraceResult // Trace results procudes by the task
}
// blockTraceResult represets the results of tracing a single block when an entire
// chain is being traced.
type blockTraceResult struct {
Block hexutil . Uint64 ` json:"block" ` // Block number corresponding to this trace
Hash common . Hash ` json:"hash" ` // Block hash corresponding to this trace
Traces [ ] * txTraceResult ` json:"traces" ` // Trace results produced by the task
}
// txTraceTask represents a single transaction trace task when an entire block
// is being traced.
type txTraceTask struct {
statedb * state . StateDB // Intermediate state prepped for tracing
index int // Transaction offset in the block
}
// TraceChain returns the structured logs created during the execution of EVM
// between two blocks (excluding start) and returns them as a JSON object.
2021-01-25 07:36:39 -06:00
func ( api * API ) TraceChain ( ctx context . Context , start , end rpc . BlockNumber , config * TraceConfig ) ( * rpc . Subscription , error ) { // Fetch the block interval that we want to trace
from , err := api . blockByNumber ( ctx , start )
if err != nil {
return nil , err
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
2021-01-25 07:36:39 -06:00
to , err := api . blockByNumber ( ctx , end )
if err != nil {
return nil , err
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
2018-08-21 02:48:53 -05:00
if from . Number ( ) . Cmp ( to . Number ( ) ) >= 0 {
return nil , fmt . Errorf ( "end block (#%d) needs to come after start block (#%d)" , end , start )
}
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
return api . traceChain ( ctx , from , to , config )
}
// traceChain configures a new tracer according to the provided configuration, and
// executes all the transactions contained within. The return value will be one item
2018-09-19 11:10:40 -05:00
// per transaction, dependent on the requested tracer.
2021-01-25 07:36:39 -06:00
func ( api * API ) traceChain ( ctx context . Context , start , end * types . Block , config * TraceConfig ) ( * rpc . Subscription , error ) {
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// Tracing a chain is a **long** operation, only do with subscriptions
notifier , supported := rpc . NotifierFromContext ( ctx )
if ! supported {
return & rpc . Subscription { } , rpc . ErrNotificationsUnsupported
}
sub := notifier . CreateSubscription ( )
2021-01-25 07:36:39 -06:00
// Prepare all the states for tracing. Note this procedure can take very
// long time. Timeout mechanism is necessary.
reexec := defaultTraceReexec
if config != nil && config . Reexec != nil {
reexec = * config . Reexec
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
2021-01-25 07:36:39 -06:00
blocks := int ( end . NumberU64 ( ) - start . NumberU64 ( ) )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
threads := runtime . NumCPU ( )
if threads > blocks {
threads = blocks
}
var (
2021-04-07 02:30:26 -05:00
pend = new ( sync . WaitGroup )
tasks = make ( chan * blockTraceTask , threads )
results = make ( chan * blockTraceTask , threads )
localctx = context . Background ( )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
)
for th := 0 ; th < threads ; th ++ {
pend . Add ( 1 )
go func ( ) {
defer pend . Done ( )
// Fetch and execute the next block trace tasks
for task := range tasks {
2021-01-25 07:36:39 -06:00
signer := types . MakeSigner ( api . backend . ChainConfig ( ) , task . block . Number ( ) )
2021-04-07 02:30:26 -05:00
blockCtx := core . NewEVMBlockContext ( task . block . Header ( ) , api . chainContext ( localctx ) , nil )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// Trace all the transactions contained within
for i , tx := range task . block . Transactions ( ) {
2021-05-17 08:13:22 -05:00
msg , _ := tx . AsMessage ( signer , task . block . BaseFee ( ) )
2021-06-24 04:46:26 -05:00
txctx := & Context {
BlockHash : task . block . Hash ( ) ,
TxIndex : i ,
TxHash : tx . Hash ( ) ,
2021-03-14 10:13:25 -05:00
}
2021-04-07 02:30:26 -05:00
res , err := api . traceTx ( localctx , msg , txctx , blockCtx , task . statedb , config )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
if err != nil {
task . results [ i ] = & txTraceResult { Error : err . Error ( ) }
2018-02-05 10:40:32 -06:00
log . Warn ( "Tracing failed" , "hash" , tx . Hash ( ) , "block" , task . block . NumberU64 ( ) , "err" , err )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
break
}
2019-02-01 03:30:59 -06:00
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
2021-01-25 07:36:39 -06:00
task . statedb . Finalise ( api . backend . ChainConfig ( ) . IsEIP158 ( task . block . Number ( ) ) )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
task . results [ i ] = & txTraceResult { Result : res }
}
// Stream the result back to the user or abort on teardown
select {
case results <- task :
case <- notifier . Closed ( ) :
return
}
}
} ( )
}
// Start a goroutine to feed all the blocks into the tracers
2021-09-28 06:06:19 -05:00
var (
begin = time . Now ( )
derefTodo [ ] common . Hash // list of hashes to dereference from the db
derefsMu sync . Mutex // mutex for the derefs
)
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
go func ( ) {
var (
2021-04-07 02:30:26 -05:00
logged time . Time
number uint64
traced uint64
failed error
parent common . Hash
statedb * state . StateDB
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
)
// Ensure everything is properly cleaned up on any exit path
defer func ( ) {
close ( tasks )
pend . Wait ( )
switch {
case failed != nil :
log . Warn ( "Chain tracing failed" , "start" , start . NumberU64 ( ) , "end" , end . NumberU64 ( ) , "transactions" , traced , "elapsed" , time . Since ( begin ) , "err" , failed )
case number < end . NumberU64 ( ) :
log . Warn ( "Chain tracing aborted" , "start" , start . NumberU64 ( ) , "end" , end . NumberU64 ( ) , "abort" , number , "transactions" , traced , "elapsed" , time . Since ( begin ) )
default :
log . Info ( "Chain tracing finished" , "start" , start . NumberU64 ( ) , "end" , end . NumberU64 ( ) , "transactions" , traced , "elapsed" , time . Since ( begin ) )
}
close ( results )
} ( )
2021-11-04 12:54:00 -05:00
var preferDisk bool
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// Feed all the blocks both into the tracer, as well as fast process concurrently
2021-04-07 02:30:26 -05:00
for number = start . NumberU64 ( ) ; number < end . NumberU64 ( ) ; number ++ {
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// Stop tracing if interruption was requested
select {
case <- notifier . Closed ( ) :
return
default :
}
2021-09-28 06:06:19 -05:00
// clean out any derefs
derefsMu . Lock ( )
for _ , h := range derefTodo {
statedb . Database ( ) . TrieDB ( ) . Dereference ( h )
}
derefTodo = derefTodo [ : 0 ]
derefsMu . Unlock ( )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// Print progress logs if long enough time elapsed
if time . Since ( logged ) > 8 * time . Second {
logged = time . Now ( )
2021-01-25 07:36:39 -06:00
log . Info ( "Tracing chain segment" , "start" , start . NumberU64 ( ) , "end" , end . NumberU64 ( ) , "current" , number , "transactions" , traced , "elapsed" , time . Since ( begin ) )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
2021-04-07 02:30:26 -05:00
// Retrieve the parent state to trace on top
block , err := api . blockByNumber ( localctx , rpc . BlockNumber ( number ) )
if err != nil {
failed = err
break
}
// Prepare the statedb for tracing. Don't use the live database for
// tracing to avoid persisting state junks into the database.
2021-11-04 12:54:00 -05:00
statedb , err = api . backend . StateAtBlock ( localctx , block , reexec , statedb , false , preferDisk )
2021-04-07 02:30:26 -05:00
if err != nil {
failed = err
break
}
2021-11-04 12:54:00 -05:00
if trieDb := statedb . Database ( ) . TrieDB ( ) ; trieDb != nil {
2021-04-07 02:30:26 -05:00
// Hold the reference for tracer, will be released at the final stage
2021-11-04 12:54:00 -05:00
trieDb . Reference ( block . Root ( ) , common . Hash { } )
2021-04-07 02:30:26 -05:00
// Release the parent state because it's already held by the tracer
if parent != ( common . Hash { } ) {
2021-11-04 12:54:00 -05:00
trieDb . Dereference ( parent )
}
// Prefer disk if the trie db memory grows too much
s1 , s2 := trieDb . Size ( )
if ! preferDisk && ( s1 + s2 ) > defaultTracechainMemLimit {
log . Info ( "Switching to prefer-disk mode for tracing" , "size" , s1 + s2 )
preferDisk = true
2021-04-07 02:30:26 -05:00
}
}
parent = block . Root ( )
next , err := api . blockByNumber ( localctx , rpc . BlockNumber ( number + 1 ) )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
if err != nil {
failed = err
break
}
2021-01-25 07:36:39 -06:00
// Send the block over to the concurrent tracers (if not in the fast-forward phase)
2021-04-07 02:30:26 -05:00
txs := next . Transactions ( )
2021-01-25 07:36:39 -06:00
select {
2021-04-07 02:30:26 -05:00
case tasks <- & blockTraceTask { statedb : statedb . Copy ( ) , block : next , rootref : block . Root ( ) , results : make ( [ ] * txTraceResult , len ( txs ) ) } :
2021-01-25 07:36:39 -06:00
case <- notifier . Closed ( ) :
return
2018-08-08 09:16:38 -05:00
}
2021-01-25 07:36:39 -06:00
traced += uint64 ( len ( txs ) )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
} ( )
// Keep reading the trace results and stream the to the user
go func ( ) {
var (
done = make ( map [ uint64 ] * blockTraceResult )
2021-01-25 07:36:39 -06:00
next = start . NumberU64 ( ) + 1
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
)
for res := range results {
// Queue up next received result
result := & blockTraceResult {
Block : hexutil . Uint64 ( res . block . NumberU64 ( ) ) ,
Hash : res . block . Hash ( ) ,
Traces : res . results ,
}
2021-09-28 06:06:19 -05:00
// Schedule any parent tries held in memory by this task for dereferencing
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
done [ uint64 ( result . Block ) ] = result
2021-09-28 06:06:19 -05:00
derefsMu . Lock ( )
derefTodo = append ( derefTodo , res . rootref )
derefsMu . Unlock ( )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// Stream completed traces to the user, aborting on the first error
for result , ok := done [ next ] ; ok ; result , ok = done [ next ] {
if len ( result . Traces ) > 0 || next == end . NumberU64 ( ) {
notifier . Notify ( sub . ID , result )
}
delete ( done , next )
next ++
}
}
} ( )
return sub , nil
}
// TraceBlockByNumber returns the structured logs created during the execution of
// EVM and returns them as a JSON object.
2021-01-25 07:36:39 -06:00
func ( api * API ) TraceBlockByNumber ( ctx context . Context , number rpc . BlockNumber , config * TraceConfig ) ( [ ] * txTraceResult , error ) {
block , err := api . blockByNumber ( ctx , number )
if err != nil {
return nil , err
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
return api . traceBlock ( ctx , block , config )
}
// TraceBlockByHash returns the structured logs created during the execution of
// EVM and returns them as a JSON object.
2021-01-25 07:36:39 -06:00
func ( api * API ) TraceBlockByHash ( ctx context . Context , hash common . Hash , config * TraceConfig ) ( [ ] * txTraceResult , error ) {
block , err := api . blockByHash ( ctx , hash )
if err != nil {
return nil , err
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
return api . traceBlock ( ctx , block , config )
}
// TraceBlock returns the structured logs created during the execution of EVM
// and returns them as a JSON object.
2022-03-15 04:27:30 -05:00
func ( api * API ) TraceBlock ( ctx context . Context , blob hexutil . Bytes , config * TraceConfig ) ( [ ] * txTraceResult , error ) {
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
block := new ( types . Block )
if err := rlp . Decode ( bytes . NewReader ( blob ) , block ) ; err != nil {
return nil , fmt . Errorf ( "could not decode block: %v" , err )
}
return api . traceBlock ( ctx , block , config )
}
// TraceBlockFromFile returns the structured logs created during the execution of
// EVM and returns them as a JSON object.
2021-01-25 07:36:39 -06:00
func ( api * API ) TraceBlockFromFile ( ctx context . Context , file string , config * TraceConfig ) ( [ ] * txTraceResult , error ) {
2022-05-16 04:59:35 -05:00
blob , err := os . ReadFile ( file )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
if err != nil {
return nil , fmt . Errorf ( "could not read file: %v" , err )
}
return api . TraceBlock ( ctx , blob , config )
}
2020-08-26 05:20:12 -05:00
// TraceBadBlock returns the structured logs created during the execution of
2018-12-10 04:32:40 -06:00
// EVM against a block pulled from the pool of bad ones and returns them as a JSON
// object.
2021-01-25 07:36:39 -06:00
func ( api * API ) TraceBadBlock ( ctx context . Context , hash common . Hash , config * TraceConfig ) ( [ ] * txTraceResult , error ) {
2021-09-28 05:53:11 -05:00
block := rawdb . ReadBadBlock ( api . backend . ChainDb ( ) , hash )
if block == nil {
return nil , fmt . Errorf ( "bad block %#x not found" , hash )
2018-10-15 05:28:44 -05:00
}
2021-09-28 05:53:11 -05:00
return api . traceBlock ( ctx , block , config )
2018-10-15 05:28:44 -05:00
}
2018-12-10 04:32:40 -06:00
// StandardTraceBlockToFile dumps the structured logs created during the
// execution of EVM to the local file system and returns a list of files
// to the caller.
2021-01-25 07:36:39 -06:00
func ( api * API ) StandardTraceBlockToFile ( ctx context . Context , hash common . Hash , config * StdTraceConfig ) ( [ ] string , error ) {
block , err := api . blockByHash ( ctx , hash )
if err != nil {
return nil , err
2018-10-04 10:15:37 -05:00
}
2018-12-10 04:32:40 -06:00
return api . standardTraceBlockToFile ( ctx , block , config )
2018-10-15 05:28:44 -05:00
}
2021-09-28 05:53:11 -05:00
// 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 {
// Check in the bad blocks
block = rawdb . ReadBadBlock ( api . backend . ChainDb ( ) , 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
}
2021-11-04 12:54:00 -05:00
statedb , err := api . backend . StateAtBlock ( ctx , parent , reexec , nil , true , false )
2021-09-28 05:53:11 -05:00
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 ( ) )
)
for i , tx := range block . Transactions ( ) {
var (
msg , _ = tx . AsMessage ( signer , block . BaseFee ( ) )
txContext = core . NewEVMTxContext ( msg )
vmenv = vm . NewEVM ( vmctx , txContext , statedb , chainConfig , vm . Config { } )
)
statedb . Prepare ( tx . Hash ( ) , i )
if _ , err := core . ApplyMessage ( vmenv , msg , new ( core . GasPool ) . AddGas ( msg . Gas ( ) ) ) ; 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
}
2018-12-10 04:32:40 -06:00
// StandardTraceBadBlockToFile dumps the structured logs created during the
// execution of EVM against a block pulled from the pool of bad ones to the
// local file system and returns a list of files to the caller.
2021-01-25 07:36:39 -06:00
func ( api * API ) StandardTraceBadBlockToFile ( ctx context . Context , hash common . Hash , config * StdTraceConfig ) ( [ ] string , error ) {
2021-09-28 05:53:11 -05:00
block := rawdb . ReadBadBlock ( api . backend . ChainDb ( ) , hash )
if block == nil {
return nil , fmt . Errorf ( "bad block %#x not found" , hash )
2018-10-15 05:28:44 -05:00
}
2021-09-28 05:53:11 -05:00
return api . standardTraceBlockToFile ( ctx , block , config )
2018-10-04 10:15:37 -05:00
}
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// 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.
2021-01-25 07:36:39 -06:00
func ( api * API ) traceBlock ( ctx context . Context , block * types . Block , config * TraceConfig ) ( [ ] * txTraceResult , error ) {
if block . NumberU64 ( ) == 0 {
return nil , errors . New ( "genesis is not traceable" )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
2021-01-25 07:36:39 -06:00
parent , err := api . blockByNumberAndHash ( ctx , rpc . BlockNumber ( block . NumberU64 ( ) - 1 ) , block . ParentHash ( ) )
if err != nil {
return nil , err
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
reexec := defaultTraceReexec
2018-01-04 05:58:11 -06:00
if config != nil && config . Reexec != nil {
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
reexec = * config . Reexec
}
2021-11-04 12:54:00 -05:00
statedb , err := api . backend . StateAtBlock ( ctx , parent , reexec , nil , true , false )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
if err != nil {
return nil , err
}
// Execute all the transaction contained within the block concurrently
var (
2021-01-25 07:36:39 -06:00
signer = types . MakeSigner ( api . backend . ChainConfig ( ) , block . Number ( ) )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
txs = block . Transactions ( )
results = make ( [ ] * txTraceResult , len ( txs ) )
pend = new ( sync . WaitGroup )
jobs = make ( chan * txTraceTask , len ( txs ) )
)
threads := runtime . NumCPU ( )
if threads > len ( txs ) {
threads = len ( txs )
}
2021-03-14 10:13:25 -05:00
blockHash := block . Hash ( )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
for th := 0 ; th < threads ; th ++ {
pend . Add ( 1 )
go func ( ) {
2022-01-25 07:45:30 -06:00
blockCtx := core . NewEVMBlockContext ( block . Header ( ) , api . chainContext ( ctx ) , nil )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
defer pend . Done ( )
// Fetch and execute the next transaction trace tasks
for task := range jobs {
2021-05-17 08:13:22 -05:00
msg , _ := txs [ task . index ] . AsMessage ( signer , block . BaseFee ( ) )
2021-06-24 04:46:26 -05:00
txctx := & Context {
BlockHash : blockHash ,
TxIndex : task . index ,
TxHash : txs [ task . index ] . Hash ( ) ,
2021-03-14 10:13:25 -05:00
}
res , err := api . traceTx ( ctx , msg , txctx , blockCtx , task . statedb , config )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
if err != nil {
results [ task . index ] = & txTraceResult { Error : err . Error ( ) }
continue
}
results [ task . index ] = & txTraceResult { Result : res }
}
} ( )
}
// Feed the transactions into the tracers and return
var failed error
2022-01-25 07:45:30 -06:00
blockCtx := core . NewEVMBlockContext ( block . Header ( ) , api . chainContext ( ctx ) , nil )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
for i , tx := range txs {
// Send the trace task over for execution
jobs <- & txTraceTask { statedb : statedb . Copy ( ) , index : i }
// Generate the next state snapshot fast without tracing
2021-05-17 08:13:22 -05:00
msg , _ := tx . AsMessage ( signer , block . BaseFee ( ) )
2021-06-30 08:17:01 -05:00
statedb . Prepare ( tx . Hash ( ) , i )
2021-03-14 10:13:25 -05:00
vmenv := vm . NewEVM ( blockCtx , core . NewEVMTxContext ( msg ) , statedb , api . backend . ChainConfig ( ) , vm . Config { } )
2020-04-22 03:25:36 -05:00
if _ , err := core . ApplyMessage ( vmenv , msg , new ( core . GasPool ) . AddGas ( msg . Gas ( ) ) ) ; err != nil {
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
failed = err
break
}
// Finalize the state so any modifications are written to the trie
2019-02-01 03:30:59 -06:00
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
statedb . Finalise ( vmenv . ChainConfig ( ) . IsEIP158 ( block . Number ( ) ) )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
close ( jobs )
pend . Wait ( )
// If execution failed in between, abort
if failed != nil {
return nil , failed
}
return results , nil
}
2018-12-10 04:32:40 -06:00
// standardTraceBlockToFile configures a new tracer which uses standard JSON output,
// and traces either a full block or an individual transaction. The return value will
// be one filename per transaction traced.
2021-01-25 07:36:39 -06:00
func ( api * API ) standardTraceBlockToFile ( ctx context . Context , block * types . Block , config * StdTraceConfig ) ( [ ] string , error ) {
2018-12-10 04:32:40 -06:00
// If we're tracing a single transaction, make sure it's present
if config != nil && config . TxHash != ( common . Hash { } ) {
2019-02-19 11:49:24 -06:00
if ! containsTx ( block , config . TxHash ) {
2018-12-10 04:32:40 -06:00
return nil , fmt . Errorf ( "transaction %#x not found in block" , config . TxHash )
}
}
2021-01-25 07:36:39 -06:00
if block . NumberU64 ( ) == 0 {
return nil , errors . New ( "genesis is not traceable" )
2018-10-15 05:28:44 -05:00
}
2021-01-25 07:36:39 -06:00
parent , err := api . blockByNumberAndHash ( ctx , rpc . BlockNumber ( block . NumberU64 ( ) - 1 ) , block . ParentHash ( ) )
if err != nil {
return nil , err
2018-10-15 05:28:44 -05:00
}
2018-12-10 04:32:40 -06:00
reexec := defaultTraceReexec
if config != nil && config . Reexec != nil {
reexec = * config . Reexec
2018-10-15 05:28:44 -05:00
}
2021-11-04 12:54:00 -05:00
statedb , err := api . backend . StateAtBlock ( ctx , parent , reexec , nil , true , false )
2018-10-15 05:28:44 -05:00
if err != nil {
return nil , err
}
2018-12-10 04:32:40 -06:00
// Retrieve the tracing configurations, or use default values
var (
2021-11-25 06:17:09 -06:00
logConfig logger . Config
2018-12-10 04:32:40 -06:00
txHash common . Hash
)
if config != nil {
2021-11-25 06:17:09 -06:00
logConfig = config . Config
2018-12-10 04:32:40 -06:00
txHash = config . TxHash
}
logConfig . Debug = true
2018-10-15 05:28:44 -05:00
2018-12-10 04:32:40 -06:00
// Execute transaction, either tracing all or just the requested one
var (
2020-10-23 01:26:57 -05:00
dumps [ ] string
2021-01-25 07:36:39 -06:00
signer = types . MakeSigner ( api . backend . ChainConfig ( ) , block . Number ( ) )
chainConfig = api . backend . ChainConfig ( )
vmctx = core . NewEVMBlockContext ( block . Header ( ) , api . chainContext ( ctx ) , nil )
2020-10-23 01:26:57 -05:00
canon = true
2018-12-10 04:32:40 -06:00
)
2020-10-23 01:26:57 -05:00
// Check if there are any overrides: the caller may wish to enable a future
// fork when executing this block. Note, such overrides are only applicable to the
// actual specified block, not any preceding blocks that we have to go through
// in order to obtain the state.
// Therefore, it's perfectly valid to specify `"futureForkBlock": 0`, to enable `futureFork`
if config != nil && config . Overrides != nil {
// Copy the config, to not screw up the main config
// Note: the Clique-part is _not_ deep copied
chainConfigCopy := new ( params . ChainConfig )
* chainConfigCopy = * chainConfig
chainConfig = chainConfigCopy
2021-11-25 06:17:09 -06:00
if berlin := config . Config . Overrides . BerlinBlock ; berlin != nil {
2021-02-25 01:10:30 -06:00
chainConfig . BerlinBlock = berlin
2020-10-23 01:26:57 -05:00
canon = false
}
}
2018-10-15 05:28:44 -05:00
for i , tx := range block . Transactions ( ) {
2018-12-10 04:32:40 -06:00
// Prepare the trasaction for un-traced execution
2018-10-15 05:28:44 -05:00
var (
2021-05-17 08:13:22 -05:00
msg , _ = tx . AsMessage ( signer , block . BaseFee ( ) )
2020-11-13 06:42:19 -06:00
txContext = core . NewEVMTxContext ( msg )
vmConf vm . Config
dump * os . File
writer * bufio . Writer
err error
2018-10-15 05:28:44 -05:00
)
2018-12-10 04:32:40 -06:00
// If the transaction needs tracing, swap out the configs
if tx . Hash ( ) == txHash || txHash == ( common . Hash { } ) {
// Generate a unique temporary file to dump it into
prefix := fmt . Sprintf ( "block_%#x-%d-%#x-" , block . Hash ( ) . Bytes ( ) [ : 4 ] , i , tx . Hash ( ) . Bytes ( ) [ : 4 ] )
2020-10-23 01:26:57 -05:00
if ! canon {
prefix = fmt . Sprintf ( "%valt-" , prefix )
}
2022-05-16 04:59:35 -05:00
dump , err = os . CreateTemp ( os . TempDir ( ) , prefix )
2018-10-15 05:28:44 -05:00
if err != nil {
return nil , err
}
2018-12-10 04:32:40 -06:00
dumps = append ( dumps , dump . Name ( ) )
// Swap out the noop logger to the standard tracer
2019-01-23 04:13:13 -06:00
writer = bufio . NewWriter ( dump )
2018-10-15 05:28:44 -05:00
vmConf = vm . Config {
Debug : true ,
2021-11-25 06:17:09 -06:00
Tracer : logger . NewJSONLogger ( & logConfig , writer ) ,
2018-10-15 05:28:44 -05:00
EnablePreimageRecording : true ,
}
}
2018-12-10 04:32:40 -06:00
// Execute the transaction and flush any traces to disk
2020-11-13 06:42:19 -06:00
vmenv := vm . NewEVM ( vmctx , txContext , statedb , chainConfig , vmConf )
2021-06-30 08:17:01 -05:00
statedb . Prepare ( tx . Hash ( ) , i )
2020-04-22 03:25:36 -05:00
_ , err = core . ApplyMessage ( vmenv , msg , new ( core . GasPool ) . AddGas ( msg . Gas ( ) ) )
2019-01-23 04:13:13 -06:00
if writer != nil {
writer . Flush ( )
}
2018-12-10 04:32:40 -06:00
if dump != nil {
dump . Close ( )
log . Info ( "Wrote standard trace" , "file" , dump . Name ( ) )
2018-10-15 05:28:44 -05:00
}
if err != nil {
2018-12-10 04:32:40 -06:00
return dumps , err
2018-10-15 05:28:44 -05:00
}
// Finalize the state so any modifications are written to the trie
2019-02-01 03:30:59 -06:00
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
statedb . Finalise ( vmenv . ChainConfig ( ) . IsEIP158 ( block . Number ( ) ) )
2018-10-15 05:28:44 -05:00
2018-12-10 04:32:40 -06:00
// If we've traced the transaction we were looking for, abort
if tx . Hash ( ) == txHash {
2018-10-15 05:28:44 -05:00
break
}
}
2018-12-10 04:32:40 -06:00
return dumps , nil
2018-10-15 05:28:44 -05:00
}
2019-02-19 11:49:24 -06:00
// containsTx reports whether the transaction with a certain hash
// is contained within the specified block.
func containsTx ( block * types . Block , hash common . Hash ) bool {
for _ , tx := range block . Transactions ( ) {
if tx . Hash ( ) == hash {
return true
}
}
return false
}
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// TraceTransaction returns the structured logs created during the execution of EVM
// and returns them as a JSON object.
2021-01-25 07:36:39 -06:00
func ( api * API ) TraceTransaction ( ctx context . Context , hash common . Hash , config * TraceConfig ) ( interface { } , error ) {
_ , blockHash , blockNumber , index , err := api . backend . GetTransaction ( ctx , hash )
if err != nil {
return nil , err
}
// It shouldn't happen in practice.
if blockNumber == 0 {
return nil , errors . New ( "genesis is not traceable" )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
reexec := defaultTraceReexec
2018-01-04 05:58:11 -06:00
if config != nil && config . Reexec != nil {
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
reexec = * config . Reexec
}
2021-01-25 07:36:39 -06:00
block , err := api . blockByNumberAndHash ( ctx , rpc . BlockNumber ( blockNumber ) , blockHash )
if err != nil {
return nil , err
2020-09-07 03:52:01 -05:00
}
2021-04-07 02:30:26 -05:00
msg , vmctx , statedb , err := api . backend . StateAtTransaction ( ctx , block , int ( index ) , reexec )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
if err != nil {
return nil , err
}
2021-06-24 04:46:26 -05:00
txctx := & Context {
BlockHash : blockHash ,
TxIndex : int ( index ) ,
TxHash : hash ,
2021-03-14 10:13:25 -05:00
}
return api . traceTx ( ctx , msg , txctx , vmctx , statedb , config )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
2021-01-25 07:36:39 -06:00
// TraceCall lets you trace a given eth_call. It collects the structured logs
// created during the execution of EVM if the given transaction was added on
// top of the provided block and returns them as a JSON object.
2021-05-25 15:30:21 -05:00
func ( api * API ) TraceCall ( ctx context . Context , args ethapi . TransactionArgs , blockNrOrHash rpc . BlockNumberOrHash , config * TraceCallConfig ) ( interface { } , error ) {
2021-01-25 07:36:39 -06:00
// Try to retrieve the specified block
var (
err error
block * types . Block
)
if hash , ok := blockNrOrHash . Hash ( ) ; ok {
block , err = api . blockByHash ( ctx , hash )
} else if number , ok := blockNrOrHash . Number ( ) ; ok {
2022-06-02 04:39:36 -05:00
if number == rpc . PendingBlockNumber {
// We don't have access to the miner here. For tracing 'future' transactions,
// it can be done with block- and state-overrides instead, which offers
// more flexibility and stability than trying to trace on 'pending', since
// the contents of 'pending' is unstable and probably not a true representation
// of what the next actual block is likely to contain.
return nil , errors . New ( "tracing on top of pending is not supported" )
}
2021-01-25 07:36:39 -06:00
block , err = api . blockByNumber ( ctx , number )
2021-04-21 02:21:22 -05:00
} else {
return nil , errors . New ( "invalid arguments; neither block nor hash specified" )
2021-01-25 07:36:39 -06:00
}
2020-09-07 03:52:01 -05:00
if err != nil {
2021-01-25 07:36:39 -06:00
return nil , err
}
// try to recompute the state
reexec := defaultTraceReexec
if config != nil && config . Reexec != nil {
reexec = * config . Reexec
2020-09-07 03:52:01 -05:00
}
2021-11-04 12:54:00 -05:00
statedb , err := api . backend . StateAtBlock ( ctx , block , reexec , nil , true , false )
2021-01-25 07:36:39 -06:00
if err != nil {
return nil , err
}
2022-06-02 04:39:36 -05:00
vmctx := core . NewEVMBlockContext ( block . Header ( ) , api . chainContext ( ctx ) , nil )
// Apply the customization rules if required.
2021-04-21 02:21:22 -05:00
if config != nil {
if err := config . StateOverrides . Apply ( statedb ) ; err != nil {
return nil , err
}
2022-06-02 04:39:36 -05:00
config . BlockOverrides . Apply ( & vmctx )
2021-04-21 02:21:22 -05:00
}
2020-09-07 03:52:01 -05:00
// Execute the trace
core, eth, internal, les: RPC methods and fields for EIP 1559 (#22964)
* internal/ethapi: add baseFee to RPCMarshalHeader
* internal/ethapi: add FeeCap, Tip and correct GasPrice to EIP-1559 RPCTransaction results
* core,eth,les,internal: add support for tip estimation in gas price oracle
* internal/ethapi,eth/gasprice: don't suggest tip larger than fee cap
* core/types,internal: use correct eip1559 terminology for json marshalling
* eth, internal/ethapi: fix rebase problems
* internal/ethapi: fix rpc name of basefee
* internal/ethapi: address review concerns
* core, eth, internal, les: simplify gasprice oracle (#25)
* core, eth, internal, les: simplify gasprice oracle
* eth/gasprice: fix typo
* internal/ethapi: minor tweak in tx args
* internal/ethapi: calculate basefee for pending block
* internal/ethapi: fix panic
* internal/ethapi, eth/tracers: simplify txargs ToMessage
* internal/ethapi: remove unused param
* core, eth, internal: fix regressions wrt effective gas price in the evm
* eth/gasprice: drop weird debug println
* internal/jsre/deps: hack in 1559 gas conversions into embedded web3
* internal/jsre/deps: hack basFee to decimal conversion
* internal/ethapi: init feecap and tipcap for legacy txs too
* eth, graphql, internal, les: fix gas price suggestion on all combos
* internal/jsre/deps: handle decimal tipcap and feecap
* eth, internal: minor review fixes
* graphql, internal: export max fee cap RPC endpoint
* internal/ethapi: fix crash in transaction_args
* internal/ethapi: minor refactor to make the code safer
Co-authored-by: Ryan Schneider <ryanleeschneider@gmail.com>
Co-authored-by: lightclient@protonmail.com <lightclient@protonmail.com>
Co-authored-by: gary rong <garyrong0905@gmail.com>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2021-06-02 08:13:10 -05:00
msg , err := args . ToMessage ( api . backend . RPCGasCap ( ) , block . BaseFee ( ) )
if err != nil {
return nil , err
}
2021-03-14 10:13:25 -05:00
2021-04-21 02:21:22 -05:00
var traceConfig * TraceConfig
if config != nil {
traceConfig = & TraceConfig {
2021-11-25 06:17:09 -06:00
Config : config . Config ,
Tracer : config . Tracer ,
Timeout : config . Timeout ,
Reexec : config . Reexec ,
2021-04-21 02:21:22 -05:00
}
}
2021-06-24 04:46:26 -05:00
return api . traceTx ( ctx , msg , new ( Context ) , vmctx , statedb , traceConfig )
2020-09-07 03:52:01 -05:00
}
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// traceTx configures a new tracer according to the provided configuration, and
// executes the given message in the provided environment. The return value will
// be tracer dependent.
2021-06-24 04:46:26 -05:00
func ( api * API ) traceTx ( ctx context . Context , message core . Message , txctx * Context , vmctx vm . BlockContext , statedb * state . StateDB , config * TraceConfig ) ( interface { } , error ) {
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
var (
2022-04-06 02:34:18 -05:00
tracer Tracer
2020-11-13 06:42:19 -06:00
err error
2022-04-06 02:34:18 -05:00
timeout = defaultTraceTimeout
2020-11-13 06:42:19 -06:00
txContext = core . NewEVMTxContext ( message )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
)
2022-04-06 02:34:18 -05:00
if config == nil {
config = & TraceConfig { }
}
// Default tracer is the struct logger
tracer = logger . NewStructLogger ( config . Config )
if config . Tracer != nil {
tracer , err = New ( * config . Tracer , txctx )
if err != nil {
return nil , err
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
2022-04-06 02:34:18 -05:00
}
// Define a meaningful timeout of a single transaction trace
if config . Timeout != nil {
if timeout , err = time . ParseDuration ( * config . Timeout ) ; err != nil {
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
return nil , err
}
}
2022-04-06 02:34:18 -05:00
deadlineCtx , cancel := context . WithTimeout ( ctx , timeout )
go func ( ) {
<- deadlineCtx . Done ( )
if errors . Is ( deadlineCtx . Err ( ) , context . DeadlineExceeded ) {
tracer . Stop ( errors . New ( "execution timeout" ) )
}
} ( )
defer cancel ( )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
// Run the transaction with tracing enabled.
2021-06-15 05:56:14 -05:00
vmenv := vm . NewEVM ( vmctx , txContext , statedb , api . backend . ChainConfig ( ) , vm . Config { Debug : true , Tracer : tracer , NoBaseFee : true } )
2021-03-14 10:13:25 -05:00
// Call Prepare to clear out the statedb access list
2021-06-30 08:17:01 -05:00
statedb . Prepare ( txctx . TxHash , txctx . TxIndex )
2022-04-06 02:34:18 -05:00
if _ , err = core . ApplyMessage ( vmenv , message , new ( core . GasPool ) . AddGas ( message . Gas ( ) ) ) ; err != nil {
2021-04-21 02:21:22 -05:00
return nil , fmt . Errorf ( "tracing failed: %w" , err )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
2022-04-06 02:34:18 -05:00
return tracer . GetResult ( )
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
2021-01-25 07:36:39 -06:00
// APIs return the collection of RPC services the tracer package offers.
func APIs ( backend Backend ) [ ] rpc . API {
// Append all the local APIs and return
return [ ] rpc . API {
{
Namespace : "debug" ,
Version : "1.0" ,
Service : NewAPI ( backend ) ,
Public : false ,
} ,
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
2017-12-21 05:56:11 -06:00
}
}