-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Commit
Expand EIP-3155 to include features for EOF.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
--- | ||
Check failure on line 1 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorpreamble is missing header(s): `description`
Check failure on line 1 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorpreamble is missing header(s): `description`
|
||
eip: TBD | ||
Check failure on line 2 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorpreamble header `eip` must be an unsigned integer
Check failure on line 2 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorfile name must reflect the preamble header `eip`
Check failure on line 2 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorpreamble header `eip` must be an unsigned integer
Check failure on line 2 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorfile name must reflect the preamble header `eip`
|
||
title: EOF/EVM Trace Specification | ||
author: Martin Holst Swende (@holiman), Marius van der Wijden (@MariusVanDerWijden), Danno Ferrin (@shemnon) | ||
discussions-to: TBD | ||
Check failure on line 5 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorpreamble header `discussions-to` is not a valid URL
Check failure on line 5 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorpreamble header `discussions-to` should point to a thread on ethereum-magicians.org
Check failure on line 5 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorpreamble header `discussions-to` is not a valid URL
Check failure on line 5 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorpreamble header `discussions-to` should point to a thread on ethereum-magicians.org
|
||
status: Draft | ||
type: Standards Track | ||
category: Interface | ||
created: 2024-08-13 | ||
--- | ||
|
||
## Abstract | ||
|
||
Updates the EIP-3155 JSON tracing specification to support EOF features and light tracing. | ||
Check failure on line 14 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorthe first match of the given pattern must be a link
Check failure on line 14 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorthe first match of the given pattern must be a link
|
||
|
||
## Motivation | ||
|
||
[EIP-3155](./eip-3155.md) defined a tracing standard for Legacy EVM operations. However, the EVM Object Format ([EIP-7692](./eip-7692.md)) adds a number of features that need to be reflected in debugging traces. | ||
|
||
The use of these traces has also moved out from state testing, including live block tracing and differential fuzzing, increasing the need to keep tracing up to date. | ||
|
||
This EIP has multiple goals: | ||
|
||
- Add members to the trace object to support new EOF features. | ||
- Support tracing contracts contained in an EOF container as well as uncontained "legacy" contracts in the same trace. | ||
- Clarify any previous ambiguities in the EIP-3155 specification. | ||
|
||
## Specification | ||
|
||
To promote clarity and provide a cohesive specification, the entire tracing specification will be presented with alterations in-line rather than as a set of diffs on top of EIP-3155. Differences will be highlighted in the Backwards Compatibility section. | ||
|
||
### Datatypes | ||
|
||
| Type | Explanation | Example | | ||
|------------|----------------------------------------------------------------|--------------------------------------| | ||
| Number | Plain json number | "pc":0 | | ||
| Hex-Number | Hex-encoded number | "gas":"0x2540be400" | | ||
| String | Plain string | "opName":"PUSH1" | | ||
| Hex-String | Hex-encoded string | "returnData":"0x60616203" | | ||
| Array | Array of Hex-Strings | "stack":["0x0", "0x0"] | | ||
| Key-Value | Key-Value structure with key and values encoded as hex strings | "storage":{"0x0":"0x1", "0x1":"0x1"} | | ||
| Boolean | Json bool can either be true or false | "pass": true | | ||
|
||
### Output | ||
|
||
- The client outputs one JSON object per EVM operation executed. | ||
- The client MUST NOT output multiple lines for the same operation execution. | ||
- The client MUST NOT output a line for the `STOP` operation if an error occurred, or if the contract runs out of instructions. | ||
|
||
Each object contains the following members. | ||
|
||
| Name | Type | Required | Explanation | | ||
|--------------|------------|-------------|------------------------------------------| | ||
| `pc` | Number | Yes | Program Counter | | ||
| `section` | Number | Yes if EOF | EOF Code Section | | ||
| `op` | Number | Yes | Opcode | | ||
| `immediate` | Hex-String | *see below* | Immediate argument of the Opcode | | ||
| `gas` | Hex-Number | Yes | Gas left before executing this operation | | ||
| `gasCost` | Hex-Number | No | Gas cost of this operation | | ||
| `memory` | Array | No | Array of all allocated values | | ||
| `memSize` | Number | Yes | Size of memory array | | ||
| `stack` | Array | Yes | Array of all values on the stack | | ||
| `depth` | Number | Yes | Depth of the call stack | | ||
| `fdepth` | Number | Yes if EOF | Depth of the EIP-4750 return stack | | ||
Check failure on line 64 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorthe first match of the given pattern must be a link
Check failure on line 64 in EIPS/eip-eof-tracing.md GitHub Actions / EIP Walidatorthe first match of the given pattern must be a link
|
||
| `returnData` | Hex-String | No | Data returned by function call | | ||
| `refund` | Hex-Number | Yes | Amount of **global** gas refunded | | ||
| `opName` | String | No | Name of the operation | | ||
| `error` | Hex-String | No | Description of an error or revert data | | ||
| `storage` | Map | No | Array of all stored values | | ||
|
||
|
||
- The `pc` value is zero indexed either from the beginning of the contract when the contract is not in an EOF container, or from the beginning of the code section when it is a contract contained in an EOF container. | ||
- The `section` member must only be present when tracing a contract that is contained in an EOF container. | ||
In cases where legacy and EOF contracts are in the same call trace the presence and absence of the `section` member indicates if the contract at that step is EOF or legacy. | ||
- The `immediate` member is optional for PUSH series instructions, and mandatory for all other operations that have immediate arguments. | ||
- The `gas`, `stack`, `memory` and `memSize`, `depth`, and `fdepth` members are the values *before* execution of the op. | ||
- The `gasCost` is the sum of all gas costs, including dynamic costs such as memory expansion, call stipend, and account warming costs. | ||
- All array attributes (`stack`, `memory`) MUST be initialized to empty arrays ("stack":[]` NOT `"stack":null`). | ||
- The `memory` or `storage` members may be omitted if they are empty or the client does not produce them. | ||
- The `memSize` member MUST be present regardless of `memory` support. Even when `memSize` is zero. | ||
- The `error` and `returnData` members can be omitted if they are empty. | ||
- If the prior trace line had an exceptional halt, `error` should identify the halt. Otherwise, if a `REVERT` operation occurred it should contain the revert reason. | ||
- The `storage` member should only include items read or written via `SSTORE` or `SLOAD`, and not the account's entire memory. | ||
- Clients SHOULD implement a way to disable recording the storage as the stateroot includes all storage updates. | ||
- Clients SHOULD output the members in the same order as listed in this EIP. | ||
|
||
*Example:* | ||
|
||
``` | ||
{"pc":0,"op":96,"gas":"0x2540be400","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":1,"error":null,"opName":"PUSH1"} | ||
``` | ||
|
||
### Summary Line | ||
|
||
At the end of execution, the client should print summary info. This summary MUST as a single JSON object. | ||
|
||
This info SHOULD have the following members. | ||
|
||
| Name | Type | Required | Explanation | | ||
|-------------|------------|----------|--------------------------------------------------------| | ||
| `stateRoot` | Hex-String | Yes | Root of the state trie after executing the transaction | | ||
| `output` | Hex-String | Yes | Return values of the function | | ||
| `gasUsed` | Hex-Number | Yes | All gas used by the transaction | | ||
| `pass` | Boolean | Yes | If the tx was successful, or if the test passed | | ||
| `time` | Number | No | Time in nanoseconds needed to execute the transaction | | ||
| `fork` | String | No | Name of the fork rules used for execution | | ||
|
||
*Example*: | ||
|
||
``` | ||
{"stateRoot":"0xd4c577737f5d20207d338c360c42d3af78de54812720e3339f7b27293ef195b7","output":"","gasUsed":"0x3","pass":"true","time":141485} | ||
``` | ||
|
||
## Rationale | ||
|
||
This EIP is an extension of the EIP-3155 tracing features that has been in use for years. Rather than dramatically re-boot the feature, the information was added to the existing traces. | ||
|
||
A "mini" trace was contemplated to allow for tracing to be included in tools such as `t8n` and to allow for more efficient RPC tracing calls, but that seemed sufficiently different that it would be a stand-alone EIP rather than an EIP that adds features to the existing tracing capabilities. | ||
|
||
## Backwards Compatibility | ||
|
||
Clients emitting tracing JSON for uncontained "legacy" contracts will produce a compatible trace, except as outlined below | ||
|
||
### Changes from EIP-3155 | ||
|
||
- The term Client Under Test or CUT has been replaced simply with "client." | ||
|
||
### Additions to EIP-3155 | ||
|
||
- The `immediate` member was added to support the large number of instructions that contain immediate operations. | ||
Without this change, users would need bytes of the contracts being executed to rationalize the traces. | ||
- The `section` and `fdepth` members were added to support [EIP-4750](./eip-4750) EOF Functions. | ||
- Added clarification around where `pc` indexes when run in an EOF container. | ||
|
||
### Clients | ||
|
||
This EIP is fully backward compatible with go-ethereum. OpenEthereum, Besu and Nethermind clients would have to change their JSON output of | ||
`openethereum-evm` `evmtool` and | ||
`nethtest` slightly do adhere to the new and stricter specs. New clients would need to implement this change if they want to be part of the differential fuzzing group. | ||
|
||
## Test Cases | ||
|
||
This is the trace output from the Ethereum Execution Specification Test from one of the parameterized executions of the test `test_eof_functions_contract_call_succeed` in `prague/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py`. Memory and return data are disabled. | ||
|
||
```json lines | ||
{"pc":0,"op":96,"gas":"0x2fa9e78","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"} | ||
{"pc":2,"op":96,"gas":"0x2fa9e75","gasCost":"0x3","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH1"} | ||
{"pc":4,"op":96,"gas":"0x2fa9e72","gasCost":"0x3","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"} | ||
{"pc":6,"op":96,"gas":"0x2fa9e6f","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"} | ||
{"pc":8,"op":96,"gas":"0x2fa9e6c","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"} | ||
{"pc":10,"op":97,"gas":"0x2fa9e69","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH2"} | ||
{"pc":13,"op":90,"gas":"0x2fa9e66","gasCost":"0x2","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0x1000"],"depth":1,"refund":0,"opName":"GAS"} | ||
{"pc":14,"op":241,"gas":"0x2fa9e64","gasCost":"0x2eeb414","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0x1000","0x2fa9e64"],"depth":1,"refund":0,"opName":"CALL"} | ||
{"pc":0,"section":0,"op":227,"immediate":"0x0001","gas":"0x2eea9ec","gasCost":"0x5","memSize":0,"stack":[],"depth":2,"refund":0,"opName":"CALLF"} | ||
{"pc":0,"section":1,"op":228,"gas":"0x2eea9e7","gasCost":"0x3","memSize":0,"stack":[],"depth":2,"fdepth":1,"refund":0,"opName":"RETF"} | ||
{"pc":3,"section":0,"op":0,"gas":"0x2eea9e4","gasCost":"0x0","memSize":0,"stack":[],"depth":2,"refund":0,"opName":"STOP"} | ||
{"pc":15,"op":96,"gas":"0x2fa9434","gasCost":"0x3","memSize":0,"stack":["0x1"],"depth":1,"refund":0,"opName":"PUSH1"} | ||
{"pc":17,"op":85,"gas":"0x2fa9431","gasCost":"0x5654","memSize":0,"stack":["0x1","0x0"],"depth":1,"refund":0,"opName":"SSTORE"} | ||
{"pc":18,"op":0,"gas":"0x2fa3ddd","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"STOP"} | ||
``` | ||
|
||
## Security Considerations | ||
|
||
Clients should be aware that tracing can be expensive both in terms of CPU overhead and network bandwidth. | ||
Tracing endpoints should not be enabled by default, and when they are enabled should have access restrictions on the network level. | ||
Failure to do so could result in a client being overwhelmed with requests and, if operating as a validator, cause the client to fail to provide execution attestations in a timely manner. | ||
|
||
Differential fuzzing is also a double-edged sword. | ||
While it allows client teams the ability to identify consensus splits, the client teams need to be prompt in fixing any issues that are discovered. | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](../LICENSE.md). |