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

Equivalence fixes #681

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open

Equivalence fixes #681

wants to merge 7 commits into from

Conversation

msooseth
Copy link
Collaborator

@msooseth msooseth commented Mar 11, 2025

Description

This fixes two underlying issues with equivalence checking.

Creation now deploys the code and checks the difference of the deployed code

Firstly, it fixes the issue that we didn't check the deployed contract, as per Zoe's observation. This is because we never deployed the contract that was created and check its difference in behaviour. This is no longer the case, we now distinguish between create/no-create equivalence checking. Some of this code was written by Zoe, and I fixed up the rest.

Equivalence checking no longer assumes overapproximated calls/etc. return the same value

Secondly, during equivalence checking, we actually didn't distinguish the fresh variables added via overapproximation for code A and code B. So the overapproximations were somehow doing the "same thing" which is wrong, they may very well be called with different arguments, at different points of the run, etc. This false equivalence was because the variables were named the same. I now have a function rewriteFresh that sticks an A- or B- in front of these fresh variables, therefore making them symbolically different. This also means that we potentially return false positives. This is just the way things are with overapproximation. We could add constraints, such as (initial state + calldata) -> symbolic value and then these false positives will go away. However, for the moment, these are not added. This is future work.

Small Things

Currently, we cannot deal with symbolic code. Hence, the test constructor-diff-deploy is under ignoreTest. Maybe we could make it work, actually. The deployed code will NEVER have symbolic opcodes, only symbolic values. Hence, it could be possible to change the interpreter to work on this. Future work.

Both parseBlockCtx and parseTxCtx have been modified to remove the now very fragile gas context extraction. This context should pretty much be useless -- code really ought not to depend on gas. We could extract it, but I find that keeping code in that is not tested and not used is just a recipe for later headaches. I'd rather it isn't extracted, and if it really is necessary at a later point, we can extract it.

referencedFrameContext is now using exprToSMT, which makes it a lot more standard and less prone to breaking. It was essentially a bug that it wasn't doing that.

The Ord for Prop was incorrect. POr a b <= POr c d cannot be compared via a <= c || b <= d because in the case taht a == b and b >d it will return True, but it should return False. This has been fixed.

Git History etc.

Closes #647.

This is an updated version of #650 -- in a way that all commits by Zoe are preserved.

Checklist

  • tested locally
  • added automated tests
  • updated the docs
  • updated the changelog

@msooseth msooseth force-pushed the equiv-fix-mate branch 2 times, most recently from 07c494b to 33b41c7 Compare March 12, 2025 10:14
Should work this way, cleaner

Explain why test is ignored

Update changelog

Fixing git merge artefact

Fixing up git merge

Fixing some small bugs
@msooseth msooseth force-pushed the equiv-fix-mate branch 2 times, most recently from cc374e0 to 90d7155 Compare March 12, 2025 15:03
@msooseth msooseth changed the title [DRAFT] Equivalence fixes Equivalence fixes Mar 12, 2025
@msooseth msooseth force-pushed the equiv-fix-mate branch 3 times, most recently from 9b88719 to f874dad Compare March 13, 2025 11:16
@msooseth msooseth marked this pull request as ready for review March 13, 2025 14:15
@msooseth msooseth requested a review from zoep March 13, 2025 17:49
@msooseth msooseth mentioned this pull request Mar 17, 2025
4 tasks
Copy link
Collaborator

@zoep zoep left a comment

Choose a reason for hiding this comment

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

Very nice, thanks for this fix!

I had some minor comment. As an overall comment, maybe it is worth adding some more tests for deployment (for example one that covers equal constructors that deploy contracts that are not actually equal).

@@ -480,20 +483,23 @@ instance Eq Prop where
PImpl a b == PImpl c d = a == c && b == d
_ == _ = False

-- Note: we cannot compare via `a <= c || b <= d` because then
-- when a==c but b > d, we'd return TRUE, when we should be
-- returning FALSE.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it OK to return TRUE when a > b (and b < d)?

Copy link
Collaborator

Choose a reason for hiding this comment

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

If not, you can also consider a lexicographic ordering (a <= c || (a == c && b <= d))

CodeHash a@(LitAddr _) -> pure $ fromLazyText "codehash_" <> formatEAddr a
Gas prefix var -> pure $ fromLazyText $ "gas-" <> T.pack (TS.unpack prefix) <> T.pack (show var)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is dash instead of underscore here intentional?


-- If the original check was for create (i.e. undeployed code), then we must also check that the deployed
-- code is equivalent. The constraints from the undeployed code (aProps,bProps) influence this check.
checkCreatedDiff aOut bOut aProps bProps = do
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice!!!

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

Successfully merging this pull request may close these issues.

Equivalence checking does not treat empty store as equal to a store initialized to zero
2 participants