Skip to content

Commit

Permalink
Add snapshot functionality to ink_sandbox (#2261)
Browse files Browse the repository at this point in the history
* Add Snapshot functionality

* Add Snapshot testing

* Add snapshot impl to sandbox_client
  • Loading branch information
0xLucca authored Nov 13, 2024
1 parent 11c637b commit 2609f17
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 0 deletions.
22 changes: 22 additions & 0 deletions crates/e2e/sandbox/src/api/system_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,26 @@ mod tests {
make_transfer(&mut sandbox, RECIPIENT, 1).expect("Failed to make transfer");
assert!(!sandbox.events().is_empty());
}

#[test]
fn snapshot_works() {
let mut sandbox = DefaultSandbox::default();

// Check state before
let block_before = sandbox.block_number();
let snapshot_before = sandbox.take_snapshot();

// Advance some blocks to have some state change
let _ = sandbox.build_blocks(5);
let block_after = sandbox.block_number();

// Check block number and state after
assert_eq!(block_before + 5, block_after);

// Restore state
sandbox.restore_snapshot(snapshot_before);

// Check state after restore
assert_eq!(block_before, sandbox.block_number());
}
}
19 changes: 19 additions & 0 deletions crates/e2e/sandbox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use pallet_contracts::{
};
/// Export pallets that are used in [`crate::create_sandbox`]
pub use {
frame_support::sp_runtime::testing::H256,
frame_support::{
self,
sp_runtime::{
Expand All @@ -43,6 +44,18 @@ pub use {
sp_io::TestExternalities,
};

/// A snapshot of the storage.
#[derive(Clone, Debug)]
pub struct Snapshot {
/// The storage raw key-value pairs.
pub storage: RawStorage,
/// The storage root hash.
pub storage_root: StorageRoot,
}

pub type RawStorage = Vec<(Vec<u8>, (Vec<u8>, i32))>;
pub type StorageRoot = H256;

/// Alias for the balance type.
type BalanceOf<R> =
<<R as pallet_contracts::Config>::Currency as Inspect<AccountIdFor<R>>>::Balance;
Expand Down Expand Up @@ -118,4 +131,10 @@ pub trait Sandbox {
fn convert_account_to_origin(
account: AccountIdFor<Self::Runtime>,
) -> <<Self::Runtime as frame_system::Config>::RuntimeCall as Dispatchable>::RuntimeOrigin;

/// Take a snapshot of the storage.
fn take_snapshot(&mut self) -> Snapshot;

/// Restore the storage from the given snapshot.
fn restore_snapshot(&mut self, snapshot: Snapshot);
}
27 changes: 27 additions & 0 deletions crates/e2e/sandbox/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ mod construct_runtime {
weights::Weight,
};

use $crate::Snapshot;

// Define the runtime type as a collection of pallets
construct_runtime!(
pub enum $runtime {
Expand Down Expand Up @@ -289,6 +291,31 @@ mod construct_runtime {
) -> <<Self::Runtime as $crate::frame_system::Config>::RuntimeCall as $crate::frame_support::sp_runtime::traits::Dispatchable>::RuntimeOrigin {
Some(account).into()
}

fn take_snapshot(&mut self) -> Snapshot {
let mut backend = self.ext.as_backend().clone();
let raw_key_values = backend
.backend_storage_mut()
.drain()
.into_iter()
.filter(|(_, (_, r))| *r > 0)
.collect::<Vec<(Vec<u8>, (Vec<u8>, i32))>>();
let root = backend.root().to_owned();
Snapshot {
storage: raw_key_values,
storage_root: root,
}
}

fn restore_snapshot(&mut self, snapshot: Snapshot) {
self.ext = $crate::TestExternalities::from_raw_snapshot(
snapshot.storage,
snapshot.storage_root,
Default::default(),
);
}


}
}

Expand Down
32 changes: 32 additions & 0 deletions crates/e2e/src/sandbox_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ pub mod preset {
Extension,
RuntimeMetadataPrefixed,
Sandbox,
Snapshot,
};
pub use pallet_contracts_mock_network::*;
use sp_runtime::traits::Dispatchable;
Expand Down Expand Up @@ -543,6 +544,37 @@ pub mod preset {
{
Some(account).into()
}

fn take_snapshot(&mut self) -> Snapshot {
EXT_PARAA.with(|v| {
let v = v.borrow();
let mut backend = v.as_backend().clone();
let raw_key_values = backend
.backend_storage_mut()
.drain()
.into_iter()
.filter(|(_, (_, r))| *r > 0)
.collect::<Vec<(Vec<u8>, (Vec<u8>, i32))>>();
let root = backend.root().to_owned();

Snapshot {
storage: raw_key_values,
storage_root: root,
}
})
}

fn restore_snapshot(&mut self, snapshot: ink_sandbox::Snapshot) {
EXT_PARAA.with(|v| {
let mut v = v.borrow_mut();

*v = ink_sandbox::TestExternalities::from_raw_snapshot(
snapshot.storage,
snapshot.storage_root,
Default::default(),
);
})
}
}
}
}

0 comments on commit 2609f17

Please sign in to comment.