Browse Source

runtime: storage: Add extrinsic.

- add `set_distribution_operator_metadata`
Shamil Gadelshin 3 years ago
parent
commit
f5ebba5bfa

+ 61 - 2
runtime-modules/storage/src/lib.rs

@@ -74,8 +74,12 @@
 //!  invites a distribution bucket operator.
 //! - [cancel_distribution_bucket_operator_invite](./struct.Module.html#method.cancel_distribution_bucket_operator_invite) -
 //!  Cancels pending invite for a distribution bucket.
+
+//! #### Distribution provider extrinsics
 //! - [accept_distribution_bucket_invitation](./struct.Module.html#method.accept_distribution_bucket_invitation) -
 //!  Accepts pending invite for a distribution bucket.
+//! - [set_distribution_operator_metadata](./struct.Module.html#method.set_distribution_operator_metadata) -
+//!  Set distribution operator metadata for the distribution bucket.
 //!
 //! #### Public methods
 //! Public integration methods are exposed via the [DataObjectStorage](./trait.DataObjectStorage.html)
@@ -151,6 +155,7 @@ use storage_bucket_picker::StorageBucketPicker;
 // How to be sure that we don't have already accepted invitation? We need to have it in the bucket
 // a separate map. DistributionOperatorId is not sustainable - verify that on Monday.
 // TODO: test invite_distribution_bucket_operator with accepted invitation.
+// TODO: test docs.
 
 /// Public interface for the storage module.
 pub trait DataObjectStorage<T: Trait> {
@@ -1149,16 +1154,29 @@ decl_event! {
             WorkerId,
         ),
 
-        /// Emits on canceling a distribution bucket invitation for the operator.
+        /// Emits on accepting a distribution bucket invitation for the operator.
         /// Params
+        /// - worker ID
         /// - distribution bucket family ID
         /// - distribution bucket ID
-        /// - worker ID
         DistributionBucketInvitationAccepted(
             WorkerId,
             DistributionBucketFamilyId,
             DistributionBucketId,
         ),
+
+        /// Emits on setting the metadata by a distribution bucket operator.
+        /// Params
+        /// - worker ID
+        /// - distribution bucket family ID
+        /// - distribution bucket ID
+        /// - metadata
+        DistributionBucketMetadataSet(
+            WorkerId,
+            DistributionBucketFamilyId,
+            DistributionBucketId,
+            Vec<u8>
+        ),
     }
 }
 
@@ -1320,6 +1338,9 @@ decl_error! {
 
         /// No distribution bucket invitation.
         NoDistributionBucketInvitation,
+
+        /// Invalid operations: must be a distribution provider operator for a bucket.
+        MustBeDistributionProviderOperatorForBucket,
     }
 }
 
@@ -2298,9 +2319,47 @@ decl_module! {
                 )
             );
         }
+
+        /// Set distribution operator metadata for the distribution bucket.
+        #[weight = 10_000_000] // TODO: adjust weight
+        pub fn set_distribution_operator_metadata(
+            origin,
+            worker_id: WorkerId<T>,
+            distribution_bucket_family_id: T::DistributionBucketFamilyId,
+            distribution_bucket_id: T::DistributionBucketId,
+            metadata: Vec<u8>,
+        ) {
+            T::ensure_distribution_worker_origin(origin, worker_id)?;
+
+            let family =
+                Self::ensure_distribution_bucket_family_exists(&distribution_bucket_family_id)?;
+            let bucket = Self::ensure_distribution_bucket_exists(
+                &family,
+                &distribution_bucket_id
+            )?;
+
+            ensure!(
+                bucket.operators.contains(&worker_id),
+                Error::<T>::MustBeDistributionProviderOperatorForBucket
+            );
+
+            //
+            // == MUTATION SAFE ==
+            //
+
+            Self::deposit_event(
+                RawEvent::DistributionBucketMetadataSet(
+                    worker_id,
+                    distribution_bucket_family_id,
+                    distribution_bucket_id,
+                    metadata
+                )
+            );
+        }
     }
 }
 
+// -
 // Public methods
 impl<T: Trait> DataObjectStorage<T> for Module<T> {
     fn can_upload_data_objects(params: &UploadParameters<T>) -> DispatchResult {

+ 52 - 0
runtime-modules/storage/src/tests/fixtures.rs

@@ -1807,3 +1807,55 @@ impl AcceptDistributionBucketInvitationFixture {
         }
     }
 }
+
+pub struct SetDistributionBucketMetadataFixture {
+    origin: RawOrigin<u64>,
+    bucket_id: u64,
+    family_id: u64,
+    worker_id: u64,
+    metadata: Vec<u8>,
+}
+
+impl SetDistributionBucketMetadataFixture {
+    pub fn default() -> Self {
+        Self {
+            origin: RawOrigin::Signed(DEFAULT_DISTRIBUTION_PROVIDER_ACCOUNT_ID),
+            bucket_id: Default::default(),
+            family_id: Default::default(),
+            worker_id: Default::default(),
+            metadata: Default::default(),
+        }
+    }
+
+    pub fn with_metadata(self, metadata: Vec<u8>) -> Self {
+        Self { metadata, ..self }
+    }
+
+    pub fn with_origin(self, origin: RawOrigin<u64>) -> Self {
+        Self { origin, ..self }
+    }
+
+    pub fn with_bucket_id(self, bucket_id: u64) -> Self {
+        Self { bucket_id, ..self }
+    }
+
+    pub fn with_family_id(self, family_id: u64) -> Self {
+        Self { family_id, ..self }
+    }
+
+    pub fn with_worker_id(self, worker_id: u64) -> Self {
+        Self { worker_id, ..self }
+    }
+
+    pub fn call_and_assert(&self, expected_result: DispatchResult) {
+        let actual_result = Storage::set_distribution_operator_metadata(
+            self.origin.clone().into(),
+            self.worker_id,
+            self.family_id,
+            self.bucket_id,
+            self.metadata.clone(),
+        );
+
+        assert_eq!(actual_result, expected_result);
+    }
+}

+ 118 - 6
runtime-modules/storage/src/tests/mod.rs

@@ -4254,7 +4254,7 @@ fn invite_distribution_bucket_operator_fails_with_non_leader_origin() {
 }
 
 #[test]
-fn invite_distribution_bucket_operator_fails_with_non_existing_storage_bucket() {
+fn invite_distribution_bucket_operator_fails_with_non_existing_distribution_bucket() {
     build_test_externalities().execute_with(|| {
         let family_id = CreateDistributionBucketFamilyFixture::default()
             .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
@@ -4303,7 +4303,7 @@ fn invite_distribution_bucket_operator_fails_with_non_missing_invitation() {
 }
 
 #[test]
-fn invite_distribution_bucket_operator_fails_with_invalid_storage_provider_id() {
+fn invite_distribution_bucket_operator_fails_with_invalid_distribution_provider_id() {
     build_test_externalities().execute_with(|| {
         let invalid_provider_id = 155;
 
@@ -4393,7 +4393,7 @@ fn cancel_distribution_bucket_operator_invite_fails_with_non_leader_origin() {
 }
 
 #[test]
-fn cancel_distribution_bucket_operator_invite_fails_with_non_existing_storage_bucket() {
+fn cancel_distribution_bucket_operator_invite_fails_with_non_existing_distribution_bucket() {
     build_test_externalities().execute_with(|| {
         let family_id = CreateDistributionBucketFamilyFixture::default()
             .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
@@ -4408,7 +4408,7 @@ fn cancel_distribution_bucket_operator_invite_fails_with_non_existing_storage_bu
 }
 
 #[test]
-fn cancel_distribution_bucket_operator_invite_fails_with_non_invited_storage_provider() {
+fn cancel_distribution_bucket_operator_invite_fails_with_non_invited_distribution_provider() {
     build_test_externalities().execute_with(|| {
         let family_id = CreateDistributionBucketFamilyFixture::default()
             .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
@@ -4493,7 +4493,7 @@ fn accept_distribution_bucket_operator_invite_fails_with_non_leader_origin() {
 }
 
 #[test]
-fn accept_distribution_bucket_operator_invite_fails_with_non_existing_storage_bucket() {
+fn accept_distribution_bucket_operator_invite_fails_with_non_existing_distribution_bucket() {
     build_test_externalities().execute_with(|| {
         let family_id = CreateDistributionBucketFamilyFixture::default()
             .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
@@ -4508,7 +4508,7 @@ fn accept_distribution_bucket_operator_invite_fails_with_non_existing_storage_bu
 }
 
 #[test]
-fn accept_distribution_bucket_operator_invite_fails_with_non_invited_storage_provider() {
+fn accept_distribution_bucket_operator_invite_fails_with_non_invited_distribution_provider() {
     build_test_externalities().execute_with(|| {
         let family_id = CreateDistributionBucketFamilyFixture::default()
             .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
@@ -4539,3 +4539,115 @@ fn accept_distribution_bucket_operator_invite_fails_with_invalid_distribution_bu
             ));
     });
 }
+
+#[test]
+fn set_distribution_operator_metadata_invite_succeeded() {
+    build_test_externalities().execute_with(|| {
+        let starting_block = 1;
+        run_to_block(starting_block);
+
+        let provider_id = DEFAULT_DISTRIBUTION_PROVIDER_ID;
+        let metadata = b"Metadata".to_vec();
+
+        let family_id = CreateDistributionBucketFamilyFixture::default()
+            .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
+            .call_and_assert(Ok(()))
+            .unwrap();
+
+        let bucket_id = CreateDistributionBucketFixture::default()
+            .with_family_id(family_id)
+            .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
+            .call_and_assert(Ok(()))
+            .unwrap();
+
+        InviteDistributionBucketOperatorFixture::default()
+            .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
+            .with_bucket_id(bucket_id)
+            .with_family_id(family_id)
+            .with_operator_worker_id(provider_id)
+            .call_and_assert(Ok(()));
+
+        AcceptDistributionBucketInvitationFixture::default()
+            .with_origin(RawOrigin::Signed(DEFAULT_DISTRIBUTION_PROVIDER_ACCOUNT_ID))
+            .with_family_id(family_id)
+            .with_bucket_id(bucket_id)
+            .with_worker_id(provider_id)
+            .call_and_assert(Ok(()));
+
+        SetDistributionBucketMetadataFixture::default()
+            .with_origin(RawOrigin::Signed(DEFAULT_DISTRIBUTION_PROVIDER_ACCOUNT_ID))
+            .with_family_id(family_id)
+            .with_bucket_id(bucket_id)
+            .with_worker_id(provider_id)
+            .with_metadata(metadata.clone())
+            .call_and_assert(Ok(()));
+
+        EventFixture::assert_last_crate_event(RawEvent::DistributionBucketMetadataSet(
+            provider_id,
+            family_id,
+            bucket_id,
+            metadata,
+        ));
+    });
+}
+
+#[test]
+fn set_distribution_operator_metadata_fails_with_non_leader_origin() {
+    build_test_externalities().execute_with(|| {
+        let invalid_account_id = 11111;
+
+        SetDistributionBucketMetadataFixture::default()
+            .with_origin(RawOrigin::Signed(invalid_account_id))
+            .call_and_assert(Err(DispatchError::BadOrigin));
+    });
+}
+
+#[test]
+fn set_distribution_operator_metadata_fails_with_non_existing_distribution_bucket() {
+    build_test_externalities().execute_with(|| {
+        let family_id = CreateDistributionBucketFamilyFixture::default()
+            .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
+            .call_and_assert(Ok(()))
+            .unwrap();
+
+        SetDistributionBucketMetadataFixture::default()
+            .with_family_id(family_id)
+            .with_origin(RawOrigin::Signed(DEFAULT_DISTRIBUTION_PROVIDER_ACCOUNT_ID))
+            .call_and_assert(Err(Error::<Test>::DistributionBucketDoesntExist.into()));
+    });
+}
+
+#[test]
+fn set_distribution_operator_metadata_fails_with_non_distribution_provider() {
+    build_test_externalities().execute_with(|| {
+        let family_id = CreateDistributionBucketFamilyFixture::default()
+            .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
+            .call_and_assert(Ok(()))
+            .unwrap();
+
+        let bucket_id = CreateDistributionBucketFixture::default()
+            .with_family_id(family_id)
+            .with_origin(RawOrigin::Signed(DISTRIBUTION_WG_LEADER_ACCOUNT_ID))
+            .call_and_assert(Ok(()))
+            .unwrap();
+
+        SetDistributionBucketMetadataFixture::default()
+            .with_origin(RawOrigin::Signed(DEFAULT_DISTRIBUTION_PROVIDER_ACCOUNT_ID))
+            .with_family_id(family_id)
+            .with_bucket_id(bucket_id)
+            .call_and_assert(Err(
+                Error::<Test>::MustBeDistributionProviderOperatorForBucket.into(),
+            ));
+    });
+}
+
+#[test]
+fn set_distribution_operator_metadata_fails_with_invalid_distribution_bucket_family() {
+    build_test_externalities().execute_with(|| {
+        SetDistributionBucketMetadataFixture::default()
+            .with_origin(RawOrigin::Signed(DEFAULT_DISTRIBUTION_PROVIDER_ACCOUNT_ID))
+            .call_and_assert(Err(
+                Error::<Test>::DistributionBucketFamilyDoesntExist.into()
+            ));
+    });
+}