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
don't delete account and storage entries on commit #126
don't delete account and storage entries on commit #126
Conversation
hmm, perhaps keeping destroyed accounts has some side-effects? |
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.
selfdestruct, what else to say. :)
I am merkelizing everything in the state when running tests. I think i am skipping empty/zero values but I am not sure tbh, will check later.
@@ -87,26 +87,12 @@ impl<ExtDB: DatabaseRef> CacheDB<ExtDB> { | |||
impl<ExtDB: DatabaseRef> DatabaseCommit for CacheDB<ExtDB> { | |||
fn commit(&mut self, changes: Map<H160, Account>) { | |||
for (add, acc) in changes { | |||
if acc.is_empty() || matches!(acc.filth, Filth::Destroyed) { | |||
self.cache.remove(&add); | |||
self.storage.remove(&add); |
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.
Here, you need to set cache to Account::default
and iterate over storage.get(add).iter()
and set them all to zero
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.
@rakita you said set "cache to Account::default" but we're currently setting the changes
? is that right, or a mistake?
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.
@gakonst changes
are added after, because of this: #126 (comment)
self.insert_cache(add, acc.info); | ||
let storage = self.storage.entry(add).or_default(); | ||
if acc.filth.abandon_old_storage() { | ||
storage.clear(); |
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.
here iterate over all storage and set all values to zero
crates/revm/src/db/in_memory_db.rs
Outdated
for (index, value) in acc.storage { | ||
if value.is_zero() { | ||
storage.remove(&index); | ||
} else { | ||
storage.insert(index, value); | ||
} | ||
} | ||
if storage.is_empty() { | ||
self.storage.remove(&add); | ||
} |
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.
for this for
and if
use extend
@mattsse in |
I guess we'd also need to skip 0 in storage now when computing |
zero storage slots are already skipped. I am not sure why it is not working. I vaguely remember there are some funky things with merkelization in tests where some empty accounts get merkelized I will need to manually run it and compare it. |
@mattsse For tests that means that there are preloaded empty accounts and not all of them are touched (called) and those empty accounts need to appear in Merkle trie. I added |
@@ -86,26 +100,25 @@ impl<ExtDB: DatabaseRef> CacheDB<ExtDB> { | |||
// TODO It is currently only committing to cached in-memory DB | |||
impl<ExtDB: DatabaseRef> DatabaseCommit for CacheDB<ExtDB> { | |||
fn commit(&mut self, changes: Map<H160, Account>) { | |||
// clear storage by setting all values to `0` | |||
fn clear_storage(storage: &mut HashMap<U256, U256>) { | |||
storage.values_mut().for_each(|val| { |
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.
something to consider in the future, maybe we want to convert these to rayon parallel iters? maybe not worth it
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.
For this particular thing, it would be best to introduce storage incarnation: https://github.com/ledgerwatch/erigon/blob/devel/docs/programmers_guide/db_walkthrough.MD#table-plainstate
In general, for introducing rayon, we need to be careful that we have a good amount of data and processing that we want to iterate/Parallelize on.
@@ -87,26 +87,12 @@ impl<ExtDB: DatabaseRef> CacheDB<ExtDB> { | |||
impl<ExtDB: DatabaseRef> DatabaseCommit for CacheDB<ExtDB> { | |||
fn commit(&mut self, changes: Map<H160, Account>) { | |||
for (add, acc) in changes { | |||
if acc.is_empty() || matches!(acc.filth, Filth::Destroyed) { | |||
self.cache.remove(&add); | |||
self.storage.remove(&add); |
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.
@rakita you said set "cache to Account::default" but we're currently setting the changes
? is that right, or a mistake?
} else { | ||
self.insert_cache(add, acc.info); | ||
self.insert_change(add, acc.info); |
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.
same q here, what's the diff between cache / change? should we add a note that this is a temp fix?
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.
It is because of this: #126 (comment)
the cache
is loaded from the external DB.
the changes
is what is applied from commit
.
LGTM - couple comments above, should we try to release this ASAP to fix the downstream bugs in Foundry? |
I think this is good to merge, don't think this has any downside |
Hey i will merge it as it is, but check in forge if it breaks something as in using |
Good point - will keep it in mind before we update^ thanks! |
As discovered here foundry-rs/foundry#1894
deleting storage or account entries does not play nice with fork mode which basically does:
So deleting accounts/slots (when empty) would result in the fork's account/slot being served and not 0 or the empty account.
Solution
on
CacheDb::commit
don't deleteAccountInfo
or storage entries in the CacheDb's mapsalso bumps to v1.6.0