Browse Source

blog-module: update blog ownership and add weights

conectado 4 years ago
parent
commit
33436c3b26

+ 4 - 0
Cargo.lock

@@ -3743,6 +3743,10 @@ dependencies = [
  "frame-support",
  "frame-system",
  "pallet-balances",
+ "pallet-common",
+ "pallet-membership",
+ "pallet-staking-handler",
+ "pallet-timestamp",
  "parity-scale-codec",
  "sp-arithmetic",
  "sp-core",

+ 7 - 2
runtime-modules/blog/Cargo.toml

@@ -11,19 +11,24 @@ frame-support = { package = 'frame-support', default-features = false, git = 'ht
 frame-system = { package = 'frame-system', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 codec = { package = 'parity-scale-codec', version = '1.0.0', default-features = false, features = ['derive'] }
 sp-arithmetic = { package = 'sp-arithmetic', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
+common = { package = 'pallet-common', default-features = false, path = '../common'}
 
 #Benchmark dependencies
 frame-benchmarking = { package = 'frame-benchmarking', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca', optional = true}
+membership = { package = 'pallet-membership', default-features = false, path = '../membership', optional = true}
+balances = { package = 'pallet-balances', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca', optional = true}
 
 [dev-dependencies]
 sp-io = { package = 'sp-io', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 sp-core = { package = 'sp-core', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 balances = { package = 'pallet-balances', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
-
+membership = { package = 'pallet-membership', default-features = false, path = '../membership' }
+staking-handler = { package = 'pallet-staking-handler', default-features = false, path = '../staking-handler' }
+pallet-timestamp = { package = 'pallet-timestamp', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 
 [features]
 default = ['std']
-runtime-benchmarks = ['frame-benchmarking']
+runtime-benchmarks = ['frame-benchmarking', 'membership', 'balances']
 std = [
 	'codec/std',
 	'sp-std/std',

+ 120 - 56
runtime-modules/blog/src/benchmarking.rs

@@ -1,12 +1,17 @@
 #![cfg(feature = "runtime-benchmarks")]
 use super::*;
-use frame_benchmarking::{benchmarks_instance, Zero};
+use balances::Module as Balances;
+use frame_benchmarking::{account, benchmarks_instance, Zero};
+use frame_support::traits::Currency;
 use frame_system::Module as System;
 use frame_system::{EventRecord, RawOrigin};
+use membership::Module as Membership;
+use sp_runtime::traits::Bounded;
 use sp_std::convert::TryInto;
 use Module as Blog;
 
 const MAX_BYTES: u32 = 16384;
+const SEED: u32 = 0;
 
 fn assert_last_event<T: Trait<I>, I: Instance>(generic_event: <T as Trait<I>>::Event) {
     let events = System::<T>::events();
@@ -19,37 +24,96 @@ fn assert_last_event<T: Trait<I>, I: Instance>(generic_event: <T as Trait<I>>::E
     assert_eq!(event, &system_event);
 }
 
-fn get_blog_owner<T: Trait<I>, I: Instance>() -> T::AccountId {
-    T::AccountId::default()
+fn get_byte(num: u32, byte_number: u8) -> u8 {
+    ((num & (0xff << (8 * byte_number))) >> 8 * byte_number) as u8
 }
 
-fn generate_post<T: Trait<I>, I: Instance>() -> (T::AccountId, T::PostId) {
-    let caller_id = get_blog_owner::<T, I>();
-    assert_eq!(Blog::<T, I>::post_count(), Zero::zero());
+fn member_funded_account<T: Trait<I> + membership::Trait + balances::Trait, I: Instance>(
+    name: &'static str,
+    id: u32,
+) -> (T::AccountId, T::MemberId) {
+    let account_id = account::<T::AccountId>(name, id, SEED);
+    let handle = handle_from_id::<T>(id);
 
-    Blog::<T, I>::create_post(
-        RawOrigin::Signed(caller_id.clone()).into(),
-        vec![0u8],
-        vec![0u8],
+    let _ = Balances::<T>::make_free_balance_be(
+        &account_id,
+        <T as balances::Trait>::Balance::max_value(),
+    );
+
+    let params = membership::BuyMembershipParameters {
+        root_account: account_id.clone(),
+        controller_account: account_id.clone(),
+        name: None,
+        handle: Some(handle),
+        avatar_uri: None,
+        about: None,
+        referrer_id: None,
+    };
+
+    Membership::<T>::buy_membership(RawOrigin::Signed(account_id.clone()).into(), params).unwrap();
+
+    let member_id = T::MemberId::from(id.try_into().unwrap());
+    Membership::<T>::add_staking_account_candidate(
+        RawOrigin::Signed(account_id.clone()).into(),
+        member_id.clone(),
+    )
+    .unwrap();
+    Membership::<T>::confirm_staking_account(
+        RawOrigin::Signed(account_id.clone()).into(),
+        member_id.clone(),
+        account_id.clone(),
     )
     .unwrap();
 
+    (account_id, member_id)
+}
+
+// Method to generate a distintic valid handle
+// for a membership. For each index.
+fn handle_from_id<T: membership::Trait>(id: u32) -> Vec<u8> {
+    let min_handle_length = 1;
+
+    let mut handle = vec![];
+
+    for i in 0..4 {
+        handle.push(get_byte(id, i));
+    }
+
+    while handle.len() < (min_handle_length as usize) {
+        handle.push(0u8);
+    }
+
+    handle
+}
+
+fn generate_post<T: Trait<I>, I: Instance>() -> T::PostId {
+    assert_eq!(Blog::<T, I>::post_count(), Zero::zero());
+
+    Blog::<T, I>::create_post(RawOrigin::Root.into(), vec![0u8], vec![0u8]).unwrap();
+
     let post_id = T::PostId::zero();
 
     assert_eq!(Blog::<T, I>::post_count(), One::one());
 
     assert!(Blog::<T, I>::post_by_id(post_id) == Post::<T, I>::new(vec![0u8], vec![0u8]));
 
-    (caller_id, post_id)
+    post_id
 }
 
 fn generate_reply<T: Trait<I>, I: Instance>(
     creator_id: T::AccountId,
+    participant_id: ParticipantId<T>,
     post_id: T::PostId,
 ) -> T::ReplyId {
     let creator_origin = RawOrigin::Signed(creator_id);
-    let participant_id = Blog::<T, I>::get_participant(creator_origin.clone().into()).unwrap();
-    Blog::<T, I>::create_reply(creator_origin.clone().into(), post_id, None, vec![0u8]).unwrap();
+    Blog::<T, I>::create_reply(
+        creator_origin.clone().into(),
+        participant_id,
+        post_id,
+        None,
+        vec![0u8],
+    )
+    .unwrap();
 
     assert!(
         Blog::<T, I>::reply_by_id(post_id, T::ReplyId::zero())
@@ -60,14 +124,16 @@ fn generate_reply<T: Trait<I>, I: Instance>(
 }
 
 benchmarks_instance! {
+    where_clause { where T: balances::Trait, T: membership::Trait }
+
     _ {}
+
     create_post {
         let t in 0 .. MAX_BYTES;
         let b in 0 .. MAX_BYTES;
-        let caller_id = get_blog_owner::<T, I>();
         assert_eq!(Blog::<T, I>::post_count(), Zero::zero());
 
-    }:_(RawOrigin::Signed(caller_id), vec![0u8; t.try_into().unwrap()], vec![0u8; b.try_into().unwrap()])
+    }:_(RawOrigin::Root, vec![0u8; t.try_into().unwrap()], vec![0u8; b.try_into().unwrap()])
     verify {
         assert_eq!(Blog::<T, I>::post_count(), One::one());
 
@@ -80,18 +146,18 @@ benchmarks_instance! {
     }
 
     lock_post {
-        let (creator_id, post_id) = generate_post::<T, I>();
-    }: _(RawOrigin::Signed(creator_id), post_id)
+        let post_id = generate_post::<T, I>();
+    }: _(RawOrigin::Root, post_id)
     verify {
         assert!(Blog::<T, I>::post_by_id(post_id).is_locked());
         assert_last_event::<T, I>(RawEvent::PostLocked(post_id).into());
     }
 
     unlock_post {
-        let (creator_id, post_id) = generate_post::<T, I>();
-        Blog::<T, I>::lock_post(RawOrigin::Signed(creator_id.clone()).into(), post_id).unwrap();
+        let post_id = generate_post::<T, I>();
+        Blog::<T, I>::lock_post(RawOrigin::Root.into(), post_id).unwrap();
         assert!(Blog::<T, I>::post_by_id(post_id).is_locked());
-    }: _(RawOrigin::Signed(creator_id), post_id)
+    }: _(RawOrigin::Root, post_id)
     verify {
         assert!(!Blog::<T, I>::post_by_id(post_id).is_locked());
         assert_last_event::<T, I>(RawEvent::PostUnlocked(post_id).into());
@@ -101,9 +167,9 @@ benchmarks_instance! {
         let t in 0 .. MAX_BYTES;
         let b in 0 .. MAX_BYTES;
 
-        let (creator_id, post_id) = generate_post::<T, I>();
+        let post_id = generate_post::<T, I>();
     }: _(
-        RawOrigin::Signed(creator_id),
+        RawOrigin::Root,
         post_id,
         Some(vec![1u8; t.try_into().unwrap()]),
         Some(vec![1u8; b.try_into().unwrap()])
@@ -114,23 +180,23 @@ benchmarks_instance! {
             Post::<T, I>::new(vec![1u8; t.try_into().unwrap()], vec![1u8; b.try_into().unwrap()])
         );
         assert_last_event::<T, I>(RawEvent::PostEdited(post_id).into());
-
     }
 
     create_reply_to_post {
         let t in 0 .. MAX_BYTES;
 
-        let (creator_id, post_id) = generate_post::<T, I>();
-        let creator_origin = RawOrigin::Signed(creator_id);
+        let post_id = generate_post::<T, I>();
+        let (account_id, participant_id) = member_funded_account::<T, I>("caller", 0);
+        let origin = RawOrigin::Signed(account_id);
     }: create_reply(
-        creator_origin.clone(),
+        origin.clone(),
+        participant_id,
         post_id,
         None,
         vec![0u8; t.try_into().unwrap()]
     )
     verify {
         let mut expected_post = Post::<T, I>::new(vec![0u8], vec![0u8]);
-        let participant_id = Blog::<T, I>::get_participant(creator_origin.into()).unwrap();
         expected_post.increment_replies_counter();
         assert!(Blog::<T, I>::post_by_id(post_id) == expected_post);
         assert!(
@@ -148,22 +214,21 @@ benchmarks_instance! {
     create_reply_to_reply {
         let t in 0 .. MAX_BYTES;
 
-        let (creator_id, post_id) = generate_post::<T, I>();
-        let reply_id = generate_reply::<T, I>(creator_id.clone(), post_id.clone());
-        let creator_origin = RawOrigin::Signed(creator_id);
+        let post_id = generate_post::<T, I>();
+        let (account_id, participant_id) = member_funded_account::<T, I>("caller", 0);
+        let reply_id = generate_reply::<T, I>(account_id.clone(), participant_id, post_id.clone());
+        let origin = RawOrigin::Signed(account_id);
         let mut expected_post = Post::<T, I>::new(vec![0u8], vec![0u8]);
         expected_post.increment_replies_counter();
         assert!(Blog::<T, I>::post_by_id(post_id) == expected_post);
     }: create_reply(
-        creator_origin.clone(),
+        origin.clone(),
+        participant_id,
         post_id,
         Some(reply_id),
         vec![0u8; t.try_into().unwrap()]
     )
     verify {
-        let participant_id = Blog::<T, I>::get_participant(
-            creator_origin.clone().into()
-        ).unwrap();
         expected_post.increment_replies_counter();
         assert!(Blog::<T, I>::post_by_id(post_id) == expected_post);
         assert!(
@@ -183,19 +248,18 @@ benchmarks_instance! {
     edit_reply {
         let t in 0 .. MAX_BYTES;
 
-        let (creator_id, post_id) = generate_post::<T, I>();
-        let reply_id = generate_reply::<T, I>(creator_id.clone(), post_id.clone());
-        let creator_origin = RawOrigin::Signed(creator_id);
+        let post_id = generate_post::<T, I>();
+        let (account_id, participant_id) = member_funded_account::<T, I>("caller", 0);
+        let reply_id = generate_reply::<T, I>(account_id.clone(), participant_id, post_id.clone());
+        let origin = RawOrigin::Signed(account_id);
     }: _(
-        creator_origin.clone(),
+        origin.clone(),
+        participant_id,
         post_id,
         reply_id,
         vec![1u8; t.try_into().unwrap()]
     )
     verify {
-        let participant_id = Blog::<T, I>::get_participant(
-            creator_origin.clone().into()
-        ).unwrap();
         assert_eq!(
             Blog::<T, I>::reply_by_id(post_id, reply_id).text_hash,
             T::Hashing::hash(&vec![1u8; t.try_into().unwrap()])
@@ -213,37 +277,37 @@ benchmarks_instance! {
     }
 
     react_to_post {
-        let (creator_id, post_id) = generate_post::<T, I>();
-        let creator_origin = RawOrigin::Signed(creator_id);
+        let post_id = generate_post::<T, I>();
+        let (account_id, participant_id) = member_funded_account::<T, I>("caller", 0);
+        let origin = RawOrigin::Signed(account_id);
     }: react(
-        creator_origin.clone(),
+        origin.clone(),
+        participant_id,
         0,
         post_id,
         None
         )
     verify {
-        let owner = Blog::<T, I>::get_participant(
-            creator_origin.clone().into()
-        ).unwrap();
-        assert_last_event::<T, I>(RawEvent::PostReactionsUpdated(owner, post_id, 0).into());
+        assert_last_event::<T, I>(
+            RawEvent::PostReactionsUpdated(participant_id, post_id, 0).into()
+        );
     }
 
     react_to_reply {
-        let (creator_id, post_id) = generate_post::<T, I>();
-        let reply_id = generate_reply::<T, I>(creator_id.clone(), post_id.clone());
-        let creator_origin = RawOrigin::Signed(creator_id);
+        let post_id = generate_post::<T, I>();
+        let (account_id, participant_id) = member_funded_account::<T, I>("caller", 0);
+        let reply_id = generate_reply::<T, I>(account_id.clone(), participant_id, post_id.clone());
+        let origin = RawOrigin::Signed(account_id);
     }: react(
-        creator_origin.clone(),
+        origin.clone(),
+        participant_id,
         0,
         post_id,
         Some(reply_id)
     )
     verify {
-        let owner = Blog::<T, I>::get_participant(
-            creator_origin.clone().into()
-        ).unwrap();
         assert_last_event::<T, I>(
-            RawEvent::ReplyReactionsUpdated(owner, post_id, reply_id, 0).into()
+            RawEvent::ReplyReactionsUpdated(participant_id, post_id, reply_id, 0).into()
         );
     }
 }

+ 3 - 0
runtime-modules/blog/src/errors.rs

@@ -7,6 +7,9 @@ decl_error! {
         /// A non-owner is trying to do a privilegeded action.
         BlogOwnershipError,
 
+        /// A non-member is trying to participate
+        MembershipError,
+
         /// Post do not exists.
         PostNotFound,
 

+ 90 - 42
runtime-modules/blog/src/lib.rs

@@ -40,14 +40,16 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
 use codec::{Codec, Decode, Encode};
+use common::origin::MemberOriginValidator;
 use errors::Error;
 pub use frame_support::dispatch::{DispatchError, DispatchResult};
-use frame_support::traits::EnsureOrigin;
+use frame_support::weights::Weight;
 use frame_support::{
     decl_event, decl_module, decl_storage, ensure, traits::Get, Parameter, StorageDoubleMap,
 };
 use sp_arithmetic::traits::{BaseArithmetic, One};
-use sp_runtime::traits::{Hash, MaybeSerialize, MaybeSerializeDeserialize, Member};
+use sp_runtime::traits::{Hash, MaybeSerialize, Member};
+use sp_runtime::SaturatedConversion;
 use sp_std::prelude::*;
 
 mod benchmarking;
@@ -63,13 +65,31 @@ type ReactionsNumber = u64;
 /// Number of reactions, presented in runtime
 pub const REACTIONS_MAX_NUMBER: ReactionsNumber = 5;
 
-// The pallet's configuration trait.
-pub trait Trait<I: Instance = DefaultInstance>: frame_system::Trait {
-    /// Origin from which blog owner must come.
-    type BlogOwnerEnsureOrigin: EnsureOrigin<Self::Origin, Success = Self::AccountId>;
+/// Blogger participant ID alias for the member of the system.
+pub type ParticipantId<T> = common::MemberId<T>;
+
+/// blog WeightInfo.
+/// Note: This was auto generated through the benchmark CLI using the `--weight-trait` flag
+pub trait WeightInfo {
+    fn create_post(t: u32, b: u32) -> Weight;
+    fn lock_post() -> Weight;
+    fn unlock_post() -> Weight;
+    fn edit_post(t: u32, b: u32) -> Weight;
+    fn create_reply_to_post(t: u32) -> Weight;
+    fn create_reply_to_reply(t: u32) -> Weight;
+    fn edit_reply(t: u32) -> Weight;
+    fn react_to_post() -> Weight;
+    fn react_to_reply() -> Weight;
+}
 
+// The pallet's configuration trait.
+pub trait Trait<I: Instance = DefaultInstance>: frame_system::Trait + common::Trait {
     /// Origin from which participant must come.
-    type ParticipantEnsureOrigin: EnsureOrigin<Self::Origin, Success = Self::ParticipantId>;
+    type ParticipantEnsureOrigin: MemberOriginValidator<
+        Self::Origin,
+        ParticipantId<Self>,
+        Self::AccountId,
+    >;
 
     /// The overarching event type.
     type Event: From<Event<Self, I>> + Into<<Self as frame_system::Trait>::Event>;
@@ -80,15 +100,6 @@ pub trait Trait<I: Instance = DefaultInstance>: frame_system::Trait {
     /// The maximum number of replies to a post.
     type RepliesMaxNumber: Get<MaxNumber>;
 
-    /// Type for the participant id.
-    type ParticipantId: Parameter
-        + Default
-        + Clone
-        + Copy
-        + Member
-        + MaybeSerializeDeserialize
-        + Ord;
-
     /// Type of identifier for blog posts.
     type PostId: Parameter
         + Member
@@ -112,6 +123,9 @@ pub trait Trait<I: Instance = DefaultInstance>: frame_system::Trait {
         + PartialEq
         + From<u64>
         + Into<u64>;
+
+    /// Weight information for extrinsics in this pallet.
+    type WeightInfo: WeightInfo;
 }
 
 /// Type, representing blog related post structure
@@ -220,7 +234,7 @@ pub struct Reply<T: Trait<I>, I: Instance> {
     /// Reply text hash
     text_hash: T::Hash,
     /// Participant id, associated with a reply owner
-    owner: T::ParticipantId,
+    owner: ParticipantId<T>,
     /// Reply`s parent id
     parent_id: ParentId<T::ReplyId, T::PostId>,
 }
@@ -249,7 +263,7 @@ impl<T: Trait<I>, I: Instance> Reply<T, I> {
     /// Create new reply with given text and owner id
     fn new(
         text: Vec<u8>,
-        owner: T::ParticipantId,
+        owner: ParticipantId<T>,
         parent_id: ParentId<T::ReplyId, T::PostId>,
     ) -> Self {
         Self {
@@ -260,7 +274,7 @@ impl<T: Trait<I>, I: Instance> Reply<T, I> {
     }
 
     /// Check if account_id is reply owner
-    fn is_owner(&self, account_id: &T::ParticipantId) -> bool {
+    fn is_owner(&self, account_id: &ParticipantId<T>) -> bool {
         self.owner == *account_id
     }
 
@@ -286,7 +300,7 @@ decl_storage! {
         ReplyById get (fn reply_by_id): double_map hasher(blake2_128_concat) T::PostId, hasher(blake2_128_concat) T::ReplyId => Reply<T, I>;
 
         /// Mapping, representing AccountId -> All presented reactions state mapping by unique post or reply identificators.
-        pub Reactions get(fn reactions): double_map hasher(blake2_128_concat) (T::PostId, Option<T::ReplyId>), hasher(blake2_128_concat) T::ParticipantId => [bool; REACTIONS_MAX_NUMBER as usize];
+        pub Reactions get(fn reactions): double_map hasher(blake2_128_concat) (T::PostId, Option<T::ReplyId>), hasher(blake2_128_concat) ParticipantId<T> => [bool; REACTIONS_MAX_NUMBER as usize];
     }
 }
 
@@ -301,7 +315,10 @@ decl_module! {
         type Error = Error<T, I>;
 
         /// Blog owner can create posts, related to a given blog, if related blog is unlocked
-        #[weight = 10_000_000] // TODO: adjust weight
+        #[weight = T::WeightInfo::create_post(
+                title.len().saturated_into(),
+                body.len().saturated_into()
+            )]
         pub fn create_post(origin, title: Vec<u8>, body: Vec<u8>) -> DispatchResult  {
 
             // Ensure blog -> owner relation exists
@@ -330,7 +347,7 @@ decl_module! {
 
         /// Blog owner can lock posts, related to a given blog,
         /// making post immutable to any actions (replies creation, post editing, reactions, etc.)
-        #[weight = 10_000_000] // TODO: adjust weight
+        #[weight = T::WeightInfo::lock_post()]
         pub fn lock_post(origin, post_id: T::PostId) -> DispatchResult {
 
             // Ensure blog -> owner relation exists
@@ -353,7 +370,7 @@ decl_module! {
 
         /// Blog owner can unlock posts, related to a given blog,
         /// making post accesible to previously forbidden actions
-        #[weight = 10_000_000] // TODO: adjust weight
+        #[weight = T::WeightInfo::unlock_post()]
         pub fn unlock_post(origin, post_id: T::PostId) -> DispatchResult {
 
             // Ensure blog -> owner relation exists
@@ -376,7 +393,7 @@ decl_module! {
 
         /// Blog owner can edit post, related to a given blog (if unlocked)
         /// with a new title and/or body
-        #[weight = 10_000_000] // TODO: adjust weight
+        #[weight = Module::<T, I>::edit_post_weight(&new_title, &new_body)]
         pub fn edit_post(
             origin,
             post_id: T::PostId,
@@ -405,14 +422,15 @@ decl_module! {
 
         /// Create either root post reply or direct reply to reply
         /// (Only accessible, if related blog and post are unlocked)
-        #[weight = 10_000_000] // TODO: adjust weight
+        #[weight = Module::<T, I>::create_reply_weight(text.len())]
         pub fn create_reply(
             origin,
+            participant_id: ParticipantId<T>,
             post_id: T::PostId,
             reply_id: Option<T::ReplyId>,
             text: Vec<u8>
         ) -> DispatchResult {
-            let reply_owner = Self::get_participant(origin)?;
+            Self::ensure_valid_participant(origin, participant_id)?;
 
             // Ensure post with given id exists
             let post = Self::ensure_post_exists(post_id)?;
@@ -427,9 +445,9 @@ decl_module! {
             let reply = if let Some(reply_id) = reply_id {
                 // Check parent reply existance in case of direct reply
                 Self::ensure_reply_exists(post_id, reply_id)?;
-                Reply::<T, I>::new(text, reply_owner, ParentId::Reply(reply_id))
+                Reply::<T, I>::new(text, participant_id, ParentId::Reply(reply_id))
             } else {
-                Reply::<T, I>::new(text, reply_owner, ParentId::Post(post_id))
+                Reply::<T, I>::new(text, participant_id, ParentId::Post(post_id))
             };
 
             //
@@ -445,24 +463,25 @@ decl_module! {
 
             if let Some(reply_id) = reply_id {
                 // Trigger event
-                Self::deposit_event(RawEvent::DirectReplyCreated(reply_owner, post_id, reply_id, post_replies_count));
+                Self::deposit_event(RawEvent::DirectReplyCreated(participant_id, post_id, reply_id, post_replies_count));
             } else {
                 // Trigger event
-                Self::deposit_event(RawEvent::ReplyCreated(reply_owner, post_id, post_replies_count));
+                Self::deposit_event(RawEvent::ReplyCreated(participant_id, post_id, post_replies_count));
             }
             Ok(())
         }
 
         /// Reply owner can edit reply with a new text
         /// (Only accessible, if related blog and post are unlocked)
-        #[weight = 10_000_000] // TODO: adjust weight
+        #[weight = T::WeightInfo::edit_reply(new_text.len().saturated_into())]
         pub fn edit_reply(
             origin,
+            participant_id: ParticipantId<T>,
             post_id: T::PostId,
             reply_id: T::ReplyId,
             new_text: Vec<u8>
         ) -> DispatchResult {
-            let reply_owner = Self::get_participant(origin)?;
+            Self::ensure_valid_participant(origin, participant_id)?;
 
             // Ensure post with given id exists
             let post = Self::ensure_post_exists(post_id)?;
@@ -474,7 +493,7 @@ decl_module! {
             let reply = Self::ensure_reply_exists(post_id, reply_id)?;
 
             // Ensure reply -> owner relation exists
-            Self::ensure_reply_ownership(&reply, &reply_owner)?;
+            Self::ensure_reply_ownership(&reply, &participant_id)?;
 
             //
             // == MUTATION SAFE ==
@@ -490,15 +509,16 @@ decl_module! {
 
         /// Submit either post reaction or reply reaction
         /// In case, when you resubmit reaction, it`s status will be changed to an opposite one
-        #[weight = 10_000_000] // TODO: adjust weight
+        #[weight = Module::<T, I>::react_weight()]
         pub fn react(
             origin,
+            participant_id: ParticipantId<T>,
             // reaction index in array
             index: ReactionsNumber,
             post_id: T::PostId,
             reply_id: Option<T::ReplyId>
         ) {
-            let owner = Self::get_participant(origin)?;
+            Self::ensure_valid_participant(origin, participant_id)?;
 
             // Ensure index is valid & reaction under given index exists
             Self::ensure_reaction_index_is_valid(index)?;
@@ -520,9 +540,9 @@ decl_module! {
 
             // Trigger event
             if let Some(reply_id) = reply_id {
-                Self::deposit_event(RawEvent::ReplyReactionsUpdated(owner, post_id, reply_id, index));
+                Self::deposit_event(RawEvent::ReplyReactionsUpdated(participant_id, post_id, reply_id, index));
             } else {
-                Self::deposit_event(RawEvent::PostReactionsUpdated(owner, post_id, index));
+                Self::deposit_event(RawEvent::PostReactionsUpdated(participant_id, post_id, index));
             }
         }
 
@@ -530,9 +550,37 @@ decl_module! {
 }
 
 impl<T: Trait<I>, I: Instance> Module<T, I> {
+    // edit_post_weight
+    fn edit_post_weight(title: &Option<Vec<u8>>, body: &Option<Vec<u8>>) -> Weight {
+        let title_len: u32 = title.as_ref().map_or(0, |t| t.len().saturated_into());
+        let body_len: u32 = body.as_ref().map_or(0, |b| b.len().saturated_into());
+
+        T::WeightInfo::edit_post(title_len, body_len)
+    }
+
+    // calculate react weight
+    fn react_weight() -> Weight {
+        T::WeightInfo::react_to_post().max(T::WeightInfo::react_to_reply())
+    }
+
+    // calculate create_reply weight
+    fn create_reply_weight(text_len: usize) -> Weight {
+        let text_len: u32 = text_len.saturated_into();
+        T::WeightInfo::create_reply_to_post(text_len)
+            .max(T::WeightInfo::create_reply_to_reply(text_len))
+    }
+
     // Get participant id from origin
-    fn get_participant(origin: T::Origin) -> Result<T::ParticipantId, DispatchError> {
-        Ok(T::ParticipantEnsureOrigin::ensure_origin(origin)?)
+    fn ensure_valid_participant(
+        origin: T::Origin,
+        participant_id: ParticipantId<T>,
+    ) -> Result<(), DispatchError> {
+        let account_id = frame_system::ensure_signed(origin)?;
+        ensure!(
+            T::ParticipantEnsureOrigin::is_member_controller_account(&participant_id, &account_id),
+            Error::<T, I>::MembershipError
+        );
+        Ok(())
     }
 
     fn ensure_post_exists(post_id: T::PostId) -> Result<Post<T, I>, DispatchError> {
@@ -556,7 +604,7 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
 
     fn ensure_blog_ownership(blog_owner: T::Origin) -> Result<(), DispatchError> {
         ensure!(
-            T::BlogOwnerEnsureOrigin::ensure_origin(blog_owner).is_ok(),
+            frame_system::ensure_root(blog_owner).is_ok(),
             Error::<T, I>::BlogOwnershipError
         );
 
@@ -565,7 +613,7 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
 
     fn ensure_reply_ownership(
         reply: &Reply<T, I>,
-        reply_owner: &T::ParticipantId,
+        reply_owner: &ParticipantId<T>,
     ) -> Result<(), DispatchError> {
         ensure!(
             reply.is_owner(reply_owner),
@@ -615,7 +663,7 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
 decl_event!(
     pub enum Event<T, I = DefaultInstance>
     where
-        ParticipantId = <T as Trait<I>>::ParticipantId,
+        ParticipantId = ParticipantId<T>,
         PostId = <T as Trait<I>>::PostId,
         ReplyId = <T as Trait<I>>::ReplyId,
         ReactionIndex = ReactionsNumber,

+ 242 - 18
runtime-modules/blog/src/mock.rs

@@ -1,7 +1,8 @@
 #![cfg(test)]
 
 use crate::*;
-use frame_support::traits::{OnFinalize, OnInitialize};
+use frame_support::traits::{LockIdentifier, OnFinalize, OnInitialize};
+use frame_support::weights::Weight;
 use frame_support::{impl_outer_event, impl_outer_origin, ord_parameter_types, parameter_types};
 use sp_core::H256;
 use sp_io::TestExternalities;
@@ -12,7 +13,10 @@ use sp_runtime::{
 };
 
 pub(crate) const FIRST_OWNER_ORIGIN: u64 = 0;
+pub(crate) const FIRST_OWNER_PARTICIPANT_ID: u64 = 0;
 pub(crate) const SECOND_OWNER_ORIGIN: u64 = 2;
+pub(crate) const SECOND_OWNER_PARTICIPANT_ID: u64 = 2;
+pub(crate) const BAD_MEMBER_ID: u64 = 100000;
 
 impl_outer_origin! {
     pub enum Origin for Runtime {}
@@ -21,6 +25,20 @@ impl_outer_origin! {
 #[derive(Clone, Default, PartialEq, Eq, Debug)]
 pub struct Runtime;
 
+parameter_types! {
+    pub const ExistentialDeposit: u32 = 0;
+}
+
+impl balances::Trait for Runtime {
+    type Balance = u64;
+    type DustRemoval = ();
+    type Event = TestEvent;
+    type ExistentialDeposit = ExistentialDeposit;
+    type AccountStore = System;
+    type WeightInfo = ();
+    type MaxLocks = ();
+}
+
 parameter_types! {
     pub const BlockHashCount: u64 = 250;
     pub const MaximumBlockWeight: u32 = 1024;
@@ -61,6 +79,136 @@ impl_outer_event! {
     pub enum TestEvent for Runtime {
         crate DefaultInstance <T>,
         frame_system<T>,
+        balances<T>,
+        membership<T>,
+    }
+}
+
+parameter_types! {
+    pub const DefaultMembershipPrice: u64 = 100;
+    pub const DefaultInitialInvitationBalance: u64 = 100;
+    pub const InviteMemberLockId: [u8; 8] = [9; 8];
+    pub const MinimumPeriod: u64 = 5;
+}
+
+impl membership::Trait for Runtime {
+    type Event = TestEvent;
+    type DefaultMembershipPrice = DefaultMembershipPrice;
+    type DefaultInitialInvitationBalance = DefaultInitialInvitationBalance;
+    type WorkingGroup = ();
+    type WeightInfo = Weights;
+    type InvitedMemberStakingHandler = staking_handler::StakingManager<Self, InviteMemberLockId>;
+}
+
+impl pallet_timestamp::Trait for Runtime {
+    type Moment = u64;
+    type OnTimestampSet = ();
+    type MinimumPeriod = MinimumPeriod;
+    type WeightInfo = ();
+}
+
+impl staking_handler::LockComparator<u64> for Runtime {
+    fn are_locks_conflicting(
+        _new_lock: &LockIdentifier,
+        _existing_locks: &[LockIdentifier],
+    ) -> bool {
+        false
+    }
+}
+
+impl common::working_group::WorkingGroupBudgetHandler<Runtime> for () {
+    fn get_budget() -> u64 {
+        unimplemented!();
+    }
+
+    fn set_budget(_: u64) {
+        unimplemented!()
+    }
+}
+
+impl common::working_group::WorkingGroupAuthenticator<Runtime> for () {
+    fn ensure_worker_origin(
+        _origin: <Runtime as frame_system::Trait>::Origin,
+        _worker_id: &<Runtime as common::Trait>::ActorId,
+    ) -> DispatchResult {
+        unimplemented!()
+    }
+
+    fn ensure_leader_origin(_origin: <Runtime as frame_system::Trait>::Origin) -> DispatchResult {
+        unimplemented!()
+    }
+
+    fn get_leader_member_id() -> Option<<Runtime as common::Trait>::MemberId> {
+        unimplemented!()
+    }
+
+    fn is_leader_account_id(_: &<Runtime as frame_system::Trait>::AccountId) -> bool {
+        unimplemented!();
+    }
+
+    fn is_worker_account_id(
+        _: &<Runtime as frame_system::Trait>::AccountId,
+        _worker_id: &<Runtime as common::Trait>::ActorId,
+    ) -> bool {
+        unimplemented!();
+    }
+}
+
+pub struct Weights;
+impl membership::WeightInfo for Weights {
+    fn buy_membership_without_referrer(_: u32, _: u32, _: u32, _: u32) -> Weight {
+        unimplemented!()
+    }
+    fn buy_membership_with_referrer(_: u32, _: u32, _: u32, _: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_profile(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_none() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_root() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_controller() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_both() -> Weight {
+        unimplemented!()
+    }
+    fn set_referral_cut() -> Weight {
+        unimplemented!()
+    }
+    fn transfer_invites() -> Weight {
+        unimplemented!()
+    }
+    fn invite_member(_: u32, _: u32, _: u32, _: u32) -> Weight {
+        unimplemented!()
+    }
+    fn set_membership_price() -> Weight {
+        unimplemented!()
+    }
+    fn update_profile_verification() -> Weight {
+        unimplemented!()
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_count() -> Weight {
+        unimplemented!()
+    }
+    fn add_staking_account_candidate() -> Weight {
+        unimplemented!()
+    }
+    fn confirm_staking_account() -> Weight {
+        unimplemented!()
+    }
+    fn remove_staking_account() -> Weight {
+        unimplemented!()
     }
 }
 
@@ -78,16 +226,71 @@ impl Trait for Runtime {
 
     type PostsMaxNumber = PostsMaxNumber;
     type RepliesMaxNumber = RepliesMaxNumber;
-
-    type BlogOwnerEnsureOrigin = frame_system::EnsureSignedBy<CorrectOwner, Self::AccountId>;
-
-    type ParticipantEnsureOrigin = frame_system::EnsureSigned<Self::ParticipantId>;
-    type ParticipantId = u64;
+    type ParticipantEnsureOrigin = MockEnsureParticipant;
+    type WeightInfo = ();
 
     type PostId = u64;
     type ReplyId = u64;
 }
 
+impl WeightInfo for () {
+    fn create_post(_: u32, _: u32) -> Weight {
+        unimplemented!()
+    }
+    fn lock_post() -> Weight {
+        unimplemented!()
+    }
+    fn unlock_post() -> Weight {
+        unimplemented!()
+    }
+    fn edit_post(_: u32, _: u32) -> Weight {
+        unimplemented!()
+    }
+    fn create_reply_to_post(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn create_reply_to_reply(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn edit_reply(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn react_to_post() -> Weight {
+        unimplemented!()
+    }
+    fn react_to_reply() -> Weight {
+        unimplemented!()
+    }
+}
+
+pub struct MockEnsureParticipant;
+impl
+    MemberOriginValidator<
+        Origin,
+        ParticipantId<Runtime>,
+        <Runtime as frame_system::Trait>::AccountId,
+    > for MockEnsureParticipant
+{
+    fn is_member_controller_account(
+        member_id: &ParticipantId<Runtime>,
+        _: &<Runtime as frame_system::Trait>::AccountId,
+    ) -> bool {
+        *member_id != BAD_MEMBER_ID
+    }
+
+    fn ensure_member_controller_account_origin(
+        _: Origin,
+        _: ParticipantId<Runtime>,
+    ) -> Result<<Runtime as frame_system::Trait>::AccountId, DispatchError> {
+        unimplemented!();
+    }
+}
+
+impl common::Trait for Runtime {
+    type MemberId = u64;
+    type ActorId = u64;
+}
+
 #[derive(Default)]
 pub struct ExtBuilder;
 
@@ -125,7 +328,7 @@ pub fn generate_text(len: usize) -> Vec<u8> {
 }
 
 type RawTestEvent = RawEvent<
-    <Runtime as Trait>::ParticipantId,
+    ParticipantId<Runtime>,
     <Runtime as Trait>::PostId,
     <Runtime as Trait>::ReplyId,
     ReactionsNumber,
@@ -162,22 +365,22 @@ fn generate_post() -> (Vec<u8>, Vec<u8>) {
     (generate_text(10), generate_text(100))
 }
 
-pub fn create_post(origin_id: u64) -> DispatchResult {
+pub fn create_post(origin: Origin) -> DispatchResult {
     let (title, body) = generate_post();
-    TestBlogModule::create_post(Origin::signed(origin_id), title, body)
+    TestBlogModule::create_post(origin, title, body)
 }
 
-pub fn lock_post(origin_id: u64, post_id: <Runtime as Trait>::PostId) -> DispatchResult {
-    TestBlogModule::lock_post(Origin::signed(origin_id), post_id)
+pub fn lock_post(origin: Origin, post_id: <Runtime as Trait>::PostId) -> DispatchResult {
+    TestBlogModule::lock_post(origin, post_id)
 }
 
-pub fn unlock_post(origin_id: u64, post_id: <Runtime as Trait>::PostId) -> DispatchResult {
-    TestBlogModule::unlock_post(Origin::signed(origin_id), post_id)
+pub fn unlock_post(origin: Origin, post_id: <Runtime as Trait>::PostId) -> DispatchResult {
+    TestBlogModule::unlock_post(origin, post_id)
 }
 
-pub fn edit_post(origin_id: u64, post_id: <Runtime as Trait>::PostId) -> DispatchResult {
+pub fn edit_post(origin: Origin, post_id: <Runtime as Trait>::PostId) -> DispatchResult {
     let (title, body) = generate_post();
-    TestBlogModule::edit_post(Origin::signed(origin_id), post_id, Some(title), Some(body))
+    TestBlogModule::edit_post(origin, post_id, Some(title), Some(body))
 }
 
 // Replies
@@ -205,29 +408,50 @@ pub fn get_reply(
 
 pub fn create_reply(
     origin_id: u64,
+    participant_id: u64,
     post_id: <Runtime as Trait>::PostId,
     reply_id: Option<<Runtime as Trait>::ReplyId>,
 ) -> DispatchResult {
     let reply = get_reply_text();
-    TestBlogModule::create_reply(Origin::signed(origin_id), post_id, reply_id, reply)
+    TestBlogModule::create_reply(
+        Origin::signed(origin_id),
+        participant_id,
+        post_id,
+        reply_id,
+        reply,
+    )
 }
 
 pub fn edit_reply(
     origin_id: u64,
+    participant_id: u64,
     post_id: <Runtime as Trait>::PostId,
     reply_id: <Runtime as Trait>::ReplyId,
 ) -> DispatchResult {
     let reply = get_reply_text();
-    TestBlogModule::edit_reply(Origin::signed(origin_id), post_id, reply_id, reply)
+    TestBlogModule::edit_reply(
+        Origin::signed(origin_id),
+        participant_id,
+        post_id,
+        reply_id,
+        reply,
+    )
 }
 
 // Reactions
 
 pub fn react(
     origin_id: u64,
+    participant_id: u64,
     index: ReactionsNumber,
     post_id: <Runtime as Trait>::PostId,
     reply_id: Option<<Runtime as Trait>::ReplyId>,
 ) -> DispatchResult {
-    TestBlogModule::react(Origin::signed(origin_id), index, post_id, reply_id)
+    TestBlogModule::react(
+        Origin::signed(origin_id),
+        participant_id,
+        index,
+        post_id,
+        reply_id,
+    )
 }

+ 252 - 61
runtime-modules/blog/src/tests.rs

@@ -65,7 +65,7 @@ fn post_creation_success() {
         let number_of_events_before_call = System::events().len();
 
         // Create post
-        assert_ok!(create_post(FIRST_OWNER_ORIGIN));
+        assert_ok!(create_post(Origin::root()));
 
         // Check related state after extrinsic performed
 
@@ -89,7 +89,7 @@ fn post_creation_blog_ownership_error() {
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let create_result = create_post(SECOND_OWNER_ORIGIN);
+        let create_result = create_post(Origin::signed(SECOND_OWNER_ORIGIN));
 
         // Check if related runtime storage left unchanged
         // assert!(post_storage_unchanged(FIRST_ID, FIRST_ID));
@@ -110,7 +110,7 @@ fn post_creation_limit_reached() {
             // Events number before tested call
             let number_of_events_before_call = System::events().len();
 
-            if let Err(create_post_err) = create_post(FIRST_OWNER_ORIGIN) {
+            if let Err(create_post_err) = create_post(Origin::root()) {
                 // Post counter & post max number contraint equality checked
                 assert_eq!(post_count(), PostsMaxNumber::get());
 
@@ -129,7 +129,7 @@ fn post_creation_limit_reached() {
 #[test]
 fn post_locking_success() {
     ExtBuilder::default().build().execute_with(|| {
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         let post = post_by_id(FIRST_ID).unwrap();
 
@@ -139,7 +139,7 @@ fn post_locking_success() {
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        assert_ok!(lock_post(FIRST_OWNER_ORIGIN, FIRST_ID));
+        assert_ok!(lock_post(Origin::root(), FIRST_ID));
 
         // Check related state after extrinsic performed
 
@@ -160,7 +160,7 @@ fn post_locking_post_not_found() {
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let lock_result = lock_post(FIRST_OWNER_ORIGIN, FIRST_ID);
+        let lock_result = lock_post(Origin::root(), FIRST_ID);
 
         // Failure checked
         assert_failure(
@@ -174,12 +174,12 @@ fn post_locking_post_not_found() {
 #[test]
 fn post_locking_ownership_error() {
     ExtBuilder::default().build().execute_with(|| {
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let lock_result = lock_post(SECOND_OWNER_ORIGIN, FIRST_ID);
+        let lock_result = lock_post(Origin::signed(SECOND_OWNER_ORIGIN), FIRST_ID);
 
         // Check related state after extrinsic performed
 
@@ -200,10 +200,10 @@ fn post_locking_ownership_error() {
 #[test]
 fn post_unlocking_success() {
     ExtBuilder::default().build().execute_with(|| {
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Lock post firstly
-        lock_post(FIRST_OWNER_ORIGIN, FIRST_ID).unwrap();
+        lock_post(Origin::root(), FIRST_ID).unwrap();
 
         // Check related state before extrinsic performed
         let post = post_by_id(FIRST_ID).unwrap();
@@ -213,7 +213,7 @@ fn post_unlocking_success() {
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        assert_ok!(unlock_post(FIRST_OWNER_ORIGIN, FIRST_ID));
+        assert_ok!(unlock_post(Origin::root(), FIRST_ID));
 
         // Check related state after extrinsic performed
         let post = post_by_id(FIRST_ID).unwrap();
@@ -230,15 +230,15 @@ fn post_unlocking_success() {
 #[test]
 fn post_unlocking_owner_not_found() {
     ExtBuilder::default().build().execute_with(|| {
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Lock post firstly
-        lock_post(FIRST_OWNER_ORIGIN, FIRST_ID).unwrap();
+        lock_post(Origin::root(), FIRST_ID).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let unlock_result = unlock_post(SECOND_OWNER_ORIGIN, FIRST_ID);
+        let unlock_result = unlock_post(Origin::signed(SECOND_OWNER_ORIGIN), FIRST_ID);
 
         // Check related state after extrinsic performed
         let post = post_by_id(FIRST_ID).unwrap();
@@ -262,7 +262,7 @@ fn post_unlocking_post_not_found() {
         let number_of_events_before_call = System::events().len();
 
         // Try to unlock not existing post
-        let unlock_result = unlock_post(FIRST_OWNER_ORIGIN, FIRST_ID);
+        let unlock_result = unlock_post(Origin::root(), FIRST_ID);
 
         // Failure checked
         assert_failure(
@@ -276,15 +276,15 @@ fn post_unlocking_post_not_found() {
 #[test]
 fn post_unlocking_ownership_error() {
     ExtBuilder::default().build().execute_with(|| {
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Lock post firstly
-        lock_post(FIRST_OWNER_ORIGIN, FIRST_ID).unwrap();
+        lock_post(Origin::root(), FIRST_ID).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let unlock_result = unlock_post(SECOND_OWNER_ORIGIN, FIRST_ID);
+        let unlock_result = unlock_post(Origin::signed(SECOND_OWNER_ORIGIN), FIRST_ID);
 
         // Check related state after extrinsic performed
         let post = post_by_id(FIRST_ID).unwrap();
@@ -305,12 +305,12 @@ fn post_unlocking_ownership_error() {
 fn post_editing_success() {
     ExtBuilder::default().build().execute_with(|| {
         // Create blog for future posts
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        assert_ok!(edit_post(FIRST_OWNER_ORIGIN, FIRST_ID));
+        assert_ok!(edit_post(Origin::root(), FIRST_ID));
 
         // Post after editing checked
         let post_after_editing = post_by_id(FIRST_ID);
@@ -327,12 +327,12 @@ fn post_editing_success() {
 #[test]
 fn post_editing_ownership_error() {
     ExtBuilder::default().build().execute_with(|| {
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let edit_result = edit_post(SECOND_OWNER_ORIGIN, FIRST_ID);
+        let edit_result = edit_post(Origin::signed(SECOND_OWNER_ORIGIN), FIRST_ID);
 
         // Remain unedited
         let post = post_by_id(FIRST_ID);
@@ -356,7 +356,7 @@ fn post_editing_post_not_found() {
         let number_of_events_before_call = System::events().len();
 
         // Try to unlock not existing post
-        let edit_result = edit_post(FIRST_OWNER_ORIGIN, FIRST_ID);
+        let edit_result = edit_post(Origin::root(), FIRST_ID);
 
         // Failure checked
         assert_failure(
@@ -370,15 +370,15 @@ fn post_editing_post_not_found() {
 #[test]
 fn post_editing_post_locked_error() {
     ExtBuilder::default().build().execute_with(|| {
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Lock post to make all related data immutable
-        lock_post(FIRST_OWNER_ORIGIN, FIRST_ID).unwrap();
+        lock_post(Origin::root(), FIRST_ID).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let edit_result = edit_post(FIRST_OWNER_ORIGIN, FIRST_ID);
+        let edit_result = edit_post(Origin::root(), FIRST_ID);
 
         // Remain unedited
         let post = post_by_id(FIRST_ID);
@@ -400,14 +400,19 @@ fn post_editing_post_locked_error() {
 fn reply_creation_success() {
     ExtBuilder::default().build().execute_with(|| {
         // Create post for future replies
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         let reply_owner_id = ensure_signed(Origin::signed(SECOND_OWNER_ORIGIN)).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        assert_ok!(create_reply(SECOND_OWNER_ORIGIN, FIRST_ID, None));
+        assert_ok!(create_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            None
+        ));
 
         // Check reply related state after extrinsic performed
 
@@ -435,16 +440,26 @@ fn reply_creation_success() {
 fn direct_reply_creation_success() {
     ExtBuilder::default().build().execute_with(|| {
         // Create post for future replies
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
         let direct_reply_owner_id = ensure_signed(Origin::signed(SECOND_OWNER_ORIGIN)).unwrap();
 
-        assert_ok!(create_reply(FIRST_OWNER_ORIGIN, FIRST_ID, None));
+        assert_ok!(create_reply(
+            FIRST_OWNER_ORIGIN,
+            FIRST_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            None
+        ));
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
         // Create reply for direct replying
-        assert_ok!(create_reply(SECOND_OWNER_ORIGIN, FIRST_ID, Some(FIRST_ID)));
+        assert_ok!(create_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            Some(FIRST_ID)
+        ));
 
         // Check reply related state after extrinsic performed
 
@@ -470,15 +485,20 @@ fn direct_reply_creation_success() {
 #[test]
 fn reply_creation_post_locked_error() {
     ExtBuilder::default().build().execute_with(|| {
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Lock post to make all related data immutable
-        lock_post(FIRST_OWNER_ORIGIN, FIRST_ID).unwrap();
+        lock_post(Origin::root(), FIRST_ID).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let reply_creation_result = create_reply(SECOND_OWNER_ORIGIN, FIRST_ID, None);
+        let reply_creation_result = create_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            None,
+        );
 
         // Check if related replies storage left unchanged
         assert!(replies_storage_unchanged(FIRST_ID, FIRST_ID));
@@ -498,7 +518,12 @@ fn reply_creation_post_not_found() {
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let reply_creation_result = create_reply(SECOND_OWNER_ORIGIN, FIRST_ID, None);
+        let reply_creation_result = create_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            None,
+        );
 
         // Check if related replies storage left unchanged
         assert!(replies_storage_unchanged(FIRST_ID, FIRST_ID));
@@ -516,11 +541,16 @@ fn reply_creation_post_not_found() {
 fn reply_creation_limit_reached() {
     ExtBuilder::default().build().execute_with(|| {
         // Create post for future replies
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
         loop {
             // Events number before tested call
             let number_of_events_before_call = System::events().len();
-            if let Err(create_reply_err) = create_reply(FIRST_OWNER_ORIGIN, FIRST_ID, None) {
+            if let Err(create_reply_err) = create_reply(
+                FIRST_OWNER_ORIGIN,
+                FIRST_OWNER_PARTICIPANT_ID,
+                FIRST_ID,
+                None,
+            ) {
                 let post = post_by_id(FIRST_ID).unwrap();
 
                 // Root post replies counter & reply root max number contraint equality checked
@@ -542,13 +572,18 @@ fn reply_creation_limit_reached() {
 fn direct_reply_creation_reply_not_found() {
     ExtBuilder::default().build().execute_with(|| {
         // Create post for future replies
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
         // Attempt to create direct reply for nonexistent reply
-        let reply_creation_result = create_reply(SECOND_OWNER_ORIGIN, FIRST_ID, Some(FIRST_ID));
+        let reply_creation_result = create_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            Some(FIRST_ID),
+        );
 
         // Check if related runtime storage left unchanged
         assert!(replies_storage_unchanged(FIRST_ID, SECOND_ID));
@@ -566,16 +601,28 @@ fn direct_reply_creation_reply_not_found() {
 fn reply_editing_success() {
     ExtBuilder::default().build().execute_with(|| {
         // Create post for future replies
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         let reply_owner_id = ensure_signed(Origin::signed(SECOND_OWNER_ORIGIN)).unwrap();
 
-        create_reply(SECOND_OWNER_ORIGIN, FIRST_ID, None).unwrap();
+        create_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            None,
+        )
+        .unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        edit_reply(SECOND_OWNER_ORIGIN, FIRST_ID, FIRST_ID).unwrap();
+        edit_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            FIRST_ID,
+        )
+        .unwrap();
 
         // Reply after editing checked
         let reply = reply_by_id(FIRST_ID, FIRST_ID);
@@ -592,19 +639,30 @@ fn reply_editing_success() {
 fn reply_editing_post_locked_error() {
     ExtBuilder::default().build().execute_with(|| {
         // Create post for future replies
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         let reply_owner_id = ensure_signed(Origin::signed(SECOND_OWNER_ORIGIN)).unwrap();
 
-        create_reply(SECOND_OWNER_ORIGIN, FIRST_ID, None).unwrap();
+        create_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            None,
+        )
+        .unwrap();
 
         // Lock blog to make all related data immutable
-        lock_post(FIRST_OWNER_ORIGIN, FIRST_ID).unwrap();
+        lock_post(Origin::root(), FIRST_ID).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let reply_editing_result = edit_reply(SECOND_OWNER_ORIGIN, FIRST_ID, FIRST_ID);
+        let reply_editing_result = edit_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            FIRST_ID,
+        );
 
         // Reply after editing checked
         let reply = reply_by_id(FIRST_ID, FIRST_ID);
@@ -625,12 +683,17 @@ fn reply_editing_post_locked_error() {
 fn reply_editing_not_found() {
     ExtBuilder::default().build().execute_with(|| {
         // Create post for future replies
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let reply_editing_result = edit_reply(SECOND_OWNER_ORIGIN, FIRST_ID, FIRST_ID);
+        let reply_editing_result = edit_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            FIRST_ID,
+        );
 
         // Failure checked
         assert_failure(
@@ -645,16 +708,27 @@ fn reply_editing_not_found() {
 fn reply_editing_ownership_error() {
     ExtBuilder::default().build().execute_with(|| {
         // Create post for future replies
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         let reply_owner_id = ensure_signed(Origin::signed(SECOND_OWNER_ORIGIN)).unwrap();
 
-        create_reply(SECOND_OWNER_ORIGIN, FIRST_ID, None).unwrap();
+        create_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            None,
+        )
+        .unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
-        let reply_editing_result = edit_reply(FIRST_OWNER_ORIGIN, FIRST_ID, FIRST_ID);
+        let reply_editing_result = edit_reply(
+            FIRST_OWNER_ORIGIN,
+            FIRST_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            FIRST_ID,
+        );
 
         // Reply after editing checked
         let reply = reply_by_id(FIRST_ID, FIRST_ID);
@@ -671,13 +745,69 @@ fn reply_editing_ownership_error() {
     })
 }
 
+#[test]
+fn reply_participant_error() {
+    ExtBuilder::default().build().execute_with(|| {
+        // Create post for future replies
+        create_post(Origin::root()).unwrap();
+
+        let number_of_events_before_call = System::events().len();
+
+        let reply_result = create_reply(SECOND_OWNER_ORIGIN, BAD_MEMBER_ID, FIRST_ID, None);
+
+        // Failure checked
+        assert_failure(
+            reply_result,
+            Error::MembershipError,
+            number_of_events_before_call,
+        );
+    })
+}
+
+#[test]
+fn reply_editing_participant_error() {
+    ExtBuilder::default().build().execute_with(|| {
+        // Create post for future replies
+        create_post(Origin::root()).unwrap();
+
+        let reply_owner_id = ensure_signed(Origin::signed(SECOND_OWNER_ORIGIN)).unwrap();
+
+        create_reply(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            None,
+        )
+        .unwrap();
+
+        // Events number before tested call
+        let number_of_events_before_call = System::events().len();
+
+        let reply_editing_result =
+            edit_reply(FIRST_OWNER_ORIGIN, BAD_MEMBER_ID, FIRST_ID, FIRST_ID);
+
+        // Reply after editing checked
+        let reply = reply_by_id(FIRST_ID, FIRST_ID);
+
+        // Compare with default unedited reply
+        ensure_replies_equality(reply, reply_owner_id, ParentId::Post(FIRST_ID));
+
+        // Failure checked
+        assert_failure(
+            reply_editing_result,
+            Error::MembershipError,
+            number_of_events_before_call,
+        );
+    })
+}
+
 #[test]
 fn reaction_success() {
     const REACTION_INDEX: ReactionsNumber = 4;
 
     ExtBuilder::default().build().execute_with(|| {
         // Create post for future replies
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         let reaction_owner_id = ensure_signed(Origin::signed(SECOND_OWNER_ORIGIN)).unwrap();
 
@@ -685,7 +815,13 @@ fn reaction_success() {
         let number_of_events_before_call = System::events().len();
 
         // React to a post
-        assert_ok!(react(SECOND_OWNER_ORIGIN, REACTION_INDEX, FIRST_ID, None,));
+        assert_ok!(react(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            REACTION_INDEX,
+            FIRST_ID,
+            None,
+        ));
 
         // Event checked
         let post_reactions_updated_event = get_test_event(RawEvent::PostReactionsUpdated(
@@ -699,7 +835,13 @@ fn reaction_success() {
             number_of_events_before_call + 1,
         );
 
-        create_reply(FIRST_OWNER_ORIGIN, FIRST_ID, None).unwrap();
+        create_reply(
+            FIRST_OWNER_ORIGIN,
+            FIRST_OWNER_PARTICIPANT_ID,
+            FIRST_ID,
+            None,
+        )
+        .unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
@@ -708,6 +850,7 @@ fn reaction_success() {
         for _ in 0..2 {
             assert_ok!(react(
                 SECOND_OWNER_ORIGIN,
+                SECOND_OWNER_PARTICIPANT_ID,
                 REACTION_INDEX,
                 FIRST_ID,
                 Some(FIRST_ID),
@@ -733,14 +876,20 @@ fn reaction_invalid_index() {
     const REACTIONS_MAX_NUMBER: ReactionsNumber = 5;
 
     ExtBuilder::default().build().execute_with(|| {
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
         // React to a post
         // Should fail, as last index in configured reactions array is less by one than array length
-        let react_result = react(SECOND_OWNER_ORIGIN, REACTIONS_MAX_NUMBER, FIRST_ID, None);
+        let react_result = react(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            REACTIONS_MAX_NUMBER,
+            FIRST_ID,
+            None,
+        );
 
         // Failure checked
         assert_failure(
@@ -751,6 +900,35 @@ fn reaction_invalid_index() {
     })
 }
 
+#[test]
+fn reaction_participant_error() {
+    const REACTIONS_MAX_NUMBER: ReactionsNumber = 5;
+
+    ExtBuilder::default().build().execute_with(|| {
+        create_post(Origin::root()).unwrap();
+
+        // Events number before tested call
+        let number_of_events_before_call = System::events().len();
+
+        // React to a post
+        // Should fail, as last index in configured reactions array is less by one than array length
+        let react_result = react(
+            SECOND_OWNER_ORIGIN,
+            BAD_MEMBER_ID,
+            REACTIONS_MAX_NUMBER,
+            FIRST_ID,
+            None,
+        );
+
+        // Failure checked
+        assert_failure(
+            react_result,
+            Error::MembershipError,
+            number_of_events_before_call,
+        );
+    })
+}
+
 #[test]
 fn reaction_post_not_found() {
     const REACTION_INDEX: ReactionsNumber = 4;
@@ -760,7 +938,13 @@ fn reaction_post_not_found() {
         let number_of_events_before_call = System::events().len();
 
         // React to a post
-        let react_result = react(SECOND_OWNER_ORIGIN, REACTION_INDEX, FIRST_ID, None);
+        let react_result = react(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            REACTION_INDEX,
+            FIRST_ID,
+            None,
+        );
 
         // Failure checked
         assert_failure(
@@ -776,7 +960,7 @@ fn reaction_reply_not_found() {
     const REACTION_INDEX: ReactionsNumber = 4;
 
     ExtBuilder::default().build().execute_with(|| {
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
@@ -784,6 +968,7 @@ fn reaction_reply_not_found() {
         // React to a reply
         let react_result = react(
             SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
             REACTION_INDEX,
             FIRST_ID,
             Some(FIRST_ID),
@@ -803,16 +988,22 @@ fn reaction_post_locked_error() {
     const REACTION_INDEX: ReactionsNumber = 4;
 
     ExtBuilder::default().build().execute_with(|| {
-        create_post(FIRST_OWNER_ORIGIN).unwrap();
+        create_post(Origin::root()).unwrap();
 
         // Lock block to forbid mutations
-        lock_post(FIRST_OWNER_ORIGIN, FIRST_ID).unwrap();
+        lock_post(Origin::root(), FIRST_ID).unwrap();
 
         // Events number before tested call
         let number_of_events_before_call = System::events().len();
 
         // React to a post
-        let react_result = react(SECOND_OWNER_ORIGIN, REACTION_INDEX, FIRST_ID, None);
+        let react_result = react(
+            SECOND_OWNER_ORIGIN,
+            SECOND_OWNER_PARTICIPANT_ID,
+            REACTION_INDEX,
+            FIRST_ID,
+            None,
+        );
 
         // Failure checked
         assert_failure(

+ 19 - 0
runtime/src/lib.rs

@@ -874,6 +874,24 @@ impl pallet_constitution::Trait for Runtime {
     type WeightInfo = weights::pallet_constitution::WeightInfo;
 }
 
+parameter_types! {
+    pub const PostsMaxNumber: u64 = 20;
+    pub const RepliesMaxNumber: u64 = 100;
+}
+
+pub type BlogInstance = blog::Instance1;
+impl blog::Trait<BlogInstance> for Runtime {
+    type Event = Event;
+
+    type PostsMaxNumber = PostsMaxNumber;
+    type RepliesMaxNumber = RepliesMaxNumber;
+    type ParticipantEnsureOrigin = Members;
+    type WeightInfo = weights::blog::WeightInfo;
+
+    type PostId = u64;
+    type ReplyId = u64;
+}
+
 /// Forum identifier for category
 pub type CategoryId = u64;
 
@@ -926,6 +944,7 @@ construct_runtime!(
         Forum: forum::{Module, Call, Storage, Event<T>, Config<T>},
         ContentDirectory: content_directory::{Module, Call, Storage, Event<T>, Config<T>},
         Constitution: pallet_constitution::{Module, Call, Storage, Event},
+        Blog: blog::<Instance1>::{Module, Call, Storage, Event<T>},
         // --- Storage
         DataObjectTypeRegistry: data_object_type_registry::{Module, Call, Storage, Event<T>, Config<T>},
         DataDirectory: data_directory::{Module, Call, Storage, Event<T>},

+ 2 - 0
runtime/src/runtime_api.rs

@@ -294,6 +294,7 @@ impl_runtime_apis! {
             use crate::ImOnline;
             use crate::Council;
             use crate::Referendum;
+            use crate::Blog;
 
 
             // Trying to add benchmarks directly to the Session Pallet caused cyclic dependency issues.
@@ -383,6 +384,7 @@ impl_runtime_apis! {
             add_benchmark!(params, batches, working_group, ContentDirectoryWorkingGroup);
             add_benchmark!(params, batches, referendum, Referendum);
             add_benchmark!(params, batches, council, Council);
+            add_benchmark!(params, batches, blog, Blog);
 
             if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
             Ok(batches)

+ 60 - 0
runtime/src/weights/blog.rs

@@ -0,0 +1,60 @@
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0
+
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::weights::{Weight, constants::RocksDbWeight as DbWeight};
+
+pub struct WeightInfo;
+impl blog::WeightInfo for WeightInfo {
+	fn create_post(t: u32, b: u32, ) -> Weight {
+		(180_427_000 as Weight)
+			.saturating_add((34_000 as Weight).saturating_mul(t as Weight))
+			.saturating_add((37_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(DbWeight::get().reads(1 as Weight))
+			.saturating_add(DbWeight::get().writes(2 as Weight))
+	}
+	fn lock_post() -> Weight {
+		(174_515_000 as Weight)
+			.saturating_add(DbWeight::get().reads(1 as Weight))
+			.saturating_add(DbWeight::get().writes(1 as Weight))
+	}
+	fn unlock_post() -> Weight {
+		(174_369_000 as Weight)
+			.saturating_add(DbWeight::get().reads(1 as Weight))
+			.saturating_add(DbWeight::get().writes(1 as Weight))
+	}
+	fn edit_post(t: u32, b: u32, ) -> Weight {
+		(333_244_000 as Weight)
+			.saturating_add((38_000 as Weight).saturating_mul(t as Weight))
+			.saturating_add((31_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(DbWeight::get().reads(1 as Weight))
+			.saturating_add(DbWeight::get().writes(1 as Weight))
+	}
+	fn create_reply_to_post(t: u32, ) -> Weight {
+		(286_102_000 as Weight)
+			.saturating_add((43_000 as Weight).saturating_mul(t as Weight))
+			.saturating_add(DbWeight::get().reads(2 as Weight))
+			.saturating_add(DbWeight::get().writes(2 as Weight))
+	}
+	fn create_reply_to_reply(t: u32, ) -> Weight {
+		(364_116_000 as Weight)
+			.saturating_add((39_000 as Weight).saturating_mul(t as Weight))
+			.saturating_add(DbWeight::get().reads(3 as Weight))
+			.saturating_add(DbWeight::get().writes(2 as Weight))
+	}
+	fn edit_reply(t: u32, ) -> Weight {
+		(286_073_000 as Weight)
+			.saturating_add((42_000 as Weight).saturating_mul(t as Weight))
+			.saturating_add(DbWeight::get().reads(3 as Weight))
+			.saturating_add(DbWeight::get().writes(1 as Weight))
+	}
+	fn react_to_post() -> Weight {
+		(244_186_000 as Weight)
+			.saturating_add(DbWeight::get().reads(2 as Weight))
+	}
+	fn react_to_reply() -> Weight {
+		(311_256_000 as Weight)
+			.saturating_add(DbWeight::get().reads(3 as Weight))
+	}
+}

+ 1 - 0
runtime/src/weights/mod.rs

@@ -24,6 +24,7 @@ pub mod pallet_timestamp;
 pub mod pallet_utility;
 
 // Joystream pallets
+pub mod blog;
 pub mod council;
 pub mod forum;
 pub mod membership;

+ 2 - 1
scripts/generate-weights.sh

@@ -53,4 +53,5 @@ benchmark working_group
 benchmark council
 benchmark referendum
 benchmark forum
-benchmark membership
+benchmark membership
+benchmark blog