Skip to content

Commit

Permalink
Add history seeding pallet
Browse files Browse the repository at this point in the history
  • Loading branch information
dariolina authored and dastansam committed Sep 9, 2024
1 parent f73c757 commit 8fdb8d8
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 7 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

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

38 changes: 38 additions & 0 deletions crates/pallet-history-seeding/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[package]
name = "pallet-history-seeding"
version = "0.1.0"
edition = "2021"
description = "A pallet for seeding history of the network"
authors = ["Dariia Porechna <[email protected]>"]
repository = "https://github.com/autonomys/subspace"
license = "Apache-2.0"
readme = "README.md"
include = [
"/src",
"/Cargo.toml",
"/README.md",
]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] }
scale-info = { version = "2.11.2", default-features = false, features = ["derive"] }
frame-support = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "5626154d0781ac9a6ffd5a6207ed237f425ae631" }
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 = [
"codec/std",
"scale-info/std",
"frame-support/std",
"frame-system/std",
"sp-std/std",
]
try-runtime = ["frame-support/try-runtime"]
5 changes: 5 additions & 0 deletions crates/pallet-history-seeding/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Pallet History Seeding

The history seeding pallet allows an authorized account to add remarks to the blockchain, which can be used to seed historical data or important information into the chain's history. The authorized account for seeding can be set by root.

License: Apache-2.0
100 changes: 100 additions & 0 deletions crates/pallet-history-seeding/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#![cfg_attr(not(feature = "std"), no_std)]

use frame_support::pallet_prelude::*;
use frame_support::traits::{BuildGenesisConfig, Get};

#[cfg(test)]
mod tests;

pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_system::pallet_prelude::*;
use frame_system::{RawOrigin, WeightInfo};
use scale_info::prelude::vec::Vec;

#[pallet::config]
pub trait Config: frame_system::Config {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
}

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

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// History was seeded. [who, remark_size]
HistorySeeded { who: T::AccountId, remark_size: u32 },
}

#[pallet::error]
pub enum Error<T> {
/// The sender is not authorized to seed history
NotAuthorized,
}

#[pallet::storage]
#[pallet::getter(fn history_seeder)]
pub type HistorySeeder<T: Config> = StorageValue<_, T::AccountId, OptionQuery>;

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Seed history with a remark
/// TODO: add proper weight
#[pallet::call_index(0)]
#[pallet::weight((<T as frame_system::Config>::SystemWeightInfo::remark(remark.len() as u32) + T::DbWeight::get().reads(1), Pays::No))]
pub fn seed_history(origin: OriginFor<T>, remark: Vec<u8>) -> DispatchResult {
let who = ensure_signed(origin.clone())?;

// Ensure the sender is the authorized history seeder
ensure!(
Some(who.clone()) == Self::history_seeder(),
Error::<T>::NotAuthorized
);

// Add the remark to the block
frame_system::Pallet::<T>::remark(
RawOrigin::Signed(who.clone()).into(),
remark.clone(),
)
.map_err(|e| e.error)?;

// Emit an event
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<T>,
new_seeder: T::AccountId,
) -> DispatchResult {
ensure_root(origin)?;
HistorySeeder::<T>::put(new_seeder);
Ok(())
}
}

#[derive(frame_support::DefaultNoBound)]
#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
pub history_seeder: Option<T::AccountId>,
}

#[pallet::genesis_build]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
fn build(&self) {
if let Some(ref seeder) = self.history_seeder {
HistorySeeder::<T>::put(seeder);
}
}
}
}
106 changes: 106 additions & 0 deletions crates/pallet-history-seeding/src/tests.rs
Original file line number Diff line number Diff line change
@@ -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<Test>;

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::<Test>::default()
.build_storage()
.unwrap();
t.into()
}

#[test]
fn genesis_config_works() {
new_test_ext().execute_with(|| {
let genesis_config = pallet::GenesisConfig::<Test> {
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::<Test>::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::<Test>::NotAuthorized
);
assert_noop!(
HistorySeeding::seed_history(RuntimeOrigin::root(), remark),
sp_runtime::DispatchError::BadOrigin
);
});
}
9 changes: 6 additions & 3 deletions crates/subspace-malicious-operator/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(),
Expand All @@ -274,6 +274,9 @@ fn subspace_genesis_config(
initial_balances: genesis_domain_params.initial_balances,
}],
},
history_seeding: HistorySeedingConfig {
history_seeder: Some(sudo_account),
},
}
}

Expand Down
20 changes: 16 additions & 4 deletions crates/subspace-node/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -206,10 +207,14 @@ pub fn gemini_3h_compiled() -> Result<GenericChainSpec, String> {
]),
genesis_domains: vec![
evm_chain_spec::get_genesis_domain(SpecId::Gemini, sudo_account.clone())?,
auto_id_chain_spec::get_genesis_domain(SpecId::Gemini, sudo_account)?,
auto_id_chain_spec::get_genesis_domain(
SpecId::Gemini,
sudo_account.clone(),
)?,
],
},
CouncilDemocracyConfigParams::<BlockNumber>::production_params(),
sudo_account.clone(),
)?)
.map_err(|error| format!("Failed to serialize genesis config: {error}"))?,
)
Expand Down Expand Up @@ -316,10 +321,11 @@ pub fn devnet_config_compiled() -> Result<GenericChainSpec, String> {
]),
genesis_domains: vec![auto_id_chain_spec::get_genesis_domain(
SpecId::DevNet,
sudo_account,
sudo_account.clone(),
)?],
},
CouncilDemocracyConfigParams::<BlockNumber>::fast_params(),
sudo_account.clone(),
)?)
.map_err(|error| format!("Failed to serialize genesis config: {error}"))?,
)
Expand All @@ -330,6 +336,7 @@ pub fn devnet_config_compiled() -> Result<GenericChainSpec, String> {
pub fn dev_config() -> Result<GenericChainSpec, String> {
let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?;
let sudo_account = get_account_id_from_seed("Alice");
let history_seeder = get_account_id_from_seed("Bob");

Ok(GenericChainSpec::builder(wasm_binary, None)
.with_name("Subspace development")
Expand Down Expand Up @@ -380,6 +387,7 @@ pub fn dev_config() -> Result<GenericChainSpec, String> {
)?],
},
CouncilDemocracyConfigParams::<BlockNumber>::fast_params(),
history_seeder,
)?)
.map_err(|error| format!("Failed to serialize genesis config: {error}"))?,
))
Expand All @@ -395,6 +403,7 @@ fn subspace_genesis_config(
genesis_params: GenesisParams,
genesis_domain_params: GenesisDomainParams,
council_democracy_config_params: CouncilDemocracyConfigParams<BlockNumber>,
history_seeder_account: AccountId,
) -> Result<RuntimeGenesisConfig, String> {
let GenesisParams {
enable_rewards_at,
Expand Down Expand Up @@ -469,6 +478,9 @@ fn subspace_genesis_config(
.then_some(genesis_domain_params.permissioned_action_allowed_by),
genesis_domains,
},
history_seeding: HistorySeedingConfig {
history_seeder: Some(history_seeder_account),
},
})
}

Expand Down
Loading

0 comments on commit 8fdb8d8

Please sign in to comment.