Skip to content
This repository has been archived by the owner on Jul 20, 2022. It is now read-only.

Receipt fixes #77

Closed

Conversation

benjamincburns
Copy link
Contributor

@benjamincburns benjamincburns commented Oct 12, 2018

Makes it so that receipts are returned when EVM runtime errors occur (e.g. REVERT). Adds missing status, from, and to fields to the transaction receipt.

@aludvik
Copy link

aludvik commented Oct 18, 2018

@benjamincburns Since this is a pretty substantial change (some previous transactions that were previously invalid are now valid), can you summarize the discussion from RocketChat about why this is the desired behavior, what the pros and cons are, and what use cases this support.

@benjamincburns
Copy link
Contributor Author

Go formatting issues are now fixed.

@benjamincburns
Copy link
Contributor Author

benjamincburns commented Oct 24, 2018

@aludvik sure thing.

To be clear, this change doesn't allow for contract state updates when transaction execution fails. It simply records the transaction execution failure in the transaction receipt format that is appropriate for the transaction family.

Prior to these changes there was no way for a client which submitted its transactions via Seth's RPC interface to determine whether the transaction was executed, and what the result of that execution was.

Via the Ethereum RPC interface, the usual transaction flow looks like this:

  1. Client submits a message call transaction to a contract address via either the eth_sendTransaction or the eth_sendRawTransaction RPC call
  2. Server responds with RPC response containing transaction hash in the result field
  3. Client uses the transaction hash returned by the server to poll for the result of the transaction via eth_getTransactionReceipt.
  4. Until the transaction is mined into a block, the server always returns null in response to the client's eth_getTransactionReceipt request.
  5. When the transaction is mined into a block, regardless of whether the transaction succeeded or failed, the server responds to eth_getTransactionReceipt with a valid transaction receipt.
  6. The client inspects the status field in eth_getTransactionReceipt to determine whether their transaction succeeded or failed.

If no receipt is produced when a message call to a contract address fails due to a runtime error (e.g. due to the REVERT opcode), then the client can't tell the difference between transaction failure, and the transaction never starting.

@benjamincburns
Copy link
Contributor Author

As to what use-cases this supports, I'm working on integrating the Truffle toolsuite with Sawtooth-Seth. See the blocked tickets on the commit-referenced Jira issue for more info.

Signed-off-by: Ben Burns <benjamin.c.burns@gmail.com>
@benjamincburns
Copy link
Contributor Author

Looks like I had some rust formatting issues as well - those should be fixed up now.

@benjamincburns benjamincburns force-pushed the receipt-fixes branch 2 times, most recently from 32c15f0 to 7145595 Compare October 24, 2018 05:53
@@ -238,6 +239,9 @@ def test_get_block_by_hash(self):
self.assertEqual(result["stateRoot"], "0x" + self.state_root)
self.assertEqual(result["gasUsed"], hex(self.gas))
self.assertEqual(result["transactions"][0], "0x" + self.txn_id)
self.assertEqual(result["status"], "0x" + self.status)
Copy link
Contributor

Choose a reason for hiding this comment

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

@benjamincburns benjamincburns force-pushed the receipt-fixes branch 2 times, most recently from 47b3065 to 1f3b704 Compare October 24, 2018 20:05
Signed-off-by: Ben Burns <benjamin.c.burns@gmail.com>
Copy link
Contributor

@knkski knkski left a comment

Choose a reason for hiding this comment

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

Some minor feedback, but overall LGTM

@@ -80,6 +80,7 @@ def setUpClass(cls):
# account values
cls.public_key = "036d7bb6ca0fd581eb037e91042320af97508003264f08545a9db134df215f373e"
cls.account_address = "434d46456b6973a678b77382fca0252629f4389f"
cls.account_address_b = bytes([0x43, 0x4d, 0x46, 0x45, 0x6b, 0x69, 0x73, 0xa6, 0x78, 0xb7, 0x73, 0x82, 0xfc, 0xa0, 0x25, 0x26, 0x29, 0xf4, 0x38, 0x9f])
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be worth writing this as cls.account_address_b = bytes.fromhex(cls.account_address) so that the two definitions don't get out of sync

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good point - I missed that helper function - will fix.

status=self.status,
to=self.contract_address_b,
)
setattr(receipt, 'from', self.account_address_b)
Copy link
Contributor

Choose a reason for hiding this comment

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

Wondering what the purpose of setattr is here vs just passing it into the constructor

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sadly due to a limitation of python you can't use reserved words as keyword arguments for a function. The protobuf devs seem to be aware of that limitation, but it's as yet unresolved, and setattr is the only viable workaround I could find.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll add a comment to make this more clear, since I'm already going to do that bytes.fromhex fix you mentioned elsewhere...

Copy link
Contributor

Choose a reason for hiding this comment

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

Cool, makes sense. Another option is that you could do is SethTransactionReceipt(**{'from': self.account_address_b, ...}), but either way works

Signed-off-by: Ben Burns <benjamin.c.burns@gmail.com>
@aludvik
Copy link

aludvik commented Oct 26, 2018

@benjamincburns Thanks for the response. Am I correct in understanding there are three types of validity with Ethereum transactions?

  1. Totally valid - The transaction "object" was valid and the execution was a success
  2. Valid but failed - The transaction "object" was valid but the execution failed
  3. Invalid - The transaction "object" was invalid because of something like a bad signature, bad payload, incorrect nonce.

Is that characterization accurate? Does the nonce still get updated if the transaction execution fails?

@benjamincburns
Copy link
Contributor Author

@aludvik sorry that I didn't see your question above! Yes, your characterization is accurate. The nonce gets updated in cases 1 and 2, as in these cases a transaction receipt is generated. Transaction receipts are included in block hash calculations, and as such they're stored on chain under the transaction receipt storage trie data structure.

@benjamincburns
Copy link
Contributor Author

Noticed that this branch has gone a bit stale, so I fixed up the outstanding conflicts. I've also ruthlessly culled the projects/issues I'm watching, so with any luck I won't miss future notifications on this PR!

@benjamincburns
Copy link
Contributor Author

benjamincburns commented Apr 18, 2019

FAIL: Missing Signed-Off Field

I suppose that's what I get for fixing conflicts with GitHub's internal tooling - will fix and force-push.

Signed-off-by: Ben Burns <benjamin.c.burns@gmail.com>
@vaporos
Copy link
Contributor

vaporos commented Apr 18, 2019

@benjamincburns Looks great.

Can you rebase on top of master (instead of adding the merge commit) and force-push?

Also, in your commit messages, can you remove the STL- from the first line? When we reference bugs (which isn't often currently), we prefer to follow https://chris.beams.io/posts/git-commit/ which is to put "Resolves: xxx" at the bottom of the commit message.

@benjamincburns
Copy link
Contributor Author

I'm not sure where this left off and it's been quite some time since the original submission. I've moved on to other projects in that time, so I think it's best if I go ahead and close.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants