Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: add info about tracer config, rm revertReasonTracer #25509

Merged
merged 2 commits into from Aug 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 9 additions & 15 deletions docs/_dapp/builtin-tracers.md
Expand Up @@ -65,12 +65,20 @@ The `callTracer` tracks all the call frames executed during a transaction, inclu
| input | string | call data |
| output | string | return data |
| error | string | error, if any |
| revertReason | string | Solidity revert reason, if any |
| calls | []callframe | list of sub-calls |

Things to note about the call tracer:

- Calls to precompiles are also included in the result
- In case a frame reverts, the field `output` will contain the raw return data, unlike [revertReasonTracer](#revertreasontracer) which parses the data and returns the revert message
- In case a frame reverts, the field `output` will contain the raw return data
- In case the top level frame reverts, its `revertReason` field will contain the parsed reason of revert as returned by the Solidity contract

`callTracer` has an option to only trace the main (top-level) call and none of the sub-calls. This avoids extra processing for each call frame if only the top-level call info are required. Here's how it can be configured:

```terminal
> debug.traceTransaction('0xc73e70f6d60e63a71dabf90b9983f2cdd56b0cb7bcf1a205f638d630a95bba73', { tracer: 'callTracer', tracerConfig: { onlyTopCall: true } })
```

### noopTracer

Expand All @@ -87,20 +95,6 @@ Executing a transaction requires the prior state, including account of sender an
| code | string | hex-encoded bytecode |
| storage | map[string]string | storage slots of the contract |

### revertReasonTracer

The `revertReasonTracer` is useful for analyzing failed transactions. The return value is:

- In case the transaction reverted: reason of the revert as returned by the Solidity contract
- Error message for any other failure

Example:

```terminal
> debug.traceTransaction('0x97695ffb034be7e1faeb372a564bb951ba4ebf4fee4caff2f9d1702497bb2b8b', { tracer: 'revertReasonTracer' })
"execution reverted: tokensMintedPerAddress exceed MAX_TOKENS_MINTED_PER_ADDRESS"
```

## JS tracers

The following are a list of tracers written in JS that come as part of Geth:
Expand Down
6 changes: 4 additions & 2 deletions docs/_dapp/custom-tracer.md
Expand Up @@ -384,7 +384,7 @@ type opcounter struct {
reason error // Textual reason for the interruption
}

func newOpcounter(ctx *tracers.Context) tracers.Tracer {
func newOpcounter(ctx *tracers.Context, cfg json.RawMessage) tracers.Tracer {
return &opcounter{counts: make(map[string]int)}
}

Expand Down Expand Up @@ -442,7 +442,9 @@ func (t *opcounter) Stop(err error) {
}
```

As can be seen every method of the [EVMLogger interface](https://pkg.go.dev/github.com/ethereum/go-ethereum/core/vm#EVMLogger) needs to be implemented (even if empty). Key parts to notice are the `init()` function which registers the tracer in Geth, the `CaptureState` hook where the opcode counts are incremented and `GetResult` where the result is serialized and delivered. To test this out the source is first compiled with `make geth`. Then in the console it can be invoked through the usual API methods by passing in the name it was registered under:
As can be seen every method of the [EVMLogger interface](https://pkg.go.dev/github.com/ethereum/go-ethereum/core/vm#EVMLogger) needs to be implemented (even if empty). Key parts to notice are the `init()` function which registers the tracer in Geth, the `CaptureState` hook where the opcode counts are incremented and `GetResult` where the result is serialized and delivered. Note that the constructor takes in a `cfg json.RawMessage`. This will be filled with a JSON object that user provides to the tracer to pass in optional config fields.

To test out this tracer the source is first compiled with `make geth`. Then in the console it can be invoked through the usual API methods by passing in the name it was registered under:

```console
> debug.traceTransaction('0x7ae446a7897c056023a8104d254237a8d97783a92900a7b0f7db668a9432f384', { tracer: 'opcounter' })
Expand Down
8 changes: 6 additions & 2 deletions docs/_rpc/ns-debug.md
Expand Up @@ -744,11 +744,15 @@ specifies the options for this specific call. The possible options are:

#### JavaScript-based tracing

Specifying the `tracer` option in the second argument enables JavaScript-based tracing. In this mode, `tracer` is interpreted as a JavaScript expression that is expected to evaluate to an object which must expose the `result` and `fault` methods. There exist 3 additional methods, namely: `step`, `enter` and `exit`. You must provide either `step`, or `enter` AND `exit` (i.e. these two must be exposed together). You may expose all three if you choose to do so.
Specifying the `tracer` option in the second argument enables JavaScript-based tracing. In this mode, `tracer` is interpreted as a JavaScript expression that is expected to evaluate to an object which must expose the `result` and `fault` methods. There exist 4 additional methods, namely: `setup`, `step`, `enter`, and `exit`. `enter` and `exit` must be present or omitted together.

##### Setup

`setup` is invoked once, in the beginning when the tracer is being constructed by Geth for a given transaction. It takes in one argument `config`. `config` allows users to pass in options to the tracer. `config` is to be JSON-decoded for usage and its default value is `"{}"`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@s1na Can you please explain what these new config options are?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These configs are meant to be tracer-specific. I.e. each JS or native tracer can now define which options it accepts. Let's say the callTracer has the following option to only collect data about the top-level call:

debug.traceTransaction('<txhash>, { tracer: 'callTracer', tracerConfig: { onlyTopCall: true } })

Or we're contemplating adding the following option to the prestateTracer to also collect the state of each account after tx execution:

debug.traceTransaction('<txhash>, { tracer: 'prestateTracer': tracerConfig: { collectPostState: true } })

But passing collectPostState to callTracer will have no effect because callTracer doesn't parse/understand it.


##### Step

`step`is a function that takes two arguments, log and db, and is called for each step of the EVM, or when an error occurs, as the specified transaction is traced.
`step` is a function that takes two arguments, log and db, and is called for each step of the EVM, or when an error occurs, as the specified transaction is traced.

`log` has the following fields:

Expand Down