Skip to content

feat(evm): make vm.snapshots persistent #5487

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 4 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion evm/src/executor/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,9 @@ impl DatabaseExt for Backend {
current: &mut Env,
) -> Option<JournaledState> {
trace!(?id, "revert snapshot");
if let Some(mut snapshot) = self.inner.snapshots.remove(id) {
if let Some(mut snapshot) = self.inner.snapshots.remove_at(id) {
// Re-insert snapshot to persist it
self.inner.snapshots.insert_at(snapshot.clone(), id);
// need to check whether there's a global failure which means an error occurred either
// during the snapshot or even before
if self.is_global_failure(current_state) {
Expand Down
2 changes: 1 addition & 1 deletion evm/src/executor/backend/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use revm::{
use serde::{Deserialize, Serialize};

/// A minimal abstraction of a state at a certain point in time
#[derive(Default, Debug, Serialize, Deserialize)]
#[derive(Default, Clone, Debug, Serialize, Deserialize)]
pub struct StateSnapshot {
pub accounts: Map<B160, AccountInfo>,
pub storage: Map<B160, Map<U256, U256>>,
Expand Down
5 changes: 3 additions & 2 deletions evm/src/executor/fork/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,9 @@ impl ForkedDatabase {
}

pub fn revert_snapshot(&mut self, id: U256) -> bool {
let snapshot = { self.snapshots().lock().remove(id) };
let snapshot = { self.snapshots().lock().remove_at(id) };
if let Some(snapshot) = snapshot {
self.snapshots().lock().insert_at(snapshot.clone(), id);
Comment on lines +117 to +119
Copy link
Member Author

Choose a reason for hiding this comment

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

Kind of looks like a deadlock from a glance but it's not haha—both guards are dropped on the spot

let ForkDbSnapshot {
local,
snapshot: StateSnapshot { accounts, storage, block_hashes },
Expand Down Expand Up @@ -200,7 +201,7 @@ impl DatabaseCommit for ForkedDatabase {
/// Represents a snapshot of the database
///
/// This mimics `revm::CacheDB`
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct ForkDbSnapshot {
pub local: CacheDB<SharedBackend>,
pub snapshot: StateSnapshot,
Expand Down
15 changes: 15 additions & 0 deletions evm/src/executor/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,27 @@ impl<T> Snapshots<T> {
snapshot
}

/// Removes the snapshot with the given `id`.
///
/// Does not remove snapshots after it.
pub fn remove_at(&mut self, id: U256) -> Option<T> {
self.snapshots.remove(&id)
}

/// Inserts the new snapshot and returns the id
pub fn insert(&mut self, snapshot: T) -> U256 {
let id = self.next_id();
self.snapshots.insert(id, snapshot);
id
}

/// Inserts the new snapshot at the given `id`.
///
/// Does not auto-increment the next `id`.
pub fn insert_at(&mut self, snapshot: T, id: U256) -> U256 {
self.snapshots.insert(id, snapshot);
id
}
}

impl<T> Default for Snapshots<T> {
Expand Down