Skip to content

Commit

Permalink
add storage overlay checks pallet
Browse files Browse the repository at this point in the history
  • Loading branch information
vedhavyas committed Jan 17, 2025
1 parent ae83448 commit c3ee9a3
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 0 deletions.
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ members = [
"domains/runtime/*",
"domains/service",
"domains/test/runtime/*",
"domains/test/pallets/*",
"domains/test/service",
"shared/*",
"test/subspace-test-client",
Expand Down
35 changes: 35 additions & 0 deletions domains/test/pallets/storage_overlay_checks/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[package]
name = "pallet-storage-overlay-checks"
version = "0.1.0"
authors = ["Subspace Labs <https://subspace.network>"]
edition = "2021"
license = "0BSD"
homepage = "https://subspace.network"
repository = "https://github.com/autonomys/subspace"
description = "Test pallet to check the storage overlay changes"
include = [
"/src",
"/Cargo.toml",
]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] }
frame-support = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
frame-system = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
log = { version = "0.4.22", default-features = false }
scale-info = { version = "2.11.2", default-features = false, features = ["derive"] }
sp-core = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
sp-runtime = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }


[features]
default = ["std"]
std = [
"codec/std",
"frame-support/std",
"frame-system/std",
"log/std",
"scale-info/std",
"sp-core/std",
"sp-runtime/std",
]
202 changes: 202 additions & 0 deletions domains/test/pallets/storage_overlay_checks/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
//! Test pallet to check the overlay changes during the block execution and post block execution.
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(not(feature = "std"))]
extern crate alloc;

use frame_system::pallet_prelude::BlockNumberFor;
pub use pallet::*;
use sp_core::H256;

const LOG_TARGET: &str = "runtime::storage_overlay_checks";

#[frame_support::pallet]
mod pallet {
use crate::StorageParams;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::BlockNumberFor;
use sp_core::H256;
use sp_runtime::traits::Zero;

#[pallet::config]
pub trait Config: frame_system::Config {}

#[pallet::storage]
pub(super) type Svvq<T> = StorageValue<_, H256, ValueQuery>;

#[pallet::storage]
pub(super) type Svoq<T> = StorageValue<_, H256, OptionQuery>;

#[pallet::storage]
pub(super) type Smvq<T> = StorageMap<_, Identity, H256, H256, ValueQuery>;

#[pallet::storage]
pub(super) type Smoq<T> = StorageMap<_, Identity, H256, H256, OptionQuery>;

#[pallet::storage]
pub(super) type Sdmvq<T> =
StorageDoubleMap<_, Identity, H256, Identity, H256, H256, ValueQuery>;

#[pallet::storage]
pub(super) type Sdmoq<T> =
StorageDoubleMap<_, Identity, H256, Identity, H256, H256, OptionQuery>;

#[pallet::storage]
pub(super) type Snmvq<T> = StorageNMap<
_,
(
NMapKey<Identity, H256>,
NMapKey<Identity, H256>,
NMapKey<Identity, H256>,
),
H256,
ValueQuery,
>;

#[pallet::storage]
pub(super) type Snmoq<T> = StorageNMap<
_,
(
NMapKey<Identity, H256>,
NMapKey<Identity, H256>,
NMapKey<Identity, H256>,
),
H256,
OptionQuery,
>;

#[pallet::pallet]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);

#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_initialize(n: BlockNumberFor<T>) -> Weight {
// even blocks, storages must be set already and are emptied
// odd block, storages must be empty and are set
let params = StorageParams::default();
if n % BlockNumberFor::<T>::from(2u32) == Zero::zero() {
Pallet::<T>::check_storage_exists(n, params);
Pallet::<T>::clear_storage(n);
} else {
Pallet::<T>::check_storage_empty(n, params);
Pallet::<T>::set_storage(n, params);
}

Weight::zero()
}

fn on_finalize(n: BlockNumberFor<T>) {
// even blocks, storages must be emptied during initialize
// odd block, storages must be set during initialize
let params = StorageParams::default();
if n % BlockNumberFor::<T>::from(2u32) == Zero::zero() {
Pallet::<T>::check_storage_empty(n, params);
} else {
Pallet::<T>::check_storage_exists(n, params);
}
}
}
}

#[derive(Clone, Copy)]
struct StorageParams {
key1: H256,
key2: H256,
key3: H256,
value: H256,
}

impl Default for StorageParams {
fn default() -> Self {
Self {
key1: H256::repeat_byte(1),
key2: H256::repeat_byte(2),
key3: H256::repeat_byte(3),
value: H256::repeat_byte(4),
}
}
}

impl<T: Config> Pallet<T> {
fn set_storage(n: BlockNumberFor<T>, params: StorageParams) {
log::debug!(target: LOG_TARGET, "Setting storages at: {:?}", n);
let StorageParams {
key1,
key2,
key3,
value,
} = params;

Svvq::<T>::set(value);
Svoq::<T>::set(Some(value));
Smvq::<T>::set(key1, value);
Smoq::<T>::set(key1, Some(value));
Sdmvq::<T>::set(key1, key2, value);
Sdmoq::<T>::set(key1, key2, Some(value));
Snmvq::<T>::set((key1, key2, key3), value);
Snmoq::<T>::set((key1, key2, key3), Some(value));
}

fn clear_storage(n: BlockNumberFor<T>) {
log::debug!(target: LOG_TARGET, "Clearing storages at: {:?}", n);
Svvq::<T>::kill();
Svoq::<T>::kill();
let _ = Smvq::<T>::clear(u32::MAX, None);
let _ = Smoq::<T>::clear(u32::MAX, None);
let _ = Sdmvq::<T>::clear(u32::MAX, None);
let _ = Sdmoq::<T>::clear(u32::MAX, None);
let _ = Snmvq::<T>::clear(u32::MAX, None);
let _ = Snmoq::<T>::clear(u32::MAX, None);
}

fn check_storage_exists(n: BlockNumberFor<T>, params: StorageParams) {
log::debug!(target: LOG_TARGET, "Checking storages exists at: {:?}", n);
let StorageParams {
key1,
key2,
key3,
value,
} = params;

assert_eq!(Svvq::<T>::get(), value);
assert_eq!(Svoq::<T>::get(), Some(value));
assert_eq!(Smvq::<T>::get(key1), value);
assert_eq!(Smoq::<T>::get(key1), Some(value));
assert_eq!(Sdmvq::<T>::get(key1, key2), value);
assert_eq!(Sdmoq::<T>::get(key1, key2), Some(value));
assert_eq!(Snmvq::<T>::get((key1, key2, key3)), value);
assert_eq!(Snmoq::<T>::get((key1, key2, key3)), Some(value));
}

fn check_storage_empty(n: BlockNumberFor<T>, params: StorageParams) {
log::debug!(target: LOG_TARGET, "Checking storages empty at: {:?}", n);
let StorageParams {
key1,
key2,
key3,
value: _,
} = params;

assert!(!Svvq::<T>::exists());

assert!(!Svoq::<T>::exists());
assert_eq!(Svoq::<T>::get(), None);

assert!(!Smvq::<T>::contains_key(key1));

assert!(!Smoq::<T>::contains_key(key1));
assert_eq!(Smoq::<T>::get(key1), None);

assert!(!Sdmvq::<T>::contains_key(key1, key2));

assert!(!Sdmoq::<T>::contains_key(key1, key2));
assert_eq!(Sdmoq::<T>::get(key1, key2), None);

assert!(!Snmvq::<T>::contains_key((key1, key2, key3)));

assert!(!Snmoq::<T>::contains_key((key1, key2, key3)));
assert_eq!(Snmoq::<T>::get((key1, key2, key3)), None);
}
}
2 changes: 2 additions & 0 deletions domains/test/runtime/auto-id/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pallet-block-fees = { version = "0.1.0", path = "../../../pallets/block-fees", d
pallet-domain-id = { version = "0.1.0", path = "../../../pallets/domain-id", default-features = false }
pallet-domain-sudo = { version = "0.1.0", path = "../../../pallets/domain-sudo", default-features = false }
pallet-messenger = { version = "0.1.0", path = "../../../pallets/messenger", default-features = false }
pallet-storage-overlay-checks = { version = "0.1.0", path = "../../pallets/storage_overlay_checks", default-features = false }
pallet-timestamp = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
pallet-transaction-payment = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
pallet-transaction-payment-rpc-runtime-api = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
Expand Down Expand Up @@ -85,6 +86,7 @@ std = [
"pallet-domain-id/std",
"pallet-domain-sudo/std",
"pallet-messenger/std",
"pallet-storage-overlay-checks/std",
"pallet-timestamp/std",
"pallet-transaction-payment/std",
"pallet-transaction-payment-rpc-runtime-api/std",
Expand Down
5 changes: 5 additions & 0 deletions domains/test/runtime/auto-id/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,8 @@ impl pallet_domain_sudo::Config for Runtime {
type IntoRuntimeCall = IntoRuntimeCall;
}

impl pallet_storage_overlay_checks::Config for Runtime {}

// Create the runtime by composing the FRAME pallets that were previously configured.
//
// NOTE: Currently domain runtime does not naturally support the pallets with inherent extrinsics.
Expand Down Expand Up @@ -488,6 +490,9 @@ construct_runtime!(

// Sudo account
Sudo: pallet_domain_sudo = 100,

// checks
StorageOverlayChecks: pallet_storage_overlay_checks = 200,
}
);

Expand Down
2 changes: 2 additions & 0 deletions domains/test/runtime/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pallet-evm-precompile-modexp = { version = "2.0.0-dev", default-features = false
pallet-evm-precompile-sha3fips = { version = "2.0.0-dev", default-features = false, git = "https://github.com/autonomys/frontier", rev = "f80f9e2bad338f3bf3854b256b3c4edea23e5968" }
pallet-evm-precompile-simple = { version = "2.0.0-dev", default-features = false, git = "https://github.com/autonomys/frontier", rev = "f80f9e2bad338f3bf3854b256b3c4edea23e5968" }
pallet-messenger = { version = "0.1.0", path = "../../../pallets/messenger", default-features = false }
pallet-storage-overlay-checks = { version = "0.1.0", path = "../../pallets/storage_overlay_checks", default-features = false }
pallet-timestamp = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
pallet-transaction-payment = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
pallet-transaction-payment-rpc-runtime-api = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
Expand Down Expand Up @@ -98,6 +99,7 @@ std = [
"pallet-evm-precompile-sha3fips/std",
"pallet-evm-precompile-simple/std",
"pallet-messenger/std",
"pallet-storage-overlay-checks/std",
"pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std",
Expand Down
5 changes: 5 additions & 0 deletions domains/test/runtime/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,8 @@ impl pallet_domain_sudo::Config for Runtime {
type IntoRuntimeCall = IntoRuntimeCall;
}

impl pallet_storage_overlay_checks::Config for Runtime {}

// Create the runtime by composing the FRAME pallets that were previously configured.
//
// NOTE: Currently domain runtime does not naturally support the pallets with inherent extrinsics.
Expand Down Expand Up @@ -764,6 +766,9 @@ construct_runtime!(

// Sudo account
Sudo: pallet_domain_sudo = 100,

// checks
StorageOverlayChecks: pallet_storage_overlay_checks = 200,
}
);

Expand Down

0 comments on commit c3ee9a3

Please sign in to comment.