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

Embedding transaction status code in receipts #658

Merged
merged 6 commits into from
Nov 30, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions EIPS/eip-draft-returndata.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## Preamble

EIP: <to be assigned>
Copy link
Member

Choose a reason for hiding this comment

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

Number 658 seems to have been assigned to this one.

Title: Embedding transaction return data in receipts
Copy link
Member

Choose a reason for hiding this comment

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

I guess the title should now be changed to Embedding transaction status code in receipts.

Author: Nick Johnson <[email protected]>
Type: Standard Track
Category Core
Status: Draft
Copy link
Member

Choose a reason for hiding this comment

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

Status should now be Accepted.

Copy link
Member

Choose a reason for hiding this comment

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

No, more like Final.

Created: 2017-06-30
Requires: 140
Replaces: 98


## Abstract
This EIP replaces the intermediate state root field of the receipt with either the contract return data and status, or a hash of that value.

## Motivation
With the introduction of the REVERT opcode in EIP140, it is no longer possible for users to assume that a transaction failed iff it consumed all gas. As a result, there is no clear mechanism for callers to determine whether a transaction succeeded and the state changes contained in it were applied.
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: iff

Copy link
Member

Choose a reason for hiding this comment

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

I believe it's intended ("if and only if")

Copy link
Contributor

Choose a reason for hiding this comment

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

Here's a transaction that consumed all gas and didn't fail.

It was never possible to make the assumption to begin with. ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It wasn't, but people still did.


Full nodes can provide RPCs to get a transaction return status and value by replaying the transaction, but fast nodes can only do this for nodes after their pivot point, and light nodes cannot do this at all, making a non-consensus solution impractical.

Instead, we propose to replace the intermediate state root, already obsoleted by EIP98, with either the return status (1 for success, 0 for failure) and any return/revert data, or the hash of the above. This both allows callers to determine success status, and remedies the previous omission of return data from the receipt.

## Specification
Option 1: For blocks where block.number >= METROPOLIS_FORK_BLKNUM, the intermediate state root is replaced by `status + return_data`, where `status` is the 1 byte status code, with 0 indicating failure (due to any operation that can cause the transaction or top-level call to revert) and 1 indicating success, and `return_data` is the data returned from the `RETURN` or `REVERT` opcode of the top-level call, and where `+` indicates concatenation.

Option 2: For blocks where block.number >= METROPOLIS_FORK_BLKNUM, the intermediate state root is replaced by `keccak256(status + return_data)`, where `status`, `return_data` and `+` have meanings as described in option 1. Additionally, new wire protocol messages are added for `GetReturnData` and `ReturnData`, permitting nodes to fetch the status and return data for transactions contained in specified blocks.
Copy link
Member

Choose a reason for hiding this comment

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

Option 2 won't work since the data will be available only on nodes that actually ran the transaction. So you're back to the original issue you set out to solve. Also if you only have the hash of the result, there's no way to do a "success, but here's a message" scenario. Not sure if relevant.

Copy link
Member

Choose a reason for hiding this comment

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

I guess if you disallow "success + message", then we could use sha(success + <empty>) as the check in fast/light nodes to see if something went wrong without knowing what.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Option 2 would work by adding a new data type for nodes to synchronise: return data. Fast synced clients would fetch this for all past receipts, and light nodes would fetch it on demand.


## Rationale
Option 1 minimises additional complexity in the wire protocol and client synchronisation implementations by embedding all necessary data in the receipt itself, but may complicate the transition process by changing the relevant field from a fixed length hash to a variable length field. The implications of a transaction sender being able to add arbitrary length data to transaction receipts also need close examination from the perspective of gas costing.

Option 2 reduces overhead from data type changes, but introduces extra wire protocol complexity, and another record type for fast and light nodes to synchronise or fetch.

## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).