-
Notifications
You must be signed in to change notification settings - Fork 247
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
314 additions
and
10 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.