-
Notifications
You must be signed in to change notification settings - Fork 71
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
feat: support for snapshot cheatcodes #427
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incredibly straightforward 👌
src/halmos/cheatcodes.py
Outdated
""" | ||
Generates a snapshot ID by hashing the current state (code, storage, and balance). | ||
""" | ||
m = hashlib.sha3_256() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we don't need the hash to be cryptographically secure for this, we'd be better off using a high quality regular hash function like xxh3_64 from https://pypi.org/project/xxhash/, about 10x faster:
# built-in sha3_256, not keccak
$ python -m timeit --setup="from hashlib import sha3_256" "sha3_256(b'').digest()"
500000 loops, best of 5: 892 nsec per loop
# xxh64, requires `pip install xxhash`
$ python -m timeit --setup="from xxhash import xxh64_digest" "xxh64_digest(b'')"
2000000 loops, best of 5: 101 nsec per loop
# xxh3_64, requires `pip install xxhash`
$ python -m timeit --setup="from xxhash import xxh3_64_digest" "xxh3_64_digest(b'')"
5000000 loops, best of 5: 98.3 nsec per loop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for suggestion!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wdyt? 7d08e7a
addr = addr if isinstance(addr, int) else addr.as_long() | ||
m.update(int.to_bytes(addr, length=32)) | ||
# simply the object address is used, as code remains unchanged after deployment | ||
m.update(int.to_bytes(id(code), length=32)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spidey sense: I would normally avoid using the value of id in computations, since it changes from run to run
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree, but it's acceptable in this case. actually, i'm not sure if z3.get_id() would be guaranteed to be deterministic. we also use uuid() for unique variable naming, so they would change from run to run anyway.
b424c17
to
7d08e7a
Compare
support for state and storage snapshots:
note: two structurally identical symbolic storages/states are given the same snapshot id, but those that are semantically equivalent may not be assigned the same snapshot id. (see SnapshotTest for examples.)