Browse Source

runtime: storage: Add ‘MaxDistributionBucketFamilyNumber’ constant.

Shamil Gadelshin 3 years ago
parent
commit
e040109af7

+ 43 - 5
runtime-modules/storage/src/lib.rs

@@ -5,12 +5,14 @@
 //! - [spec](https://github.com/Joystream/joystream/issues/2224)
 //! - [utilization model](https://github.com/Joystream/joystream/issues/2359)
 //!
-//! Pallet functionality could be split in three distinct groups:
-//! - extrinsics for the working group leader
+//! Pallet functionality could be split in five distinct groups:
+//! - extrinsics for the storage working group leader
+//! - extrinsics for the distribution group leader
 //! - extrinsics for the storage provider
+//! - extrinsics for the distribution provider
 //! - public methods for the pallet integration
 //!
-//! #### Working group leader extrinsics
+//! #### Storage working group leader extrinsics
 //! - [create_storage_bucket](./struct.Module.html#method.create_storage_bucket) - creates storage
 //! bucket.
 //! - [update_storage_buckets_for_bag](./struct.Module.html#method.update_storage_buckets_for_bag) -
@@ -49,6 +51,10 @@
 //! - [accept_pending_data_objects](./struct.Module.html#method.accept_pending_data_objects) - a
 //! storage provider signals that the data object was successfully uploaded to its storage.
 //!
+//! #### Distribution working group leader extrinsics
+//! - [create_distribution_bucket_family](./struct.Module.html#method.create_distribution_bucket_family) -
+//! creates distribution bucket family.
+//!
 //! #### Public methods
 //! Public integration methods are exposed via the [DataObjectStorage](./trait.DataObjectStorage.html)
 //! - can_upload_data_objects
@@ -70,6 +76,7 @@
 //! - StorageBucketsPerBagValueConstraint
 //! - DefaultMemberDynamicBagCreationPolicy
 //! - DefaultChannelDynamicBagCreationPolicy
+//! - MaxDistributionBucketFamilyNumber
 //!
 
 // Ensure we're `no_std` when compiling for Wasm.
@@ -255,6 +262,9 @@ pub trait Trait: frame_system::Trait + balances::Trait + membership::Trait {
     /// Something that provides randomness in the runtime.
     type Randomness: Randomness<Self::Hash>;
 
+    /// Defines max allowed distribution bucket family number.
+    type MaxDistributionBucketFamilyNumber: Get<u64>;
+
     /// Demand the storage working group leader authorization.
     /// TODO: Refactor after merging with the Olympia release.
     fn ensure_storage_working_group_leader_origin(origin: Self::Origin) -> DispatchResult;
@@ -799,6 +809,9 @@ decl_storage! {
         pub DistributionBucketFamilyById get (fn distribution_bucket_family_by_id):
             map hasher(blake2_128_concat) T::DistributionBucketFamilyId =>
             DistributionBucketFamily<T::DistributionBucketId>;
+
+        /// Total number of distribution bucket families in the system.
+        pub DistributionBucketFamilyNumber get(fn distribution_bucket_family_number): u64;
     }
 }
 
@@ -1086,6 +1099,9 @@ decl_error! {
 
         /// Storage provider operator doesn't exist.
         StorageProviderOperatorDoesntExist,
+
+        /// Max distribution bucket family number limit exceeded.
+        MaxDistributionBucketFamilyNumberLimitExceeded,
     }
 }
 
@@ -1122,6 +1138,9 @@ decl_module! {
         const DefaultChannelDynamicBagCreationPolicy: DynamicBagCreationPolicy =
             T::DefaultChannelDynamicBagCreationPolicy::get();
 
+        /// Exports const - max allowed distribution bucket family number.
+        const MaxDistributionBucketFamilyNumber: u64 = T::MaxDistributionBucketFamilyNumber::get();
+
         // ===== Storage Lead actions =====
 
         /// Delete storage bucket. Must be empty. Storage operator must be missing.
@@ -1647,18 +1666,25 @@ decl_module! {
           Self::create_dynamic_bag(bag_id)?;
         }
 
+        // ===== Distribution Lead actions =====
+
         /// Create a distribution family.
         #[weight = 10_000_000] // TODO: adjust weight
         pub fn create_distribution_bucket_family(origin) {
             T::ensure_distribution_working_group_leader_origin(origin)?;
 
-            // TODO: check max bucket families number
-
+            ensure!(
+                Self::distribution_bucket_family_number() <
+                    T::MaxDistributionBucketFamilyNumber::get(),
+                Error::<T>::MaxDistributionBucketFamilyNumberLimitExceeded
+            );
 
             //
             // == MUTATION SAFE ==
             //
 
+            Self::increment_distribution_family_number();
+
             let family = DistributionBucketFamily {
                 distribution_buckets: BTreeMap::new(),
             };
@@ -1894,6 +1920,18 @@ impl<T: Trait> DataObjectStorage<T> for Module<T> {
 }
 
 impl<T: Trait> Module<T> {
+    // Increment distribution family number in the storage.
+    fn increment_distribution_family_number() {
+        DistributionBucketFamilyNumber::put(Self::distribution_bucket_family_number() + 1);
+    }
+
+    // Decrement distribution family number in the storage. No effect on zero number.
+    fn decrement_distribution_family_number() {
+        if Self::distribution_bucket_family_number() > 0 {
+            DistributionBucketFamilyNumber::put(Self::distribution_bucket_family_number() - 1);
+        }
+    }
+
     // Validates dynamic bag creation params and conditions.
     fn validate_create_dynamic_bag_params(bag_id: &DynamicBagId<T>) -> DispatchResult {
         ensure!(

+ 6 - 3
runtime-modules/storage/src/tests/fixtures.rs

@@ -1195,7 +1195,7 @@ impl CreateDistributionBucketBucketFamilyFixture {
 
     pub fn call_and_assert(&self, expected_result: DispatchResult) -> Option<u64> {
         let next_family_id = Storage::next_distribution_bucket_family_id();
-        //let buckets_number = Storage::storage_buckets_number(); // TODO
+        let family_number = Storage::distribution_bucket_family_number();
         let actual_result = Storage::create_distribution_bucket_family(self.origin.clone().into());
 
         assert_eq!(actual_result, expected_result);
@@ -1205,7 +1205,10 @@ impl CreateDistributionBucketBucketFamilyFixture {
                 next_family_id + 1,
                 Storage::next_distribution_bucket_family_id()
             );
-            // assert_eq!(buckets_number + 1, Storage::storage_buckets_number()); //TODO
+            assert_eq!(
+                family_number + 1,
+                Storage::distribution_bucket_family_number()
+            );
             assert!(<crate::DistributionBucketFamilyById<Test>>::contains_key(
                 next_family_id
             ));
@@ -1216,7 +1219,7 @@ impl CreateDistributionBucketBucketFamilyFixture {
                 next_family_id,
                 Storage::next_distribution_bucket_family_id()
             );
-            // assert_eq!(buckets_number, Storage::storage_buckets_number()); //TODO
+            assert_eq!(family_number, Storage::distribution_bucket_family_number());
             assert!(!<crate::DistributionBucketFamilyById<Test>>::contains_key(
                 next_family_id
             ));

+ 2 - 0
runtime-modules/storage/src/tests/mocks.rs

@@ -54,6 +54,7 @@ impl balances::Trait for Test {
 parameter_types! {
     pub const MaxStorageBucketNumber: u64 = 1000;
     pub const MaxNumberOfDataObjectsPerBag: u64 = 4;
+    pub const MaxDistributionBucketFamilyNumber: u64 = 1;
     pub const DataObjectDeletionPrize: u64 = 10;
     pub const StorageModuleId: ModuleId = ModuleId(*b"mstorage"); // module storage
     pub const BlacklistSizeLimit: u64 = 1;
@@ -94,6 +95,7 @@ impl crate::Trait for Test {
     type DefaultChannelDynamicBagCreationPolicy = DefaultChannelDynamicBagCreationPolicy;
     type Randomness = CollectiveFlip;
     type MaxRandomIterationNumber = MaxRandomIterationNumber;
+    type MaxDistributionBucketFamilyNumber = MaxDistributionBucketFamilyNumber;
 
     fn ensure_storage_working_group_leader_origin(origin: Self::Origin) -> DispatchResult {
         let account_id = ensure_signed(origin)?;

+ 15 - 0
runtime-modules/storage/src/tests/mod.rs

@@ -3513,3 +3513,18 @@ fn create_distribution_bucket_family_fails_with_non_signed_origin() {
             .call_and_assert(Err(DispatchError::BadOrigin));
     });
 }
+
+#[test]
+fn create_distribution_bucket_family_fails_with_exceeding_family_number_limit() {
+    build_test_externalities().execute_with(|| {
+        CreateDistributionBucketBucketFamilyFixture::default()
+            .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
+            .call_and_assert(Ok(()));
+
+        CreateDistributionBucketBucketFamilyFixture::default()
+            .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
+            .call_and_assert(Err(
+                Error::<Test>::MaxDistributionBucketFamilyNumberLimitExceeded.into(),
+            ));
+    });
+}

+ 2 - 0
runtime/src/lib.rs

@@ -653,6 +653,7 @@ parameter_types! {
 }
 
 parameter_types! {
+    pub const MaxDistributionBucketFamilyNumber: u64 = 20; //TODO: adjust value
     pub const MaxStorageBucketNumber: u64 = 20; //TODO: adjust value
     pub const MaxNumberOfDataObjectsPerBag: u64 = 1000; //TODO: adjust value
     pub const DataObjectDeletionPrize: Balance = 10; //TODO: adjust value
@@ -687,6 +688,7 @@ impl storage::Trait for Runtime {
     type DefaultChannelDynamicBagCreationPolicy = DefaultChannelDynamicBagCreationPolicy;
     type Randomness = RandomnessCollectiveFlip;
     type MaxRandomIterationNumber = MaxRandomIterationNumber;
+    type MaxDistributionBucketFamilyNumber = MaxDistributionBucketFamilyNumber;
 
     fn ensure_storage_working_group_leader_origin(origin: Self::Origin) -> DispatchResult {
         StorageWorkingGroup::ensure_origin_is_active_leader(origin)