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.
(ctx context.Context, message core.Message, vmctx vm.Context, statedb *state.StateDB, config *TraceConfig)
| 590 | // executes the given message in the provided environment. The return value will |
| 591 | // be tracer dependent. |
| 592 | func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, vmctx vm.Context, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { |
| 593 | // Assemble the structured logger or the JavaScript tracer |
| 594 | var ( |
| 595 | tracer vm.Tracer |
| 596 | err error |
| 597 | ) |
| 598 | switch { |
| 599 | case config != nil && config.Tracer != nil: |
| 600 | // Define a meaningful timeout of a single transaction trace |
| 601 | timeout := defaultTraceTimeout |
| 602 | if config.Timeout != nil { |
| 603 | if timeout, err = time.ParseDuration(*config.Timeout); err != nil { |
| 604 | return nil, err |
| 605 | } |
| 606 | } |
| 607 | // Constuct the JavaScript tracer to execute with |
| 608 | if tracer, err = tracers.New(*config.Tracer); err != nil { |
| 609 | return nil, err |
| 610 | } |
| 611 | // Handle timeouts and RPC cancellations |
| 612 | deadlineCtx, cancel := context.WithTimeout(ctx, timeout) |
| 613 | go func() { |
| 614 | <-deadlineCtx.Done() |
| 615 | tracer.(*tracers.Tracer).Stop(errors.New("execution timeout")) |
| 616 | }() |
| 617 | defer cancel() |
| 618 | |
| 619 | case config == nil: |
| 620 | tracer = vm.NewStructLogger(nil) |
| 621 | |
| 622 | default: |
| 623 | tracer = vm.NewStructLogger(config.LogConfig) |
| 624 | } |
| 625 | // Run the transaction with tracing enabled. |
| 626 | vmenv := vm.NewEVM(vmctx, statedb, api.config, vm.Config{Debug: true, Tracer: tracer}) |
| 627 | |
| 628 | ret, gas, failed, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas())) |
| 629 | if err != nil { |
| 630 | return nil, fmt.Errorf("tracing failed: %v", err) |
| 631 | } |
| 632 | // Depending on the tracer type, format and return the output |
| 633 | switch tracer := tracer.(type) { |
| 634 | case *vm.StructLogger: |
| 635 | return &cpcapi.ExecutionResult{ |
| 636 | Gas: gas, |
| 637 | Failed: failed, |
| 638 | ReturnValue: fmt.Sprintf("%x", ret), |
| 639 | StructLogs: cpcapi.FormatLogs(tracer.StructLogs()), |
| 640 | }, nil |
| 641 | |
| 642 | case *tracers.Tracer: |
| 643 | return tracer.GetResult() |
| 644 | |
| 645 | default: |
| 646 | panic(fmt.Sprintf("bad tracer type %T", tracer)) |
| 647 | } |
| 648 | } |
| 649 |
no test coverage detected