@ -203,13 +203,11 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
// Fetch and execute the next block trace tasks
// Fetch and execute the next block trace tasks
for task := range tasks {
for task := range tasks {
signer := types . MakeSigner ( api . eth . blockchain . Config ( ) , task . block . Number ( ) )
signer := types . MakeSigner ( api . eth . blockchain . Config ( ) , task . block . Number ( ) )
blockCtx := core . NewEVMBlockContext ( task . block . Header ( ) , api . eth . blockchain , nil )
// Trace all the transactions contained within
// Trace all the transactions contained within
for i , tx := range task . block . Transactions ( ) {
for i , tx := range task . block . Transactions ( ) {
msg , _ := tx . AsMessage ( signer )
msg , _ := tx . AsMessage ( signer )
vmctx := core . NewEVMContext ( msg , task . block . Header ( ) , api . eth . blockchain , nil )
res , err := api . traceTx ( ctx , msg , blockCtx , task . statedb , config )
res , err := api . traceTx ( ctx , msg , vmctx , task . statedb , config )
if err != nil {
if err != nil {
task . results [ i ] = & txTraceResult { Error : err . Error ( ) }
task . results [ i ] = & txTraceResult { Error : err . Error ( ) }
log . Warn ( "Tracing failed" , "hash" , tx . Hash ( ) , "block" , task . block . NumberU64 ( ) , "err" , err )
log . Warn ( "Tracing failed" , "hash" , tx . Hash ( ) , "block" , task . block . NumberU64 ( ) , "err" , err )
@ -473,17 +471,15 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
if threads > len ( txs ) {
if threads > len ( txs ) {
threads = len ( txs )
threads = len ( txs )
}
}
blockCtx := core . NewEVMBlockContext ( block . Header ( ) , api . eth . blockchain , nil )
for th := 0 ; th < threads ; th ++ {
for th := 0 ; th < threads ; th ++ {
pend . Add ( 1 )
pend . Add ( 1 )
go func ( ) {
go func ( ) {
defer pend . Done ( )
defer pend . Done ( )
// Fetch and execute the next transaction trace tasks
// Fetch and execute the next transaction trace tasks
for task := range jobs {
for task := range jobs {
msg , _ := txs [ task . index ] . AsMessage ( signer )
msg , _ := txs [ task . index ] . AsMessage ( signer )
vmctx := core . NewEVMContext ( msg , block . Header ( ) , api . eth . blockchain , nil )
res , err := api . traceTx ( ctx , msg , blockCtx , task . statedb , config )
res , err := api . traceTx ( ctx , msg , vmctx , task . statedb , config )
if err != nil {
if err != nil {
results [ task . index ] = & txTraceResult { Error : err . Error ( ) }
results [ task . index ] = & txTraceResult { Error : err . Error ( ) }
continue
continue
@ -500,9 +496,9 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
// Generate the next state snapshot fast without tracing
// Generate the next state snapshot fast without tracing
msg , _ := tx . AsMessage ( signer )
msg , _ := tx . AsMessage ( signer )
vmc tx := core . NewEVMContext ( msg , block . Header ( ) , api . eth . blockchain , nil )
txContext := core . NewEVMTx Context ( msg )
vmenv := vm . NewEVM ( vmctx , statedb , api . eth . blockchain . Config ( ) , vm . Config { } )
vmenv := vm . NewEVM ( blockCtx , txContext , statedb , api . eth . blockchain . Config ( ) , vm . Config { } )
if _ , err := core . ApplyMessage ( vmenv , msg , new ( core . GasPool ) . AddGas ( msg . Gas ( ) ) ) ; err != nil {
if _ , err := core . ApplyMessage ( vmenv , msg , new ( core . GasPool ) . AddGas ( msg . Gas ( ) ) ) ; err != nil {
failed = err
failed = err
break
break
@ -565,6 +561,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
signer = types . MakeSigner ( api . eth . blockchain . Config ( ) , block . Number ( ) )
signer = types . MakeSigner ( api . eth . blockchain . Config ( ) , block . Number ( ) )
dumps [ ] string
dumps [ ] string
chainConfig = api . eth . blockchain . Config ( )
chainConfig = api . eth . blockchain . Config ( )
vmctx = core . NewEVMBlockContext ( block . Header ( ) , api . eth . blockchain , nil )
canon = true
canon = true
)
)
// Check if there are any overrides: the caller may wish to enable a future
// Check if there are any overrides: the caller may wish to enable a future
@ -587,13 +584,12 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
for i , tx := range block . Transactions ( ) {
for i , tx := range block . Transactions ( ) {
// Prepare the trasaction for un-traced execution
// Prepare the trasaction for un-traced execution
var (
var (
msg , _ = tx . AsMessage ( signer )
msg , _ = tx . AsMessage ( signer )
vmctx = core . NewEVMContext ( msg , block . Header ( ) , api . eth . blockchain , nil )
txContext = core . NewEVMTxContext ( msg )
vmConf vm . Config
vmConf vm . Config
dump * os . File
dump * os . File
writer * bufio . Writer
writer * bufio . Writer
err error
err error
)
)
// If the transaction needs tracing, swap out the configs
// If the transaction needs tracing, swap out the configs
if tx . Hash ( ) == txHash || txHash == ( common . Hash { } ) {
if tx . Hash ( ) == txHash || txHash == ( common . Hash { } ) {
@ -617,7 +613,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
}
}
}
}
// Execute the transaction and flush any traces to disk
// Execute the transaction and flush any traces to disk
vmenv := vm . NewEVM ( vmctx , statedb , chainConfig , vmConf )
vmenv := vm . NewEVM ( vmctx , txContext , statedb , chainConfig , vmConf )
_ , err = core . ApplyMessage ( vmenv , msg , new ( core . GasPool ) . AddGas ( msg . Gas ( ) ) )
_ , err = core . ApplyMessage ( vmenv , msg , new ( core . GasPool ) . AddGas ( msg . Gas ( ) ) )
if writer != nil {
if writer != nil {
writer . Flush ( )
writer . Flush ( )
@ -776,18 +772,19 @@ func (api *PrivateDebugAPI) TraceCall(ctx context.Context, args ethapi.CallArgs,
// Execute the trace
// Execute the trace
msg := args . ToMessage ( api . eth . APIBackend . RPCGasCap ( ) )
msg := args . ToMessage ( api . eth . APIBackend . RPCGasCap ( ) )
vmctx := core . NewEVMContext ( msg , header , api . eth . blockchain , nil )
vmctx := core . NewEVMBlock Context ( header , api . eth . blockchain , nil )
return api . traceTx ( ctx , msg , vmctx , statedb , config )
return api . traceTx ( ctx , msg , vmctx , statedb , config )
}
}
// traceTx configures a new tracer according to the provided configuration, and
// traceTx configures a new tracer according to the provided configuration, and
// executes the given message in the provided environment. The return value will
// executes the given message in the provided environment. The return value will
// be tracer dependent.
// be tracer dependent.
func ( api * PrivateDebugAPI ) traceTx ( ctx context . Context , message core . Message , vmctx vm . Context , statedb * state . StateDB , config * TraceConfig ) ( interface { } , error ) {
func ( api * PrivateDebugAPI ) traceTx ( ctx context . Context , message core . Message , vmctx vm . Block Context, statedb * state . StateDB , config * TraceConfig ) ( interface { } , error ) {
// Assemble the structured logger or the JavaScript tracer
// Assemble the structured logger or the JavaScript tracer
var (
var (
tracer vm . Tracer
tracer vm . Tracer
err error
err error
txContext = core . NewEVMTxContext ( message )
)
)
switch {
switch {
case config != nil && config . Tracer != nil :
case config != nil && config . Tracer != nil :
@ -817,7 +814,7 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v
tracer = vm . NewStructLogger ( config . LogConfig )
tracer = vm . NewStructLogger ( config . LogConfig )
}
}
// Run the transaction with tracing enabled.
// Run the transaction with tracing enabled.
vmenv := vm . NewEVM ( vmctx , statedb , api . eth . blockchain . Config ( ) , vm . Config { Debug : true , Tracer : tracer } )
vmenv := vm . NewEVM ( vmctx , txContext , statedb , api . eth . blockchain . Config ( ) , vm . Config { Debug : true , Tracer : tracer } )
result , err := core . ApplyMessage ( vmenv , message , new ( core . GasPool ) . AddGas ( message . Gas ( ) ) )
result , err := core . ApplyMessage ( vmenv , message , new ( core . GasPool ) . AddGas ( message . Gas ( ) ) )
if err != nil {
if err != nil {
@ -847,19 +844,19 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v
}
}
// computeTxEnv returns the execution environment of a certain transaction.
// computeTxEnv returns the execution environment of a certain transaction.
func ( api * PrivateDebugAPI ) computeTxEnv ( block * types . Block , txIndex int , reexec uint64 ) ( core . Message , vm . Context , * state . StateDB , error ) {
func ( api * PrivateDebugAPI ) computeTxEnv ( block * types . Block , txIndex int , reexec uint64 ) ( core . Message , vm . Block Context, * state . StateDB , error ) {
// Create the parent state database
// Create the parent state database
parent := api . eth . blockchain . GetBlock ( block . ParentHash ( ) , block . NumberU64 ( ) - 1 )
parent := api . eth . blockchain . GetBlock ( block . ParentHash ( ) , block . NumberU64 ( ) - 1 )
if parent == nil {
if parent == nil {
return nil , vm . Context { } , nil , fmt . Errorf ( "parent %#x not found" , block . ParentHash ( ) )
return nil , vm . Block Context{ } , nil , fmt . Errorf ( "parent %#x not found" , block . ParentHash ( ) )
}
}
statedb , err := api . computeStateDB ( parent , reexec )
statedb , err := api . computeStateDB ( parent , reexec )
if err != nil {
if err != nil {
return nil , vm . Context { } , nil , err
return nil , vm . Block Context{ } , nil , err
}
}
if txIndex == 0 && len ( block . Transactions ( ) ) == 0 {
if txIndex == 0 && len ( block . Transactions ( ) ) == 0 {
return nil , vm . Context { } , statedb , nil
return nil , vm . Block Context{ } , statedb , nil
}
}
// Recompute transactions up to the target index.
// Recompute transactions up to the target index.
@ -868,18 +865,19 @@ func (api *PrivateDebugAPI) computeTxEnv(block *types.Block, txIndex int, reexec
for idx , tx := range block . Transactions ( ) {
for idx , tx := range block . Transactions ( ) {
// Assemble the transaction call message and return if the requested offset
// Assemble the transaction call message and return if the requested offset
msg , _ := tx . AsMessage ( signer )
msg , _ := tx . AsMessage ( signer )
context := core . NewEVMContext ( msg , block . Header ( ) , api . eth . blockchain , nil )
txContext := core . NewEVMTxContext ( msg )
context := core . NewEVMBlockContext ( block . Header ( ) , api . eth . blockchain , nil )
if idx == txIndex {
if idx == txIndex {
return msg , context , statedb , nil
return msg , context , statedb , nil
}
}
// Not yet the searched for transaction, execute on top of the current state
// Not yet the searched for transaction, execute on top of the current state
vmenv := vm . NewEVM ( context , statedb , api . eth . blockchain . Config ( ) , vm . Config { } )
vmenv := vm . NewEVM ( context , txContext , statedb , api . eth . blockchain . Config ( ) , vm . Config { } )
if _ , err := core . ApplyMessage ( vmenv , msg , new ( core . GasPool ) . AddGas ( tx . Gas ( ) ) ) ; err != nil {
if _ , err := core . ApplyMessage ( vmenv , msg , new ( core . GasPool ) . AddGas ( tx . Gas ( ) ) ) ; err != nil {
return nil , vm . Context { } , nil , fmt . Errorf ( "transaction %#x failed: %v" , tx . Hash ( ) , err )
return nil , vm . Block Context{ } , nil , fmt . Errorf ( "transaction %#x failed: %v" , tx . Hash ( ) , err )
}
}
// Ensure any modifications are committed to the state
// Ensure any modifications are committed to the state
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
statedb . Finalise ( vmenv . ChainConfig ( ) . IsEIP158 ( block . Number ( ) ) )
statedb . Finalise ( vmenv . ChainConfig ( ) . IsEIP158 ( block . Number ( ) ) )
}
}
return nil , vm . Context { } , nil , fmt . Errorf ( "transaction index %d out of range for block %#x" , txIndex , block . Hash ( ) )
return nil , vm . Block Context{ } , nil , fmt . Errorf ( "transaction index %d out of range for block %#x" , txIndex , block . Hash ( ) )
}
}