From 176069cc959bc7275a94bf3a5403289ef63b7cb0 Mon Sep 17 00:00:00 2001 From: dastansam Date: Thu, 5 Sep 2024 19:21:52 +0200 Subject: [PATCH] Complete `history-seeding` pallet --- Cargo.lock | 4 + crates/pallet-history-seeding/Cargo.toml | 6 + crates/pallet-history-seeding/src/lib.rs | 82 +++++++------- crates/pallet-history-seeding/src/tests.rs | 106 ++++++++++++++++++ .../src/chain_spec.rs | 9 +- crates/subspace-node/src/chain_spec.rs | 8 +- 6 files changed, 172 insertions(+), 43 deletions(-) create mode 100644 crates/pallet-history-seeding/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index e8c2660097f..020fe501db7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7856,8 +7856,12 @@ version = "0.1.0" dependencies = [ "frame-support", "frame-system", + "pallet-sudo", "parity-scale-codec", "scale-info", + "sp-core", + "sp-io", + "sp-runtime", "sp-std", ] diff --git a/crates/pallet-history-seeding/Cargo.toml b/crates/pallet-history-seeding/Cargo.toml index 62d471826db..b5541da1027 100644 --- a/crates/pallet-history-seeding/Cargo.toml +++ b/crates/pallet-history-seeding/Cargo.toml @@ -20,6 +20,12 @@ frame-support = { default-features = false, git = "https://github.com/subspace/p frame-system = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "5626154d0781ac9a6ffd5a6207ed237f425ae631" } sp-std = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "5626154d0781ac9a6ffd5a6207ed237f425ae631" } +[dev-dependencies] +pallet-sudo = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "5626154d0781ac9a6ffd5a6207ed237f425ae631", features = ["std"] } +sp-core = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "5626154d0781ac9a6ffd5a6207ed237f425ae631" } +sp-io = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "5626154d0781ac9a6ffd5a6207ed237f425ae631" } +sp-runtime = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "5626154d0781ac9a6ffd5a6207ed237f425ae631" } + [features] default = ["std"] std = [ diff --git a/crates/pallet-history-seeding/src/lib.rs b/crates/pallet-history-seeding/src/lib.rs index 1f5f8a53102..a411a3dfd78 100644 --- a/crates/pallet-history-seeding/src/lib.rs +++ b/crates/pallet-history-seeding/src/lib.rs @@ -1,18 +1,20 @@ #![cfg_attr(not(feature = "std"), no_std)] -use frame_support::{pallet_prelude::*, traits::Get}; +use frame_support::pallet_prelude::*; +use frame_support::traits::{BuildGenesisConfig, Get}; -//use frame_system::pallet_prelude::*; -//use sp_std::prelude::*; +#[cfg(test)] +mod tests; pub use pallet::*; #[frame_support::pallet] pub mod pallet { use super::*; - use frame_system::{pallet_prelude::*, RawOrigin}; + use frame_system::pallet_prelude::*; + use frame_system::RawOrigin; use scale_info::prelude::vec::Vec; - + #[pallet::config] pub trait Config: frame_system::Config { type RuntimeEvent: From> + IsType<::RuntimeEvent>; @@ -25,7 +27,7 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// History was seeded. [who, remark_size] - HistorySeeded(T::AccountId, u32), + HistorySeeded { who: T::AccountId, remark_size: u32 }, } #[pallet::error] @@ -34,6 +36,10 @@ pub mod pallet { NotAuthorized, } + #[pallet::storage] + #[pallet::getter(fn history_seeder)] + pub type HistorySeeder = StorageValue<_, T::AccountId, OptionQuery>; + #[pallet::call] impl Pallet { /// Seed history with a remark @@ -42,53 +48,53 @@ pub mod pallet { #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), Pays::No))] pub fn seed_history(origin: OriginFor, remark: Vec) -> DispatchResult { let who = ensure_signed(origin.clone())?; - + // Ensure the sender is the authorized history seeder - ensure!(Some(who.clone()) == Self::history_seeder(), Error::::NotAuthorized); + ensure!( + Some(who.clone()) == Self::history_seeder(), + Error::::NotAuthorized + ); // Add the remark to the block - frame_system::Pallet::::remark(RawOrigin::Signed(who.clone()).into(), remark.clone()) - .map_err(|e| e.error)?; + frame_system::Pallet::::remark( + RawOrigin::Signed(who.clone()).into(), + remark.clone(), + ) + .map_err(|e| e.error)?; // Emit an event - Self::deposit_event(Event::HistorySeeded(who, remark.len() as u32)); + Self::deposit_event(Event::HistorySeeded { + who, + remark_size: remark.len() as u32, + }); Ok(()) } #[pallet::call_index(1)] #[pallet::weight(T::DbWeight::get().writes(1))] - pub fn set_history_seeder(origin: OriginFor, new_seeder: T::AccountId) -> DispatchResult { + pub fn set_history_seeder( + origin: OriginFor, + new_seeder: T::AccountId, + ) -> DispatchResult { ensure_root(origin)?; - >::put(new_seeder); + HistorySeeder::::put(new_seeder); Ok(()) } } - #[pallet::storage] - #[pallet::getter(fn history_seeder)] - pub type HistorySeeder = StorageValue<_, T::AccountId, OptionQuery>; + #[derive(frame_support::DefaultNoBound)] + #[pallet::genesis_config] + pub struct GenesisConfig { + pub history_seeder: Option, + } - // #[pallet::genesis_config] - // pub struct GenesisConfig { - // pub history_seeder: Option, - // } - - // #[cfg(feature = "std")] - // impl Default for GenesisConfig { - // fn default() -> Self { - // Self { history_seeder: None } - // } - // } - - // #[pallet::genesis_build] - // impl GenesisBuild for GenesisConfig { - // fn build(&self) { - // if let Some(ref seeder) = self.history_seeder { - // >::put(seeder); - // } - // } - // } + #[pallet::genesis_build] + impl BuildGenesisConfig for GenesisConfig { + fn build(&self) { + if let Some(ref seeder) = self.history_seeder { + HistorySeeder::::put(seeder); + } + } + } } - - diff --git a/crates/pallet-history-seeding/src/tests.rs b/crates/pallet-history-seeding/src/tests.rs new file mode 100644 index 00000000000..f5fa8f1be9a --- /dev/null +++ b/crates/pallet-history-seeding/src/tests.rs @@ -0,0 +1,106 @@ +use super::*; +use crate::{self as pallet_history_seeding}; +use frame_support::{assert_noop, assert_ok, construct_runtime, derive_impl}; +use frame_system as system; +use sp_runtime::BuildStorage; + +type Block = frame_system::mocking::MockBlock; + +construct_runtime!( + pub struct Test { + System: frame_system, + Sudo: pallet_sudo, + HistorySeeding: pallet_history_seeding, + } +); + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl frame_system::Config for Test { + type Block = Block; +} + +impl pallet_sudo::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type WeightInfo = (); +} + +impl pallet::Config for Test { + type RuntimeEvent = RuntimeEvent; +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = system::GenesisConfig::::default() + .build_storage() + .unwrap(); + t.into() +} + +#[test] +fn genesis_config_works() { + new_test_ext().execute_with(|| { + let genesis_config = pallet::GenesisConfig:: { + history_seeder: Some(1), + }; + genesis_config.build(); + assert_eq!(HistorySeeding::history_seeder(), Some(1)); + }); +} + +#[test] +fn set_history_seeder_works() { + new_test_ext().execute_with(|| { + assert_ok!(HistorySeeding::set_history_seeder(RuntimeOrigin::root(), 1)); + assert_eq!(HistorySeeding::history_seeder(), Some(1)); + + // Ensure only root can set the history seeder + assert_noop!( + HistorySeeding::set_history_seeder(RuntimeOrigin::signed(1), 2), + sp_runtime::DispatchError::BadOrigin + ); + }); +} + +#[test] +fn seed_history_works() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + + // Set the history seeder + assert_ok!(HistorySeeding::set_history_seeder(RuntimeOrigin::root(), 1)); + + // Seed history + let remark = vec![1, 2, 3]; + assert_ok!(HistorySeeding::seed_history( + RuntimeOrigin::signed(1), + remark.clone() + )); + + // Check if the event was emitted + System::assert_has_event(RuntimeEvent::HistorySeeding(Event::HistorySeeded { + who: 1, + remark_size: 3, + })); + + // Ensure unauthorized account cannot seed history + assert_noop!( + HistorySeeding::seed_history(RuntimeOrigin::signed(2), remark), + Error::::NotAuthorized + ); + }); +} + +#[test] +fn seed_history_fails_when_no_seeder_set() { + new_test_ext().execute_with(|| { + let remark = vec![1, 2, 3]; + assert_noop!( + HistorySeeding::seed_history(RuntimeOrigin::signed(1), remark.clone()), + Error::::NotAuthorized + ); + assert_noop!( + HistorySeeding::seed_history(RuntimeOrigin::root(), remark), + Error::::NotAuthorized + ); + }); +} diff --git a/crates/subspace-malicious-operator/src/chain_spec.rs b/crates/subspace-malicious-operator/src/chain_spec.rs index 8085f356e7e..b90bc008d01 100644 --- a/crates/subspace-malicious-operator/src/chain_spec.rs +++ b/crates/subspace-malicious-operator/src/chain_spec.rs @@ -14,8 +14,8 @@ use std::marker::PhantomData; use std::num::NonZeroU32; use subspace_runtime::{ AllowAuthoringBy, CouncilConfig, DemocracyConfig, DomainsConfig, EnableRewardsAt, - MaxDomainBlockSize, MaxDomainBlockWeight, RewardsConfig, RuntimeConfigsConfig, SubspaceConfig, - VestingConfig, + HistorySeedingConfig, MaxDomainBlockSize, MaxDomainBlockWeight, RewardsConfig, + RuntimeConfigsConfig, SubspaceConfig, VestingConfig, }; use subspace_runtime_primitives::{ AccountId, Balance, BlockNumber, CouncilDemocracyConfigParams, SSC, @@ -261,7 +261,7 @@ fn subspace_genesis_config( raw_genesis_storage: genesis_domain_params.raw_genesis_storage, // Domain config, mainly for placeholder the concrete value TBD - owner_account_id: sudo_account, + owner_account_id: sudo_account.clone(), domain_name: genesis_domain_params.domain_name, max_block_size: MaxDomainBlockSize::get(), max_block_weight: MaxDomainBlockWeight::get(), @@ -274,6 +274,9 @@ fn subspace_genesis_config( initial_balances: genesis_domain_params.initial_balances, }], }, + history_seeding: HistorySeedingConfig { + history_seeder: Some(sudo_account), + }, } } diff --git a/crates/subspace-node/src/chain_spec.rs b/crates/subspace-node/src/chain_spec.rs index 66ccff9de1f..68828b77403 100644 --- a/crates/subspace-node/src/chain_spec.rs +++ b/crates/subspace-node/src/chain_spec.rs @@ -33,8 +33,9 @@ use std::num::NonZeroU32; use subspace_core_primitives::PotKey; use subspace_runtime::{ AllowAuthoringBy, BalancesConfig, CouncilConfig, DemocracyConfig, DomainsConfig, - EnableRewardsAt, MaxDomainBlockSize, MaxDomainBlockWeight, RewardsConfig, RuntimeConfigsConfig, - RuntimeGenesisConfig, SubspaceConfig, SudoConfig, SystemConfig, VestingConfig, WASM_BINARY, + EnableRewardsAt, HistorySeedingConfig, MaxDomainBlockSize, MaxDomainBlockWeight, RewardsConfig, + RuntimeConfigsConfig, RuntimeGenesisConfig, SubspaceConfig, SudoConfig, SystemConfig, + VestingConfig, WASM_BINARY, }; use subspace_runtime_primitives::time::MILLISECS_PER_BLOCK; use subspace_runtime_primitives::{ @@ -469,6 +470,9 @@ fn subspace_genesis_config( .then_some(genesis_domain_params.permissioned_action_allowed_by), genesis_domains, }, + history_seeding: HistorySeedingConfig { + history_seeder: Some(sudo_account.clone()), + }, }) }