Skip to content

Commit 0983d02

Browse files
committed
eth, internal/web3ext: tiny polishes in tracers
1 parent 42a914a commit 0983d02

File tree

2 files changed

+97
-77
lines changed

2 files changed

+97
-77
lines changed

eth/api_tracer.go

Lines changed: 95 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ type TraceConfig struct {
6666
type StdTraceConfig struct {
6767
*vm.LogConfig
6868
Reexec *uint64
69-
TxHash *common.Hash
69+
TxHash common.Hash
7070
}
7171

7272
// txTraceResult is the result of a single transaction trace.
@@ -375,7 +375,7 @@ func (api *PrivateDebugAPI) TraceBlockByNumber(ctx context.Context, number rpc.B
375375
func (api *PrivateDebugAPI) TraceBlockByHash(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) {
376376
block := api.eth.blockchain.GetBlockByHash(hash)
377377
if block == nil {
378-
return nil, fmt.Errorf("block #%x not found", hash)
378+
return nil, fmt.Errorf("block %#x not found", hash)
379379
}
380380
return api.traceBlock(ctx, block, config)
381381
}
@@ -400,37 +400,41 @@ func (api *PrivateDebugAPI) TraceBlockFromFile(ctx context.Context, file string,
400400
return api.TraceBlock(ctx, blob, config)
401401
}
402402

403-
// TraceBadBlockByHash returns the structured logs created during the execution of a block
404-
func (api *PrivateDebugAPI) TraceBadBlock(ctx context.Context, blockHash common.Hash, config *TraceConfig) ([]*txTraceResult, error) {
403+
// TraceBadBlockByHash returns the structured logs created during the execution of
404+
// EVM against a block pulled from the pool of bad ones and returns them as a JSON
405+
// object.
406+
func (api *PrivateDebugAPI) TraceBadBlock(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) {
405407
blocks := api.eth.blockchain.BadBlocks()
406408
for _, block := range blocks {
407-
if block.Hash() == blockHash {
409+
if block.Hash() == hash {
408410
return api.traceBlock(ctx, block, config)
409411
}
410412
}
411-
return nil, fmt.Errorf("hash not found among bad blocks")
413+
return nil, fmt.Errorf("bad block %#x not found", hash)
412414
}
413415

414-
// StandardTraceBadBlockToFile dumps the standard-json logs to files on the local filesystem,
415-
// and returns a list of files to the caller.
416-
func (api *PrivateDebugAPI) StandardTraceBadBlockToFile(ctx context.Context, blockHash common.Hash, stdConfig *StdTraceConfig) ([]string, error) {
417-
blocks := api.eth.blockchain.BadBlocks()
418-
for _, block := range blocks {
419-
if block.Hash() == blockHash {
420-
return api.standardTraceBlockToFile(ctx, block, stdConfig)
421-
}
416+
// StandardTraceBlockToFile dumps the structured logs created during the
417+
// execution of EVM to the local file system and returns a list of files
418+
// to the caller.
419+
func (api *PrivateDebugAPI) StandardTraceBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) {
420+
block := api.eth.blockchain.GetBlockByHash(hash)
421+
if block == nil {
422+
return nil, fmt.Errorf("block %#x not found", hash)
422423
}
423-
return nil, fmt.Errorf("hash not found among bad blocks")
424+
return api.standardTraceBlockToFile(ctx, block, config)
424425
}
425426

426-
// StandardTraceBlockToFile dumps the standard-json logs to files on the local filesystem,
427-
// and returns a list of files to the caller.
428-
func (api *PrivateDebugAPI) StandardTraceBlockToFile(ctx context.Context, blockHash common.Hash, stdConfig *StdTraceConfig) ([]string, error) {
429-
block := api.eth.blockchain.GetBlockByHash(blockHash)
430-
if block == nil {
431-
return nil, fmt.Errorf("block #%x not found", blockHash)
427+
// StandardTraceBadBlockToFile dumps the structured logs created during the
428+
// execution of EVM against a block pulled from the pool of bad ones to the
429+
// local file system and returns a list of files to the caller.
430+
func (api *PrivateDebugAPI) StandardTraceBadBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) {
431+
blocks := api.eth.blockchain.BadBlocks()
432+
for _, block := range blocks {
433+
if block.Hash() == hash {
434+
return api.standardTraceBlockToFile(ctx, block, config)
435+
}
432436
}
433-
return api.standardTraceBlockToFile(ctx, block, stdConfig)
437+
return nil, fmt.Errorf("bad block %#x not found", hash)
434438
}
435439

436440
// traceBlock configures a new tracer according to the provided configuration, and
@@ -443,7 +447,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
443447
}
444448
parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
445449
if parent == nil {
446-
return nil, fmt.Errorf("parent %x not found", block.ParentHash())
450+
return nil, fmt.Errorf("parent %#x not found", block.ParentHash())
447451
}
448452
reexec := defaultTraceReexec
449453
if config != nil && config.Reexec != nil {
@@ -514,90 +518,104 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
514518
return results, nil
515519
}
516520

517-
// standardTraceBlockToFile configures a new tracer which uses standard-json output, and
518-
// traces either a full block or an individual transaction. The return value will be one filename
519-
// per transaction traced.
520-
func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block *types.Block, stdConfig *StdTraceConfig) ([]string, error) {
521+
// standardTraceBlockToFile configures a new tracer which uses standard JSON output,
522+
// and traces either a full block or an individual transaction. The return value will
523+
// be one filename per transaction traced.
524+
func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block *types.Block, config *StdTraceConfig) ([]string, error) {
525+
// If we're tracing a single transaction, make sure it's present
526+
if config != nil && config.TxHash != (common.Hash{}) {
527+
var exists bool
528+
for _, tx := range block.Transactions() {
529+
if exists = (tx.Hash() == config.TxHash); exists {
530+
break
531+
}
532+
}
533+
if !exists {
534+
return nil, fmt.Errorf("transaction %#x not found in block", config.TxHash)
535+
}
536+
}
521537
// Create the parent state database
522538
if err := api.eth.engine.VerifyHeader(api.eth.blockchain, block.Header(), true); err != nil {
523539
return nil, err
524540
}
525541
parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
526542
if parent == nil {
527-
return nil, fmt.Errorf("parent %x not found", block.ParentHash())
543+
return nil, fmt.Errorf("parent %#x not found", block.ParentHash())
528544
}
529-
var (
530-
signer = types.MakeSigner(api.config, block.Number())
531-
done = false
532-
blockPrefix = fmt.Sprintf("block_0x%x", block.Hash().Bytes()[:4])
533-
usedLogConfig = &vm.LogConfig{Debug: true}
534-
files []string
535-
reExec_val = defaultTraceReexec
536-
txHash *common.Hash
537-
)
538-
if stdConfig != nil {
539-
if stdConfig.Reexec != nil {
540-
reExec_val = *stdConfig.Reexec
541-
}
542-
if stdConfig.LogConfig != nil {
543-
usedLogConfig.DisableMemory = stdConfig.LogConfig.DisableMemory
544-
usedLogConfig.DisableStack = stdConfig.LogConfig.DisableStack
545-
usedLogConfig.DisableStorage = stdConfig.LogConfig.DisableStorage
546-
usedLogConfig.Limit = stdConfig.LogConfig.Limit
547-
}
548-
txHash = stdConfig.TxHash
545+
reexec := defaultTraceReexec
546+
if config != nil && config.Reexec != nil {
547+
reexec = *config.Reexec
549548
}
550-
statedb, err := api.computeStateDB(parent, reExec_val)
549+
statedb, err := api.computeStateDB(parent, reexec)
551550
if err != nil {
552551
return nil, err
553552
}
553+
// Retrieve the tracing configurations, or use default values
554+
var (
555+
logConfig vm.LogConfig
556+
txHash common.Hash
557+
)
558+
if config != nil {
559+
if config.LogConfig != nil {
560+
logConfig = *config.LogConfig
561+
}
562+
txHash = config.TxHash
563+
}
564+
logConfig.Debug = true
554565

566+
// Execute transaction, either tracing all or just the requested one
567+
var (
568+
signer = types.MakeSigner(api.config, block.Number())
569+
dumps []string
570+
)
555571
for i, tx := range block.Transactions() {
572+
// Prepare the trasaction for un-traced execution
556573
var (
557-
outfile *os.File
558-
err error
574+
msg, _ = tx.AsMessage(signer)
575+
vmctx = core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
576+
577+
vmConf vm.Config
578+
dump *os.File
579+
err error
559580
)
560-
msg, _ := tx.AsMessage(signer)
561-
vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
562-
vmConf := vm.Config{}
563-
if txHash == nil || bytes.Equal(txHash.Bytes(), tx.Hash().Bytes()) {
564-
prefix := fmt.Sprintf("%v-%d-0x%x-", blockPrefix, i, tx.Hash().Bytes()[:4])
565-
// Open a file to dump trace into
566-
outfile, err = ioutil.TempFile(os.TempDir(), prefix)
581+
// If the transaction needs tracing, swap out the configs
582+
if tx.Hash() == txHash || txHash == (common.Hash{}) {
583+
// Generate a unique temporary file to dump it into
584+
prefix := fmt.Sprintf("block_%#x-%d-%#x-", block.Hash().Bytes()[:4], i, tx.Hash().Bytes()[:4])
585+
586+
dump, err = ioutil.TempFile(os.TempDir(), prefix)
567587
if err != nil {
568588
return nil, err
569589
}
570-
files = append(files, outfile.Name())
590+
dumps = append(dumps, dump.Name())
591+
592+
// Swap out the noop logger to the standard tracer
571593
vmConf = vm.Config{
572594
Debug: true,
573-
Tracer: vm.NewJSONLogger(usedLogConfig, bufio.NewWriter(outfile)),
595+
Tracer: vm.NewJSONLogger(&logConfig, bufio.NewWriter(dump)),
574596
EnablePreimageRecording: true,
575597
}
576-
if txHash != nil { // Only one tx to trace
577-
done = true
578-
}
579598
}
599+
// Execute the transaction and flush any traces to disk
580600
vmenv := vm.NewEVM(vmctx, statedb, api.config, vmConf)
581601
_, _, _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()))
582602

583-
if outfile != nil {
584-
outfile.Close()
585-
log.Info("Wrote trace", "file", outfile.Name())
603+
if dump != nil {
604+
dump.Close()
605+
log.Info("Wrote standard trace", "file", dump.Name())
586606
}
587607
if err != nil {
588-
return files, err
608+
return dumps, err
589609
}
590610
// Finalize the state so any modifications are written to the trie
591611
statedb.Finalise(true)
592612

593-
if done {
613+
// If we've traced the transaction we were looking for, abort
614+
if tx.Hash() == txHash {
594615
break
595616
}
596617
}
597-
if txHash != nil && !done {
598-
return nil, fmt.Errorf("transaction hash not found in block")
599-
}
600-
return files, nil
618+
return dumps, nil
601619
}
602620

603621
// computeStateDB retrieves the state database associated with a certain block.
@@ -675,7 +693,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, hash common.Ha
675693
// Retrieve the transaction and assemble its EVM context
676694
tx, blockHash, _, index := rawdb.ReadTransaction(api.eth.ChainDb(), hash)
677695
if tx == nil {
678-
return nil, fmt.Errorf("transaction %x not found", hash)
696+
return nil, fmt.Errorf("transaction %#x not found", hash)
679697
}
680698
reexec := defaultTraceReexec
681699
if config != nil && config.Reexec != nil {
@@ -755,11 +773,11 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree
755773
// Create the parent state database
756774
block := api.eth.blockchain.GetBlockByHash(blockHash)
757775
if block == nil {
758-
return nil, vm.Context{}, nil, fmt.Errorf("block %x not found", blockHash)
776+
return nil, vm.Context{}, nil, fmt.Errorf("block %#x not found", blockHash)
759777
}
760778
parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
761779
if parent == nil {
762-
return nil, vm.Context{}, nil, fmt.Errorf("parent %x not found", block.ParentHash())
780+
return nil, vm.Context{}, nil, fmt.Errorf("parent %#x not found", block.ParentHash())
763781
}
764782
statedb, err := api.computeStateDB(parent, reexec)
765783
if err != nil {
@@ -778,10 +796,10 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree
778796
// Not yet the searched for transaction, execute on top of the current state
779797
vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{})
780798
if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
781-
return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
799+
return nil, vm.Context{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
782800
}
783801
// Ensure any modifications are committed to the state
784802
statedb.Finalise(true)
785803
}
786-
return nil, vm.Context{}, nil, fmt.Errorf("tx index %d out of range for block %x", txIndex, blockHash)
804+
return nil, vm.Context{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, blockHash)
787805
}

internal/web3ext/web3ext.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,11 +388,13 @@ web3._extend({
388388
name: 'standardTraceBadBlockToFile',
389389
call: 'debug_standardTraceBadBlockToFile',
390390
params: 2,
391+
inputFormatter: [null, null]
391392
}),
392393
new web3._extend.Method({
393394
name: 'standardTraceBlockToFile',
394395
call: 'debug_standardTraceBlockToFile',
395396
params: 2,
397+
inputFormatter: [null, null]
396398
}),
397399
new web3._extend.Method({
398400
name: 'traceBlockByNumber',

0 commit comments

Comments
 (0)