Browse Source

Merge pull request #2531 from iorveth/issue_2396

Olympia forum: create_thread extrinsic should take poll description, not description_hash, as arg
shamil-gadelshin 3 years ago
parent
commit
95d4e69e65

+ 53 - 68
runtime-modules/forum/src/benchmarking.rs

@@ -53,7 +53,7 @@ const MAX_POSTS: u32 = 500;
 const MAX_THREADS: u32 = 500;
 
 fn get_byte(num: u32, byte_number: u8) -> u8 {
-    ((num & (0xff << (8 * byte_number))) >> 8 * byte_number) as u8
+    ((num & (0xff << (8 * byte_number))) >> (8 * byte_number)) as u8
 }
 
 fn assert_last_event<T: Trait>(generic_event: <T as Trait>::Event) {
@@ -90,12 +90,12 @@ where
     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(),
+        member_id,
     )
     .unwrap();
     Membership::<T>::confirm_staking_account(
         RawOrigin::Signed(account_id.clone()).into(),
-        member_id.clone(),
+        member_id,
         account_id.clone(),
     )
     .unwrap();
@@ -178,12 +178,8 @@ where
 
     let mut successful_application_ids = BTreeSet::<ApplicationId>::new();
     successful_application_ids.insert(application_id);
-    ForumGroup::<T>::fill_opening(
-        leader_origin.clone().into(),
-        opening_id,
-        successful_application_ids,
-    )
-    .unwrap();
+    ForumGroup::<T>::fill_opening(leader_origin.into(), opening_id, successful_application_ids)
+        .unwrap();
 
     let actor_id =
         <T as common::membership::MembershipTypes>::ActorId::from(id.try_into().unwrap());
@@ -294,7 +290,7 @@ fn create_new_thread<T: Trait>(
     category_id: T::CategoryId,
     title: Vec<u8>,
     text: Vec<u8>,
-    poll: Option<Poll<T::Moment, T::Hash>>,
+    poll: Option<PollInput<T::Moment>>,
 ) -> T::ThreadId {
     Module::<T>::create_thread(
         RawOrigin::Signed(account_id).into(),
@@ -327,30 +323,26 @@ fn add_thread_post<T: Trait>(
     Module::<T>::next_post_id() - T::PostId::one()
 }
 
-pub fn good_poll_alternative_text() -> Vec<u8> {
+fn good_poll_alternative_text() -> Vec<u8> {
     b"poll alternative".to_vec()
 }
 
-pub fn good_poll_description() -> Vec<u8> {
+fn good_poll_description() -> Vec<u8> {
     b"poll description".to_vec()
 }
 
-pub fn generate_poll<T: Trait>(
+/// Generates poll input
+pub fn generate_poll_input<T: Trait>(
     expiration_diff: T::Moment,
     alternatives_number: u32,
-) -> Poll<T::Moment, T::Hash> {
-    Poll {
-        description_hash: T::calculate_hash(good_poll_description().as_slice()),
+) -> PollInput<T::Moment> {
+    PollInput {
+        description: good_poll_description(),
         end_time: pallet_timestamp::Module::<T>::now() + expiration_diff,
         poll_alternatives: {
             let mut alternatives = vec![];
             for _ in 0..alternatives_number {
-                alternatives.push(PollAlternative {
-                    alternative_text_hash: T::calculate_hash(
-                        good_poll_alternative_text().as_slice(),
-                    ),
-                    vote_count: 0,
-                });
+                alternatives.push(good_poll_alternative_text());
             }
             alternatives
         },
@@ -382,19 +374,16 @@ pub fn generate_categories_tree<T: Trait>(
             text.clone(),
         );
 
-        match moderator_id {
-            Some(moderator_id) => {
-                // Set up category membership of moderator.
-                Module::<T>::update_category_membership_of_moderator(
-                    RawOrigin::Signed(caller_id.clone()).into(),
-                    moderator_id,
-                    category_id,
-                    true,
-                )
-                .unwrap();
-            }
-            _ => (),
-        };
+        if let Some(moderator_id) = moderator_id {
+            // Set up category membership of moderator.
+            Module::<T>::update_category_membership_of_moderator(
+                RawOrigin::Signed(caller_id.clone()).into(),
+                moderator_id,
+                category_id,
+                true,
+            )
+            .unwrap();
+        }
     }
 
     assert_eq!(
@@ -434,11 +423,7 @@ benchmarks! {
         // Generate categories tree
         let (_, parent_category_id) = generate_categories_tree::<T>(caller_id.clone(), i, None);
 
-        let parent_category = if let Some(parent_category_id) = parent_category_id {
-            Some(Module::<T>::category_by_id(parent_category_id))
-        } else {
-            None
-        };
+        let parent_category = parent_category_id.map(Module::<T>::category_by_id);
 
         let category_counter = <Module<T>>::category_counter();
 
@@ -941,18 +926,18 @@ benchmarks! {
 
         let expiration_diff = 1010u32.into();
 
-        let poll = if z == 1 {
+        let poll_input = if z == 1 {
             None
         } else {
             // min number of poll alternatives is set to 2
-            Some(generate_poll::<T>(expiration_diff, z))
+            Some(generate_poll_input::<T>(expiration_diff, z))
         };
 
         let next_thread_id = Module::<T>::next_thread_id();
         let next_post_id = Module::<T>::next_post_id();
         let initial_balance = Balances::<T>::usable_balance(&caller_id);
 
-    }: _ (RawOrigin::Signed(caller_id.clone()), forum_user_id.saturated_into(), category_id, title.clone(), text.clone(), poll.clone())
+    }: _ (RawOrigin::Signed(caller_id.clone()), forum_user_id.saturated_into(), category_id, title.clone(), text.clone(), poll_input.clone())
     verify {
 
         assert_eq!(
@@ -978,7 +963,7 @@ benchmarks! {
             category_id,
             title_hash: T::calculate_hash(&title),
             author_id: forum_user_id.saturated_into(),
-            poll: poll.clone(),
+            poll: poll_input.clone().map(<Module<T>>::from_poll_input),
             cleanup_pay_off: T::ThreadDeposit::get(),
             number_of_posts: 1,
         };
@@ -1002,7 +987,7 @@ benchmarks! {
                 forum_user_id.saturated_into(),
                 title,
                 text,
-                poll,
+                poll_input,
             ).into()
         );
     }
@@ -1058,13 +1043,13 @@ benchmarks! {
         // Create thread
         let expiration_diff = 10u32.into();
         let poll = Some(
-            generate_poll::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
+            generate_poll_input::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
         );
         let text = vec![1u8].repeat(MAX_BYTES as usize);
 
         let thread_id = create_new_thread::<T>(
             caller_id.clone(), forum_user_id.saturated_into(), category_id,
-            text.clone(), text.clone(), poll
+            text.clone(), text, poll
         );
 
         // Add poll voting.
@@ -1153,7 +1138,7 @@ benchmarks! {
         };
 
         // Create thread
-        let thread_id = create_new_thread::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, text.clone(), text.clone(), None);
+        let thread_id = create_new_thread::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, text.clone(), text, None);
         let thread = Module::<T>::thread_by_id(category_id, thread_id);
 
         let mut category = Module::<T>::category_by_id(category_id);
@@ -1215,7 +1200,7 @@ benchmarks! {
         };
 
         // Create thread
-        let thread_id = create_new_thread::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, text.clone(), text.clone(), None);
+        let thread_id = create_new_thread::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, text.clone(), text, None);
         let thread = Module::<T>::thread_by_id(category_id, thread_id);
 
         let moderator_id = ModeratorId::<T>::from(forum_user_id.try_into().unwrap());
@@ -1270,12 +1255,12 @@ benchmarks! {
 
         // Create thread
         let expiration_diff = 10u32.into();
-        let poll = Some(generate_poll::<T>(expiration_diff, j));
+        let poll_input = Some(generate_poll_input::<T>(expiration_diff, j));
         let text = vec![1u8].repeat(MAX_BYTES as usize);
 
         let thread_id = create_new_thread::<T>(
             caller_id.clone(), forum_user_id.saturated_into(), category_id,
-            text.clone(), text.clone(), poll
+            text.clone(), text, poll_input
         );
 
         let mut thread = Module::<T>::thread_by_id(category_id, thread_id);
@@ -1328,13 +1313,13 @@ benchmarks! {
         // Create thread
         let expiration_diff = 10u32.into();
         let poll = Some(
-            generate_poll::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
+            generate_poll_input::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
         );
 
         let text = vec![1u8].repeat(MAX_BYTES as usize);
         let thread_id = create_new_thread::<T>(
             caller_id.clone(), (lead_id as u64).saturated_into(), category_id,
-            text.clone(), text.clone(), poll
+            text.clone(), text, poll
         );
 
         let mut category = Module::<T>::category_by_id(category_id);
@@ -1384,13 +1369,13 @@ benchmarks! {
         // Create thread
         let expiration_diff = 10u32.into();
         let poll = Some(
-            generate_poll::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
+            generate_poll_input::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
         );
 
         let text = vec![1u8].repeat(MAX_BYTES as usize);
         let thread_id = create_new_thread::<T>(
             caller_id.clone(), (lead_id as u64).saturated_into(), category_id,
-            text.clone(), text.clone(), poll
+            text.clone(), text, poll
         );
 
         let moderator_id = ModeratorId::<T>::from(lead_id.try_into().unwrap());
@@ -1467,7 +1452,7 @@ benchmarks! {
         let new_post = Post {
             text_hash: T::calculate_hash(&text),
             author_id: forum_user_id.saturated_into(),
-            thread_id: thread_id,
+            thread_id,
             last_edited: System::<T>::block_number(),
             cleanup_pay_off: T::PostDeposit::get(),
         };
@@ -1502,7 +1487,7 @@ benchmarks! {
         // Create thread
         let expiration_diff = 10u32.into();
         let poll = Some(
-            generate_poll::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
+            generate_poll_input::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
         );
         let text = vec![1u8].repeat(MAX_BYTES as usize);
 
@@ -1511,7 +1496,7 @@ benchmarks! {
             text.clone(), text.clone(), poll
         );
 
-        let post_id = add_thread_post::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, thread_id, text.clone());
+        let post_id = add_thread_post::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, thread_id, text);
 
         let react = T::PostReactionId::one();
 
@@ -1543,7 +1528,7 @@ benchmarks! {
         // Create thread
         let expiration_diff = 10u32.into();
         let poll = Some(
-            generate_poll::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
+            generate_poll_input::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
         );
         let text = vec![1u8].repeat(MAX_BYTES as usize);
 
@@ -1552,7 +1537,7 @@ benchmarks! {
             text.clone(), text.clone(), poll
         );
 
-        let post_id = add_thread_post::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, thread_id, text.clone());
+        let post_id = add_thread_post::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, thread_id, text);
 
         let mut post = Module::<T>::post_by_id(thread_id, post_id);
 
@@ -1597,7 +1582,7 @@ benchmarks! {
         // Create thread
         let expiration_diff = 10u32.into();
         let poll = Some(
-            generate_poll::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
+            generate_poll_input::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
         );
         let text = vec![1u8].repeat(MAX_BYTES as usize);
 
@@ -1605,7 +1590,7 @@ benchmarks! {
             caller_id.clone(), forum_user_id.saturated_into(), category_id,
             text.clone(), text.clone(), poll
         );
-        let post_id = add_thread_post::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, thread_id, text.clone());
+        let post_id = add_thread_post::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, thread_id, text);
 
         let mut thread = Module::<T>::thread_by_id(category_id, thread_id);
 
@@ -1644,7 +1629,7 @@ benchmarks! {
         // Create thread
         let expiration_diff = 10u32.into();
         let poll = Some(
-            generate_poll::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
+            generate_poll_input::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
         );
         let text = vec![1u8].repeat(MAX_BYTES as usize);
 
@@ -1652,7 +1637,7 @@ benchmarks! {
             caller_id.clone(), forum_user_id.saturated_into(), category_id,
             text.clone(), text.clone(), poll
         );
-        let post_id = add_thread_post::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, thread_id, text.clone());
+        let post_id = add_thread_post::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, thread_id, text);
 
         let mut thread = Module::<T>::thread_by_id(category_id, thread_id);
 
@@ -1700,7 +1685,7 @@ benchmarks! {
         // Create thread
         let expiration_diff = 10u32.into();
         let poll = Some(
-            generate_poll::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
+            generate_poll_input::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
         );
         let text = vec![1u8].repeat(MAX_BYTES as usize);
 
@@ -1726,7 +1711,7 @@ benchmarks! {
             );
         }
 
-        let post_id = add_thread_post::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, thread_id, text.clone());
+        let post_id = add_thread_post::<T>(caller_id.clone(), forum_user_id.saturated_into(), category_id, thread_id, text);
 
         let mut thread = Module::<T>::thread_by_id(category_id, thread_id);
 
@@ -1777,7 +1762,7 @@ benchmarks! {
         // Create threads
         let expiration_diff = 1010u32.into();
         let poll = Some(
-            generate_poll::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
+            generate_poll_input::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
         );
         let text = vec![1u8].repeat(MAX_BYTES as usize);
 
@@ -1820,7 +1805,7 @@ benchmarks! {
         // Create threads
         let expiration_diff = 1010u32.into();
         let poll = Some(
-            generate_poll::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
+            generate_poll_input::<T>(expiration_diff, (<<<T as Trait>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>::get() - 1) as u32)
         );
         let text = vec![1u8].repeat(MAX_BYTES as usize);
 

+ 46 - 14
runtime-modules/forum/src/lib.rs

@@ -173,7 +173,7 @@ pub trait Trait:
 }
 
 /// Upper bounds for storage maps and double maps. Needed to prevent potential block exhaustion during deletion, etc.
-/// MaxSubcategories, MaxThreadsInCategory, and MaxPostsInThread should be reasonably small because when the category is deleted
+/// MaxSubcategories, and MaxCategories should be reasonably small because when the category is deleted
 /// all of it's subcategories with their threads and posts will be iterated over and deleted.
 pub trait StorageLimits {
     /// Maximum direct subcategories in a category
@@ -189,7 +189,7 @@ pub trait StorageLimits {
     type MaxPollAlternativesNumber: Get<u64>;
 }
 
-/// Represents all poll alternatives and vote count for each one
+/// Represents all poll alternative text hashes and vote count for each one
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
 pub struct PollAlternative<Hash> {
@@ -200,6 +200,20 @@ pub struct PollAlternative<Hash> {
     pub vote_count: u32,
 }
 
+/// Represents a poll input
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
+pub struct PollInput<Timestamp> {
+    /// description
+    pub description: Vec<u8>,
+
+    /// timestamp of poll end
+    pub end_time: Timestamp,
+
+    /// Alternative polls description
+    pub poll_alternatives: Vec<Vec<u8>>,
+}
+
 /// Represents a poll
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
@@ -207,7 +221,7 @@ pub struct Poll<Timestamp, Hash> {
     /// hash of description
     pub description_hash: Hash,
 
-    /// pallet_timestamp of poll end
+    /// timestamp of poll end
     pub end_time: Timestamp,
 
     /// Alternative description and count
@@ -480,7 +494,7 @@ decl_event!(
         ForumUserId = ForumUserId<T>,
         <T as Trait>::PostReactionId,
         PrivilegedActor = PrivilegedActor<T>,
-        Poll = Poll<<T as pallet_timestamp::Trait>::Moment, <T as frame_system::Trait>::Hash>,
+        PollInput = PollInput<<T as pallet_timestamp::Trait>::Moment>,
     {
         /// A category was introduced
         CategoryCreated(CategoryId, Option<CategoryId>, Vec<u8>, Vec<u8>),
@@ -502,7 +516,7 @@ decl_event!(
 
         /// A thread with given id was created.
         /// A third argument reflects the initial post id of the thread.
-        ThreadCreated(CategoryId, ThreadId, PostId, ForumUserId, Vec<u8>, Vec<u8>, Option<Poll>),
+        ThreadCreated(CategoryId, ThreadId, PostId, ForumUserId, Vec<u8>, Vec<u8>, Option<PollInput>),
 
         /// A thread with given id was moderated.
         ThreadModerated(ThreadId, Vec<u8>, PrivilegedActor, CategoryId),
@@ -883,7 +897,7 @@ decl_module! {
             category_id: T::CategoryId,
             title: Vec<u8>,
             text: Vec<u8>,
-            poll: Option<Poll<T::Moment, T::Hash>>,
+            poll_input: Option<PollInput<T::Moment>>,
         ) -> DispatchResult {
             // Ensure data migration is done
             Self::ensure_data_migration_done()?;
@@ -893,12 +907,12 @@ decl_module! {
             Self::ensure_can_create_thread(&account_id, &forum_user_id, &category_id)?;
 
             // Ensure poll is valid
-            if let Some(ref data) = poll {
+            if let Some(ref data) = poll_input {
                 // Check all poll alternatives
                 Self::ensure_poll_alternatives_length_is_valid(&data.poll_alternatives)?;
 
                 // Check poll self information
-                Self::ensure_poll_is_valid(data)?;
+                Self::ensure_poll_input_is_valid(data)?;
             }
 
             //
@@ -916,12 +930,15 @@ decl_module! {
                 &account_id
             )?;
 
+            // Hash poll description and poll alternatives description
+            let poll = poll_input.clone().map(Self::from_poll_input);
+
             // Build a new thread
             let new_thread = Thread {
                 category_id,
                 title_hash: T::calculate_hash(&title),
                 author_id: forum_user_id,
-                poll: poll.clone(),
+                poll,
                 cleanup_pay_off: T::ThreadDeposit::get(),
                 number_of_posts: 0,
             };
@@ -955,7 +972,7 @@ decl_module! {
                     forum_user_id,
                     title,
                     text,
-                    poll,
+                    poll_input,
                 )
             );
 
@@ -1546,6 +1563,22 @@ decl_module! {
 }
 
 impl<T: Trait> Module<T> {
+    /// Hash poll description and poll alternatives descriptions, coverting `PollInput` into `Poll`
+    fn from_poll_input(poll_input: PollInput<T::Moment>) -> Poll<T::Moment, T::Hash> {
+        Poll {
+            description_hash: T::calculate_hash(poll_input.description.as_slice()),
+            poll_alternatives: poll_input
+                .poll_alternatives
+                .into_iter()
+                .map(|poll_alternative| PollAlternative {
+                    alternative_text_hash: T::calculate_hash(poll_alternative.as_slice()),
+                    vote_count: 0,
+                })
+                .collect(),
+            end_time: poll_input.end_time,
+        }
+    }
+
     fn slash_thread_account(thread_id: T::ThreadId, amount: BalanceOf<T>) {
         let thread_account_id = T::ModuleId::get().into_sub_account(thread_id);
         let _ = Balances::<T>::slash(&thread_account_id, amount);
@@ -1579,6 +1612,7 @@ impl<T: Trait> Module<T> {
         )
     }
 
+    /// Add new posts & increase thread counter
     pub fn add_new_post(
         thread_id: T::ThreadId,
         category_id: T::CategoryId,
@@ -1636,7 +1670,7 @@ impl<T: Trait> Module<T> {
     }
 
     // Ensure poll is valid
-    fn ensure_poll_is_valid(poll: &Poll<T::Moment, T::Hash>) -> Result<(), Error<T>> {
+    fn ensure_poll_input_is_valid(poll: &PollInput<T::Moment>) -> Result<(), Error<T>> {
         // Poll end time must larger than now
         if poll.end_time < <pallet_timestamp::Module<T>>::now() {
             return Err(Error::<T>::PollTimeSetting);
@@ -1646,9 +1680,7 @@ impl<T: Trait> Module<T> {
     }
 
     // Ensure poll alternative size is valid
-    fn ensure_poll_alternatives_length_is_valid(
-        alternatives: &[PollAlternative<T::Hash>],
-    ) -> Result<(), Error<T>> {
+    fn ensure_poll_alternatives_length_is_valid<K>(alternatives: &[K]) -> Result<(), Error<T>> {
         Self::ensure_map_limits::<<<T>::MapLimits as StorageLimits>::MaxPollAlternativesNumber>(
             alternatives.len() as u64,
         )?;

+ 50 - 20
runtime-modules/forum/src/mock.rs

@@ -555,83 +555,93 @@ pub const FORUM_MODERATOR_2_ORIGIN: OriginType = OriginType::Signed(FORUM_MODERA
 const EXTRA_MODERATOR_COUNT: usize = 5;
 pub const EXTRA_MODERATORS: [u128; EXTRA_MODERATOR_COUNT] = [125, 126, 127, 128, 129];
 
+/// Get a good category title
 pub fn good_category_title() -> Vec<u8> {
     b"Great new category".to_vec()
 }
 
+/// Get a new good category title
 pub fn good_category_title_new() -> Vec<u8> {
     b"Great new category title".to_vec()
 }
 
+/// Get a good category description
 pub fn good_category_description() -> Vec<u8> {
     b"This is a great new category for the forum".to_vec()
 }
 
+/// Get a good new category description
 pub fn good_category_description_new() -> Vec<u8> {
     b"This is a great new category description for the forum".to_vec()
 }
 
+/// Get a new good thread title
 pub fn good_thread_title() -> Vec<u8> {
     b"Great new thread".to_vec()
 }
 
+/// Get a new good thread text
 pub fn good_thread_text() -> Vec<u8> {
     b"The first post in this thread".to_vec()
 }
 
+/// Get a new title ofr the  good  thread
 pub fn good_thread_new_title() -> Vec<u8> {
     b"Brand new thread title".to_vec()
 }
 
+/// Get a good post text
 pub fn good_post_text() -> Vec<u8> {
     b"A response in the thread".to_vec()
 }
 
+/// Get a good new post text
 pub fn good_post_new_text() -> Vec<u8> {
     b"Changed post's text".to_vec()
 }
 
+/// Get a good moderation rationale
 pub fn good_moderation_rationale() -> Vec<u8> {
     b"Moderation rationale".to_vec()
 }
 
+/// Get a good poll description
 pub fn good_poll_description() -> Vec<u8> {
     b"poll description".to_vec()
 }
 
+/// Get a good poll alternative text
 pub fn good_poll_alternative_text() -> Vec<u8> {
     b"poll alternative".to_vec()
 }
 
-pub fn generate_poll(
+/// Generate a valid poll input
+pub fn generate_poll_input(
     expiration_diff: u64,
-) -> Poll<<Runtime as pallet_timestamp::Trait>::Moment, <Runtime as frame_system::Trait>::Hash> {
-    Poll {
-        description_hash: Runtime::calculate_hash(good_poll_description().as_slice()),
+) -> PollInput<<Runtime as pallet_timestamp::Trait>::Moment> {
+    PollInput {
+        description: good_poll_description(),
         end_time: Timestamp::now() + expiration_diff,
         poll_alternatives: {
             let mut alternatives = vec![];
             for _ in 0..5 {
-                alternatives.push(PollAlternative {
-                    alternative_text_hash: Runtime::calculate_hash(
-                        good_poll_alternative_text().as_slice(),
-                    ),
-                    vote_count: 0,
-                });
+                alternatives.push(good_poll_alternative_text());
             }
             alternatives
         },
     }
 }
 
-pub fn generate_poll_timestamp_cases(
+/// Generate poll input for different timestamp cases
+pub fn generate_poll_input_timestamp_cases(
     index: usize,
     expiration_diff: u64,
-) -> Poll<<Runtime as pallet_timestamp::Trait>::Moment, <Runtime as frame_system::Trait>::Hash> {
-    let test_cases = vec![generate_poll(expiration_diff), generate_poll(1)];
+) -> PollInput<<Runtime as pallet_timestamp::Trait>::Moment> {
+    let test_cases = vec![generate_poll_input(expiration_diff), generate_poll_input(1)];
     test_cases[index].clone()
 }
 
+/// Create category mock
 pub fn create_category_mock(
     origin: OriginType,
     parent: Option<<Runtime as Trait>::CategoryId>,
@@ -664,6 +674,7 @@ pub fn create_category_mock(
     category_id
 }
 
+/// Create thread mock
 pub fn create_thread_mock(
     origin: OriginType,
     account_id: <Runtime as frame_system::Trait>::AccountId,
@@ -671,9 +682,7 @@ pub fn create_thread_mock(
     category_id: <Runtime as Trait>::CategoryId,
     title: Vec<u8>,
     text: Vec<u8>,
-    poll_data: Option<
-        Poll<<Runtime as pallet_timestamp::Trait>::Moment, <Runtime as frame_system::Trait>::Hash>,
-    >,
+    poll_input_data: Option<PollInput<<Runtime as pallet_timestamp::Trait>::Moment>>,
     result: DispatchResult,
 ) -> <Runtime as Trait>::ThreadId {
     let thread_id = TestForumModule::next_thread_id();
@@ -686,7 +695,7 @@ pub fn create_thread_mock(
             category_id,
             title.clone(),
             text.clone(),
-            poll_data.clone(),
+            poll_input_data.clone(),
         ),
         result
     );
@@ -701,7 +710,7 @@ pub fn create_thread_mock(
                 forum_user_id,
                 title.clone(),
                 text.clone(),
-                poll_data.clone()
+                poll_input_data.clone()
             ))
         );
 
@@ -720,6 +729,7 @@ pub fn create_thread_mock(
     thread_id
 }
 
+/// Create edit thread title mock
 pub fn edit_thread_title_mock(
     origin: OriginType,
     forum_user_id: ForumUserId<Runtime>,
@@ -756,6 +766,7 @@ pub fn edit_thread_title_mock(
     thread_id
 }
 
+/// Create delete thread mock
 pub fn delete_thread_mock(
     origin: OriginType,
     account_id: <Runtime as frame_system::Trait>::AccountId,
@@ -810,6 +821,7 @@ pub fn delete_thread_mock(
     }
 }
 
+/// Create delete post mock
 pub fn delete_post_mock(
     origin: OriginType,
     account_id: <Runtime as frame_system::Trait>::AccountId,
@@ -863,6 +875,7 @@ pub fn delete_post_mock(
     }
 }
 
+/// Create move thread mock
 pub fn move_thread_mock(
     origin: OriginType,
     moderator_id: ModeratorId<Runtime>,
@@ -898,6 +911,7 @@ pub fn move_thread_mock(
     }
 }
 
+/// Made a create post mock
 pub fn create_post_mock(
     origin: OriginType,
     account_id: <Runtime as frame_system::Trait>::AccountId,
@@ -960,6 +974,7 @@ pub fn create_post_mock(
     post_id
 }
 
+/// Create edit post text mock
 pub fn edit_post_text_mock(
     origin: OriginType,
     forum_user_id: ForumUserId<Runtime>,
@@ -998,10 +1013,12 @@ pub fn edit_post_text_mock(
     post_id
 }
 
+/// Change current timestamp
 pub fn change_current_time(diff: u64) -> () {
     Timestamp::set_timestamp(Timestamp::now() + diff);
 }
 
+/// Create update category membership of moderator mock
 pub fn update_category_membership_of_moderator_mock(
     origin: OriginType,
     moderator_id: ModeratorId<Runtime>,
@@ -1036,6 +1053,7 @@ pub fn update_category_membership_of_moderator_mock(
     category_id
 }
 
+/// Create vote on poll mock
 pub fn vote_on_poll_mock(
     origin: OriginType,
     forum_user_id: ForumUserId<Runtime>,
@@ -1081,6 +1099,7 @@ pub fn vote_on_poll_mock(
     thread_id
 }
 
+/// Create update category archival status mock
 pub fn update_category_archival_status_mock(
     origin: OriginType,
     actor: PrivilegedActor<Runtime>,
@@ -1109,6 +1128,7 @@ pub fn update_category_archival_status_mock(
     }
 }
 
+/// Create update category title mock
 pub fn update_category_title_mock(
     origin: OriginType,
     actor: PrivilegedActor<Runtime>,
@@ -1138,6 +1158,7 @@ pub fn update_category_title_mock(
     }
 }
 
+/// Create update category description mock
 pub fn update_category_description_mock(
     origin: OriginType,
     actor: PrivilegedActor<Runtime>,
@@ -1167,6 +1188,7 @@ pub fn update_category_description_mock(
     }
 }
 
+/// Create delete category mock
 pub fn delete_category_mock(
     origin: OriginType,
     moderator_id: PrivilegedActor<Runtime>,
@@ -1186,6 +1208,7 @@ pub fn delete_category_mock(
     }
 }
 
+/// Create moderate thread mock
 pub fn moderate_thread_mock(
     origin: OriginType,
     moderator_id: ModeratorId<Runtime>,
@@ -1227,6 +1250,7 @@ pub fn moderate_thread_mock(
     thread_id
 }
 
+/// Create moderate post mock
 pub fn moderate_post_mock(
     origin: OriginType,
     moderator_id: ModeratorId<Runtime>,
@@ -1275,6 +1299,7 @@ pub fn moderate_post_mock(
     post_id
 }
 
+/// Create set stickied threads mock
 pub fn set_stickied_threads_mock(
     origin: OriginType,
     moderator_id: ModeratorId<Runtime>,
@@ -1308,6 +1333,7 @@ pub fn set_stickied_threads_mock(
     category_id
 }
 
+/// Create react post mock
 pub fn react_post_mock(
     origin: OriginType,
     forum_user_id: ForumUserId<Runtime>,
@@ -1342,14 +1368,17 @@ pub fn react_post_mock(
     };
 }
 
+/// Create default genesis config
 pub fn default_genesis_config() -> GenesisConfig<Runtime> {
     create_genesis_config(true)
 }
 
+/// Create config without data migration
 pub fn migration_not_done_config() -> GenesisConfig<Runtime> {
     create_genesis_config(false)
 }
 
+/// Create genesis config
 pub fn create_genesis_config(data_migration_done: bool) -> GenesisConfig<Runtime> {
     GenesisConfig::<Runtime> {
         category_by_id: vec![],
@@ -1380,6 +1409,7 @@ pub fn build_test_externalities(config: GenesisConfig<Runtime>) -> sp_io::TestEx
     t.into()
 }
 
+/// Generate enviroment with test externalities
 pub fn with_test_externalities<R, F: FnOnce() -> R>(f: F) -> R {
     let default_genesis_config = default_genesis_config();
     /*
@@ -1407,11 +1437,11 @@ pub fn run_to_block(n: u64) {
     }
 }
 
-// pub type System = system::Module<Runtime>;
+/// System module on a test runtime
 pub type System = frame_system::Module<Runtime>;
 
+/// Timestamp module on a test runtime
 pub type Timestamp = pallet_timestamp::Module<Runtime>;
-// pub type System = frame_system::Module<Runtime>;
 
 /// Export forum module on a test runtime
 pub type TestForumModule = Module<Runtime>;

+ 5 - 5
runtime-modules/forum/src/tests.rs

@@ -963,7 +963,7 @@ fn create_thread_poll_timestamp() {
             balances::Module::<Runtime>::make_free_balance_be(&forum_lead, initial_balance);
 
             change_current_time(1);
-            let poll = generate_poll_timestamp_cases(index, expiration_diff);
+            let poll = generate_poll_input_timestamp_cases(index, expiration_diff);
             change_current_time(index as u64 * expiration_diff + 1);
 
             let category_id = create_category_mock(
@@ -1088,7 +1088,7 @@ fn delete_thread() {
             category_id,
             good_thread_title(),
             good_thread_text(),
-            Some(generate_poll(10)),
+            Some(generate_poll_input(10)),
             Ok(()),
         );
 
@@ -1434,7 +1434,7 @@ fn vote_on_poll_origin() {
                 category_id,
                 good_thread_title(),
                 good_thread_text(),
-                Some(generate_poll(expiration_diff)),
+                Some(generate_poll_input(expiration_diff)),
                 Ok(()),
             );
 
@@ -1473,7 +1473,7 @@ fn vote_on_poll_fails_on_double_voting() {
             category_id,
             good_thread_title(),
             good_thread_text(),
-            Some(generate_poll(expiration_diff)),
+            Some(generate_poll_input(expiration_diff)),
             Ok(()),
         );
 
@@ -1558,7 +1558,7 @@ fn vote_on_poll_expired() {
             category_id,
             good_thread_title(),
             good_thread_text(),
-            Some(generate_poll(expiration_diff)),
+            Some(generate_poll_input(expiration_diff)),
             Ok(()),
         );
         change_current_time(expiration_diff + 1);