From c3ee9a33ee784a1d838da583f824ccdf7c2d229b Mon Sep 17 00:00:00 2001 From: vedhavyas Date: Fri, 17 Jan 2025 13:13:06 +0530 Subject: [PATCH] add storage overlay checks pallet --- Cargo.lock | 15 ++ Cargo.toml | 1 + .../pallets/storage_overlay_checks/Cargo.toml | 35 +++ .../pallets/storage_overlay_checks/src/lib.rs | 202 ++++++++++++++++++ domains/test/runtime/auto-id/Cargo.toml | 2 + domains/test/runtime/auto-id/src/lib.rs | 5 + domains/test/runtime/evm/Cargo.toml | 2 + domains/test/runtime/evm/src/lib.rs | 5 + 8 files changed, 267 insertions(+) create mode 100644 domains/test/pallets/storage_overlay_checks/Cargo.toml create mode 100644 domains/test/pallets/storage_overlay_checks/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 7a395a12e2..cb7079c34f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1037,6 +1037,7 @@ dependencies = [ "pallet-domain-id", "pallet-domain-sudo", "pallet-messenger", + "pallet-storage-overlay-checks", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", @@ -3319,6 +3320,7 @@ dependencies = [ "pallet-evm-precompile-sha3fips", "pallet-evm-precompile-simple", "pallet-messenger", + "pallet-storage-overlay-checks", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", @@ -7916,6 +7918,19 @@ dependencies = [ "sp-weights", ] +[[package]] +name = "pallet-storage-overlay-checks" +version = "0.1.0" +dependencies = [ + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + [[package]] name = "pallet-subspace" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 0ddc3ee148..11fc2511dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "domains/runtime/*", "domains/service", "domains/test/runtime/*", + "domains/test/pallets/*", "domains/test/service", "shared/*", "test/subspace-test-client", diff --git a/domains/test/pallets/storage_overlay_checks/Cargo.toml b/domains/test/pallets/storage_overlay_checks/Cargo.toml new file mode 100644 index 0000000000..f8deba67c4 --- /dev/null +++ b/domains/test/pallets/storage_overlay_checks/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "pallet-storage-overlay-checks" +version = "0.1.0" +authors = ["Subspace Labs "] +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", +] diff --git a/domains/test/pallets/storage_overlay_checks/src/lib.rs b/domains/test/pallets/storage_overlay_checks/src/lib.rs new file mode 100644 index 0000000000..b55a8e1d29 --- /dev/null +++ b/domains/test/pallets/storage_overlay_checks/src/lib.rs @@ -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 = StorageValue<_, H256, ValueQuery>; + + #[pallet::storage] + pub(super) type Svoq = StorageValue<_, H256, OptionQuery>; + + #[pallet::storage] + pub(super) type Smvq = StorageMap<_, Identity, H256, H256, ValueQuery>; + + #[pallet::storage] + pub(super) type Smoq = StorageMap<_, Identity, H256, H256, OptionQuery>; + + #[pallet::storage] + pub(super) type Sdmvq = + StorageDoubleMap<_, Identity, H256, Identity, H256, H256, ValueQuery>; + + #[pallet::storage] + pub(super) type Sdmoq = + StorageDoubleMap<_, Identity, H256, Identity, H256, H256, OptionQuery>; + + #[pallet::storage] + pub(super) type Snmvq = StorageNMap< + _, + ( + NMapKey, + NMapKey, + NMapKey, + ), + H256, + ValueQuery, + >; + + #[pallet::storage] + pub(super) type Snmoq = StorageNMap< + _, + ( + NMapKey, + NMapKey, + NMapKey, + ), + H256, + OptionQuery, + >; + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(n: BlockNumberFor) -> 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::::from(2u32) == Zero::zero() { + Pallet::::check_storage_exists(n, params); + Pallet::::clear_storage(n); + } else { + Pallet::::check_storage_empty(n, params); + Pallet::::set_storage(n, params); + } + + Weight::zero() + } + + fn on_finalize(n: BlockNumberFor) { + // even blocks, storages must be emptied during initialize + // odd block, storages must be set during initialize + let params = StorageParams::default(); + if n % BlockNumberFor::::from(2u32) == Zero::zero() { + Pallet::::check_storage_empty(n, params); + } else { + Pallet::::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 Pallet { + fn set_storage(n: BlockNumberFor, params: StorageParams) { + log::debug!(target: LOG_TARGET, "Setting storages at: {:?}", n); + let StorageParams { + key1, + key2, + key3, + value, + } = params; + + Svvq::::set(value); + Svoq::::set(Some(value)); + Smvq::::set(key1, value); + Smoq::::set(key1, Some(value)); + Sdmvq::::set(key1, key2, value); + Sdmoq::::set(key1, key2, Some(value)); + Snmvq::::set((key1, key2, key3), value); + Snmoq::::set((key1, key2, key3), Some(value)); + } + + fn clear_storage(n: BlockNumberFor) { + log::debug!(target: LOG_TARGET, "Clearing storages at: {:?}", n); + Svvq::::kill(); + Svoq::::kill(); + let _ = Smvq::::clear(u32::MAX, None); + let _ = Smoq::::clear(u32::MAX, None); + let _ = Sdmvq::::clear(u32::MAX, None); + let _ = Sdmoq::::clear(u32::MAX, None); + let _ = Snmvq::::clear(u32::MAX, None); + let _ = Snmoq::::clear(u32::MAX, None); + } + + fn check_storage_exists(n: BlockNumberFor, params: StorageParams) { + log::debug!(target: LOG_TARGET, "Checking storages exists at: {:?}", n); + let StorageParams { + key1, + key2, + key3, + value, + } = params; + + assert_eq!(Svvq::::get(), value); + assert_eq!(Svoq::::get(), Some(value)); + assert_eq!(Smvq::::get(key1), value); + assert_eq!(Smoq::::get(key1), Some(value)); + assert_eq!(Sdmvq::::get(key1, key2), value); + assert_eq!(Sdmoq::::get(key1, key2), Some(value)); + assert_eq!(Snmvq::::get((key1, key2, key3)), value); + assert_eq!(Snmoq::::get((key1, key2, key3)), Some(value)); + } + + fn check_storage_empty(n: BlockNumberFor, params: StorageParams) { + log::debug!(target: LOG_TARGET, "Checking storages empty at: {:?}", n); + let StorageParams { + key1, + key2, + key3, + value: _, + } = params; + + assert!(!Svvq::::exists()); + + assert!(!Svoq::::exists()); + assert_eq!(Svoq::::get(), None); + + assert!(!Smvq::::contains_key(key1)); + + assert!(!Smoq::::contains_key(key1)); + assert_eq!(Smoq::::get(key1), None); + + assert!(!Sdmvq::::contains_key(key1, key2)); + + assert!(!Sdmoq::::contains_key(key1, key2)); + assert_eq!(Sdmoq::::get(key1, key2), None); + + assert!(!Snmvq::::contains_key((key1, key2, key3))); + + assert!(!Snmoq::::contains_key((key1, key2, key3))); + assert_eq!(Snmoq::::get((key1, key2, key3)), None); + } +} diff --git a/domains/test/runtime/auto-id/Cargo.toml b/domains/test/runtime/auto-id/Cargo.toml index a69eed2e75..b2e7282260 100644 --- a/domains/test/runtime/auto-id/Cargo.toml +++ b/domains/test/runtime/auto-id/Cargo.toml @@ -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" } @@ -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", diff --git a/domains/test/runtime/auto-id/src/lib.rs b/domains/test/runtime/auto-id/src/lib.rs index 018f347322..25e151aa2e 100644 --- a/domains/test/runtime/auto-id/src/lib.rs +++ b/domains/test/runtime/auto-id/src/lib.rs @@ -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. @@ -488,6 +490,9 @@ construct_runtime!( // Sudo account Sudo: pallet_domain_sudo = 100, + + // checks + StorageOverlayChecks: pallet_storage_overlay_checks = 200, } ); diff --git a/domains/test/runtime/evm/Cargo.toml b/domains/test/runtime/evm/Cargo.toml index 2f26410460..f5977e6995 100644 --- a/domains/test/runtime/evm/Cargo.toml +++ b/domains/test/runtime/evm/Cargo.toml @@ -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" } @@ -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", diff --git a/domains/test/runtime/evm/src/lib.rs b/domains/test/runtime/evm/src/lib.rs index 1d50a4a141..00dee075e4 100644 --- a/domains/test/runtime/evm/src/lib.rs +++ b/domains/test/runtime/evm/src/lib.rs @@ -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. @@ -764,6 +766,9 @@ construct_runtime!( // Sudo account Sudo: pallet_domain_sudo = 100, + + // checks + StorageOverlayChecks: pallet_storage_overlay_checks = 200, } );