This repository has been archived by the owner on Oct 28, 2021. It is now read-only.
Coming to agreement with geth on RIPEMD touch revert - another alternative solution #5664
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
(Alternative solutions were considered in #5652 and #5663)
This is the old issue, originated that time when both Geth and Parity had incorrect revert behavior, and then it was decided to introduce a hack into consensus rules instead of doing huge chain reorg.
The buggy behavior that is now a rule is basically: when precompiled contract with address
0x03
(RIPEMD160) is touched, then exception happens and state changes are reverted, this address should be still considered touched in the end, so that "remove empty touched accounts" rule (EIP-158) deletes it from the state at the end of transaction.There are several related tests created after this incident:
GeneralStateTests/stSpecialTest/tx_xcf416c53
- emulates the transaction where this special behavior took place on the main net. Here the gas given toCALL
to RIPEMD is not enough, so theCALL
itself fails, but then transaction proceeds further till success. RIPEMD stays touched and then is deleted. All clients pass this test (otherwise they wouldn't be able to do full sync)GeneralStateTests/stRevertTest/RevertPrecompiledTouch
andGeneralStateTests/stRevertTest/RevertPrecompiledTouch_storage
- hereCALL
to RIPEMD succeeds, but later execution runs out of gas. Changes to the state are reverted, but RIPEMD stays touched and then is deleted. In these tests we have different results than geth.Dimitriy now has regenerated these latter tests via geth, and now aleth doesn't pass them.
In geth all of these cases look to be handled by just one hack https://github.com/ethereum/go-ethereum/blob/7527215a68eaac8a880be83f3f1ded0ed82f6650/core/state/state_object.go#L145-L149
Our current hack covers only the first
tx_xcf416c53
case, because for us failingCALL
to precompile is a special case, that doesn't invoke any rollbackaleth/libethereum/Executive.cpp
Lines 313 to 318 in 007d89a
This PR change this hack to behavior similar to geth, covering both not enough gas passed to
CALL
and OOG afterCALL
.More references: