|
@@ -106,12 +106,6 @@ decl_error! {
|
|
/// Voucher objects limit upper bound exceeded
|
|
/// Voucher objects limit upper bound exceeded
|
|
VoucherObjectsLimitUpperBoundExceeded,
|
|
VoucherObjectsLimitUpperBoundExceeded,
|
|
|
|
|
|
- /// Contant uploading failed. Actor voucher size limit exceeded.
|
|
|
|
- GlobalVoucherSizeLimitExceeded,
|
|
|
|
-
|
|
|
|
- /// Contant uploading failed. Actor voucher objects limit exceeded.
|
|
|
|
- GlobalVoucherObjectsLimitExceeded,
|
|
|
|
-
|
|
|
|
/// Content uploading blocked.
|
|
/// Content uploading blocked.
|
|
ContentUploadingBlocked,
|
|
ContentUploadingBlocked,
|
|
|
|
|
|
@@ -119,7 +113,13 @@ decl_error! {
|
|
OwnersAreNotEqual,
|
|
OwnersAreNotEqual,
|
|
|
|
|
|
/// No storage provider available to service the request
|
|
/// No storage provider available to service the request
|
|
- NoProviderAvailable
|
|
|
|
|
|
+ NoProviderAvailable,
|
|
|
|
+
|
|
|
|
+ /// New voucher limit being set is less than used.
|
|
|
|
+ VoucherLimitLessThanUsed,
|
|
|
|
+
|
|
|
|
+ /// Overflow detected when changing
|
|
|
|
+ VoucherOverflow,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -195,15 +195,17 @@ pub struct Delta {
|
|
}
|
|
}
|
|
|
|
|
|
/// Uploading voucher for StorageObjectOwner
|
|
/// Uploading voucher for StorageObjectOwner
|
|
|
|
+/// All fields are private. All changes should be done through the methods
|
|
|
|
+/// to avoid invalid state.
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
#[derive(Clone, Copy, Encode, Decode, PartialEq, Eq, Debug, Default)]
|
|
#[derive(Clone, Copy, Encode, Decode, PartialEq, Eq, Debug, Default)]
|
|
pub struct Voucher {
|
|
pub struct Voucher {
|
|
// Total objects size limit per StorageObjectOwner
|
|
// Total objects size limit per StorageObjectOwner
|
|
- pub size_limit: u64,
|
|
|
|
|
|
+ size_limit: u64,
|
|
// Total objects number limit per StorageObjectOwner
|
|
// Total objects number limit per StorageObjectOwner
|
|
- pub objects_limit: u64,
|
|
|
|
- pub size_used: u64,
|
|
|
|
- pub objects_used: u64,
|
|
|
|
|
|
+ objects_limit: u64,
|
|
|
|
+ size_used: u64,
|
|
|
|
+ objects_used: u64,
|
|
}
|
|
}
|
|
|
|
|
|
impl Voucher {
|
|
impl Voucher {
|
|
@@ -217,7 +219,24 @@ impl Voucher {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /// Calculate voucher delta
|
|
|
|
|
|
+ pub fn get_size_limit(&self) -> u64 {
|
|
|
|
+ self.size_limit
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn get_objects_limit(&self) -> u64 {
|
|
|
|
+ self.objects_limit
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn get_size_used(&self) -> u64 {
|
|
|
|
+ self.size_used
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn get_objects_used(&self) -> u64 {
|
|
|
|
+ self.objects_used
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// Calculate voucher delta. We don't do checked_sub as the other methods
|
|
|
|
+ /// protect against state which would result in underflow.
|
|
pub fn calculate_delta(&self) -> Delta {
|
|
pub fn calculate_delta(&self) -> Delta {
|
|
Delta {
|
|
Delta {
|
|
size: self.size_limit - self.size_used,
|
|
size: self.size_limit - self.size_used,
|
|
@@ -225,28 +244,63 @@ impl Voucher {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- pub fn fill_voucher(self, voucher_delta: Delta) -> Self {
|
|
|
|
- Self {
|
|
|
|
- size_used: self.size_used + voucher_delta.size,
|
|
|
|
- objects_used: self.objects_used + voucher_delta.objects,
|
|
|
|
- ..self
|
|
|
|
|
|
+ /// Attempts to fill voucher and returns an updated Voucher if no overlflows occur
|
|
|
|
+ /// or limits are exceeded. Error otherwise.
|
|
|
|
+ pub fn fill_voucher<T: Trait>(self, voucher_delta: Delta) -> Result<Self, Error<T>> {
|
|
|
|
+ if let Some(size_used) = self.size_used.checked_add(voucher_delta.size) {
|
|
|
|
+ // Ensure size limit not exceeded
|
|
|
|
+ ensure!(
|
|
|
|
+ size_used <= self.size_limit,
|
|
|
|
+ Error::<T>::VoucherSizeLimitExceeded
|
|
|
|
+ );
|
|
|
|
+ if let Some(objects_used) = self.objects_used.checked_add(voucher_delta.objects) {
|
|
|
|
+ // Ensure objects limit not exceeded
|
|
|
|
+ ensure!(
|
|
|
|
+ objects_used <= self.objects_limit,
|
|
|
|
+ Error::<T>::VoucherObjectsLimitExceeded
|
|
|
|
+ );
|
|
|
|
+ return Ok(Self {
|
|
|
|
+ size_used,
|
|
|
|
+ objects_used,
|
|
|
|
+ ..self
|
|
|
|
+ });
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ Err(Error::<T>::VoucherOverflow)
|
|
}
|
|
}
|
|
|
|
|
|
- pub fn release_voucher(self, voucher_delta: Delta) -> Self {
|
|
|
|
- Self {
|
|
|
|
- size_used: self.size_used - voucher_delta.size,
|
|
|
|
- objects_used: self.objects_used - voucher_delta.objects,
|
|
|
|
- ..self
|
|
|
|
|
|
+ pub fn release_voucher<T: Trait>(self, voucher_delta: Delta) -> Result<Self, Error<T>> {
|
|
|
|
+ if let Some(size_used) = self.size_used.checked_sub(voucher_delta.size) {
|
|
|
|
+ if let Some(objects_used) = self.objects_used.checked_sub(voucher_delta.objects) {
|
|
|
|
+ return Ok(Self {
|
|
|
|
+ size_used,
|
|
|
|
+ objects_used,
|
|
|
|
+ ..self
|
|
|
|
+ });
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ Err(Error::<T>::VoucherOverflow)
|
|
}
|
|
}
|
|
|
|
|
|
- pub fn set_new_size_limit(&mut self, new_size_limit: u64) {
|
|
|
|
- self.size_limit = new_size_limit;
|
|
|
|
|
|
+ pub fn set_new_size_limit<T: Trait>(&mut self, new_size_limit: u64) -> Result<(), Error<T>> {
|
|
|
|
+ if self.size_used > new_size_limit {
|
|
|
|
+ Err(Error::<T>::VoucherLimitLessThanUsed)
|
|
|
|
+ } else {
|
|
|
|
+ self.size_limit = new_size_limit;
|
|
|
|
+ Ok(())
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- pub fn set_new_objects_limit(&mut self, new_objects_limit: u64) {
|
|
|
|
- self.objects_limit = new_objects_limit;
|
|
|
|
|
|
+ pub fn set_new_objects_limit<T: Trait>(
|
|
|
|
+ &mut self,
|
|
|
|
+ new_objects_limit: u64,
|
|
|
|
+ ) -> Result<(), Error<T>> {
|
|
|
|
+ if self.objects_used > new_objects_limit {
|
|
|
|
+ Err(Error::<T>::VoucherLimitLessThanUsed)
|
|
|
|
+ } else {
|
|
|
|
+ self.objects_limit = new_objects_limit;
|
|
|
|
+ Ok(())
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -271,7 +325,7 @@ decl_storage! {
|
|
pub VoucherObjectsLimitUpperBound get(fn voucher_objects_limit_upper_bound) config(): u64 = DEFAULT_VOUCHER_OBJECTS_LIMIT_UPPER_BOUND;
|
|
pub VoucherObjectsLimitUpperBound get(fn voucher_objects_limit_upper_bound) config(): u64 = DEFAULT_VOUCHER_OBJECTS_LIMIT_UPPER_BOUND;
|
|
|
|
|
|
/// Default content voucher for all actors.
|
|
/// Default content voucher for all actors.
|
|
- pub DefaultVoucher get(fn default_voucher) config(): Voucher;
|
|
|
|
|
|
+ pub DefaultVoucher get(fn default_voucher) config(): Voucher = DEFAULT_VOUCHER;
|
|
|
|
|
|
/// Global voucher.
|
|
/// Global voucher.
|
|
pub GlobalVoucher get(fn global_voucher) config(): Voucher = DEFAULT_GLOBAL_VOUCHER;
|
|
pub GlobalVoucher get(fn global_voucher) config(): Voucher = DEFAULT_GLOBAL_VOUCHER;
|
|
@@ -332,6 +386,32 @@ decl_event! {
|
|
/// Params:
|
|
/// Params:
|
|
/// - UploadingStatus bool flag.
|
|
/// - UploadingStatus bool flag.
|
|
ContentUploadingStatusUpdated(UploadingStatus),
|
|
ContentUploadingStatusUpdated(UploadingStatus),
|
|
|
|
+
|
|
|
|
+ /// Emits when the global voucher size limit is updated.
|
|
|
|
+ /// Params:
|
|
|
|
+ /// - New limit
|
|
|
|
+ GlobalVoucherSizeLimitUpdated(u64),
|
|
|
|
+
|
|
|
|
+ /// Emits when the global voucher objects limit is updated.
|
|
|
|
+ /// Params:
|
|
|
|
+ /// - New limit
|
|
|
|
+ GlobalVoucherObjectsLimitUpdated(u64),
|
|
|
|
+
|
|
|
|
+ /// Emits when the size limit upper bound is updated.
|
|
|
|
+ /// Params:
|
|
|
|
+ /// - New Upper bound
|
|
|
|
+ VoucherSizeLimitUpperBoundUpdated(u64),
|
|
|
|
+
|
|
|
|
+ /// Emits when the objects limit upper bound is updated.
|
|
|
|
+ /// Params:
|
|
|
|
+ /// - New Upper bound
|
|
|
|
+ VoucherObjectsLimitUpperBoundUpdated(u64),
|
|
|
|
+
|
|
|
|
+ /// Emits when the lead sets a new default voucher
|
|
|
|
+ /// Params:
|
|
|
|
+ /// - New size limit
|
|
|
|
+ /// - New objects limit
|
|
|
|
+ DefaultVoucherUpdated(u64, u64),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -360,14 +440,8 @@ decl_module! {
|
|
|
|
|
|
Self::ensure_content_is_valid(&content)?;
|
|
Self::ensure_content_is_valid(&content)?;
|
|
|
|
|
|
- let owner_voucher = Self::get_voucher(&owner);
|
|
|
|
-
|
|
|
|
- // Ensure owner voucher constraints satisfied.
|
|
|
|
- // Calculate upload voucher delta
|
|
|
|
- let upload_voucher_delta = Self::ensure_owner_voucher_constraints_satisfied(owner_voucher, &content)?;
|
|
|
|
-
|
|
|
|
- // Ensure global voucher constraints satisfied.
|
|
|
|
- Self::ensure_global_voucher_constraints_satisfied(upload_voucher_delta)?;
|
|
|
|
|
|
+ // Ensure owner and global voucher constraints satisfied.
|
|
|
|
+ let (new_owner_voucher, new_global_voucher) = Self::ensure_voucher_constraints_satisfied(&owner, &content)?;
|
|
|
|
|
|
let liaison = T::StorageProviderHelper::get_random_storage_provider()?;
|
|
let liaison = T::StorageProviderHelper::get_random_storage_provider()?;
|
|
|
|
|
|
@@ -375,8 +449,13 @@ decl_module! {
|
|
// == MUTATION SAFE ==
|
|
// == MUTATION SAFE ==
|
|
//
|
|
//
|
|
|
|
|
|
- // Let's create the entry then
|
|
|
|
- Self::upload_content(owner_voucher, upload_voucher_delta, liaison, content.clone(), owner.clone());
|
|
|
|
|
|
+ // Updade or create owner voucher.
|
|
|
|
+ <Vouchers<T>>::insert(&owner, new_owner_voucher);
|
|
|
|
+
|
|
|
|
+ // Update global voucher
|
|
|
|
+ <GlobalVoucher>::put(new_global_voucher);
|
|
|
|
+
|
|
|
|
+ Self::upload_content(liaison, content.clone(), owner.clone());
|
|
|
|
|
|
Self::deposit_event(RawEvent::ContentAdded(content, owner));
|
|
Self::deposit_event(RawEvent::ContentAdded(content, owner));
|
|
}
|
|
}
|
|
@@ -395,68 +474,181 @@ decl_module! {
|
|
// Ensure content under given content ids can be successfully removed
|
|
// Ensure content under given content ids can be successfully removed
|
|
let content = Self::ensure_content_can_be_removed(&content_ids, &owner)?;
|
|
let content = Self::ensure_content_can_be_removed(&content_ids, &owner)?;
|
|
|
|
|
|
|
|
+ let owner_voucher = Self::get_voucher(&owner);
|
|
|
|
+ let removal_voucher = Self::calculate_content_voucher(content);
|
|
|
|
+ let new_owner_voucher = owner_voucher.release_voucher::<T>(removal_voucher)?;
|
|
|
|
+ let new_global_voucher = Self::global_voucher().release_voucher::<T>(removal_voucher)?;
|
|
|
|
+
|
|
//
|
|
//
|
|
// == MUTATION SAFE ==
|
|
// == MUTATION SAFE ==
|
|
//
|
|
//
|
|
|
|
|
|
- // Let's remove a content
|
|
|
|
- Self::delete_content(&owner, &content_ids, content);
|
|
|
|
|
|
+ // Updade owner voucher
|
|
|
|
+ <Vouchers<T>>::insert(&owner, new_owner_voucher);
|
|
|
|
+
|
|
|
|
+ // Update global voucher
|
|
|
|
+ <GlobalVoucher>::put(new_global_voucher);
|
|
|
|
+
|
|
|
|
+ // Let's remove content
|
|
|
|
+ for content_id in &content_ids {
|
|
|
|
+ <DataByContentId<T>>::remove(content_id);
|
|
|
|
+ }
|
|
|
|
|
|
Self::deposit_event(RawEvent::ContentRemoved(content_ids, owner));
|
|
Self::deposit_event(RawEvent::ContentRemoved(content_ids, owner));
|
|
}
|
|
}
|
|
|
|
|
|
/// Updates storage object owner voucher objects limit. Requires leader privileges.
|
|
/// Updates storage object owner voucher objects limit. Requires leader privileges.
|
|
|
|
+ /// New limit cannot be less that used value.
|
|
#[weight = 10_000_000] // TODO: adjust weight
|
|
#[weight = 10_000_000] // TODO: adjust weight
|
|
pub fn update_storage_object_owner_voucher_objects_limit(
|
|
pub fn update_storage_object_owner_voucher_objects_limit(
|
|
origin,
|
|
origin,
|
|
- abstract_owner: ObjectOwner<T>,
|
|
|
|
|
|
+ object_owner: ObjectOwner<T>,
|
|
new_voucher_objects_limit: u64
|
|
new_voucher_objects_limit: u64
|
|
) {
|
|
) {
|
|
<StorageWorkingGroup<T>>::ensure_origin_is_active_leader(origin)?;
|
|
<StorageWorkingGroup<T>>::ensure_origin_is_active_leader(origin)?;
|
|
- ensure!(new_voucher_objects_limit <= Self::voucher_objects_limit_upper_bound(), Error::<T>::VoucherObjectsLimitUpperBoundExceeded);
|
|
|
|
|
|
+ ensure!(
|
|
|
|
+ new_voucher_objects_limit <= Self::voucher_objects_limit_upper_bound(),
|
|
|
|
+ Error::<T>::VoucherObjectsLimitUpperBoundExceeded
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ let mut voucher = Self::get_voucher(&object_owner);
|
|
|
|
+
|
|
|
|
+ voucher.set_new_objects_limit::<T>(new_voucher_objects_limit)?;
|
|
|
|
|
|
//
|
|
//
|
|
// == MUTATION SAFE ==
|
|
// == MUTATION SAFE ==
|
|
//
|
|
//
|
|
|
|
|
|
- if <Vouchers<T>>::contains_key(&abstract_owner) {
|
|
|
|
- <Vouchers<T>>::mutate(&abstract_owner, |voucher| {
|
|
|
|
- voucher.set_new_objects_limit(new_voucher_objects_limit);
|
|
|
|
- });
|
|
|
|
- } else {
|
|
|
|
- let mut voucher = Self::default_voucher();
|
|
|
|
- voucher.set_new_objects_limit(new_voucher_objects_limit);
|
|
|
|
- <Vouchers<T>>::insert(&abstract_owner, voucher);
|
|
|
|
- };
|
|
|
|
|
|
+ <Vouchers<T>>::insert(&object_owner, voucher);
|
|
|
|
|
|
- Self::deposit_event(RawEvent::StorageObjectOwnerVoucherObjectsLimitUpdated(abstract_owner, new_voucher_objects_limit));
|
|
|
|
|
|
+ Self::deposit_event(RawEvent::StorageObjectOwnerVoucherObjectsLimitUpdated(object_owner, new_voucher_objects_limit));
|
|
}
|
|
}
|
|
|
|
|
|
/// Updates storage object owner voucher size limit. Requires leader privileges.
|
|
/// Updates storage object owner voucher size limit. Requires leader privileges.
|
|
|
|
+ /// New limit cannot be less that used value.
|
|
#[weight = 10_000_000] // TODO: adjust weight
|
|
#[weight = 10_000_000] // TODO: adjust weight
|
|
pub fn update_storage_object_owner_voucher_size_limit(
|
|
pub fn update_storage_object_owner_voucher_size_limit(
|
|
origin,
|
|
origin,
|
|
- abstract_owner: ObjectOwner<T>,
|
|
|
|
|
|
+ object_owner: ObjectOwner<T>,
|
|
new_voucher_size_limit: u64
|
|
new_voucher_size_limit: u64
|
|
) {
|
|
) {
|
|
<StorageWorkingGroup<T>>::ensure_origin_is_active_leader(origin)?;
|
|
<StorageWorkingGroup<T>>::ensure_origin_is_active_leader(origin)?;
|
|
- ensure!(new_voucher_size_limit <= Self::voucher_size_limit_upper_bound(), Error::<T>::VoucherSizeLimitUpperBoundExceeded);
|
|
|
|
|
|
+ ensure!(
|
|
|
|
+ new_voucher_size_limit <= Self::voucher_size_limit_upper_bound(),
|
|
|
|
+ Error::<T>::VoucherSizeLimitUpperBoundExceeded
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ let mut voucher = Self::get_voucher(&object_owner);
|
|
|
|
+
|
|
|
|
+ voucher.set_new_size_limit::<T>(new_voucher_size_limit)?;
|
|
|
|
|
|
//
|
|
//
|
|
// == MUTATION SAFE ==
|
|
// == MUTATION SAFE ==
|
|
//
|
|
//
|
|
|
|
|
|
- if <Vouchers<T>>::contains_key(&abstract_owner) {
|
|
|
|
- <Vouchers<T>>::mutate(&abstract_owner, |voucher| {
|
|
|
|
- voucher.set_new_size_limit(new_voucher_size_limit);
|
|
|
|
- });
|
|
|
|
- } else {
|
|
|
|
- let mut voucher = Self::default_voucher();
|
|
|
|
- voucher.set_new_size_limit(new_voucher_size_limit);
|
|
|
|
- <Vouchers<T>>::insert(&abstract_owner, voucher);
|
|
|
|
- };
|
|
|
|
|
|
+ <Vouchers<T>>::insert(&object_owner, voucher);
|
|
|
|
+
|
|
|
|
+ Self::deposit_event(RawEvent::StorageObjectOwnerVoucherSizeLimitUpdated(object_owner, new_voucher_size_limit));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// Sets global voucher size limit. Requires root privileges.
|
|
|
|
+ /// New limit cannot be less that used value.
|
|
|
|
+ #[weight = 10_000_000] // TODO: adjust weight
|
|
|
|
+ pub fn set_global_voucher_size_limit(
|
|
|
|
+ origin,
|
|
|
|
+ new_size_limit: u64
|
|
|
|
+ ) {
|
|
|
|
+ ensure_root(origin)?;
|
|
|
|
+
|
|
|
|
+ let mut voucher = Self::global_voucher();
|
|
|
|
+ voucher.set_new_size_limit::<T>(new_size_limit)?;
|
|
|
|
+
|
|
|
|
+ //
|
|
|
|
+ // == MUTATION SAFE ==
|
|
|
|
+ //
|
|
|
|
+
|
|
|
|
+ GlobalVoucher::put(voucher);
|
|
|
|
+
|
|
|
|
+ Self::deposit_event(RawEvent::GlobalVoucherSizeLimitUpdated(new_size_limit));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// Sets global voucher objects limit. Requires root privileges.
|
|
|
|
+ /// New limit cannot be less that used value.
|
|
|
|
+ #[weight = 10_000_000] // TODO: adjust weight
|
|
|
|
+ pub fn set_global_voucher_objects_limit(
|
|
|
|
+ origin,
|
|
|
|
+ new_objects_limit: u64
|
|
|
|
+ ) {
|
|
|
|
+ ensure_root(origin)?;
|
|
|
|
+
|
|
|
|
+ let mut voucher = Self::global_voucher();
|
|
|
|
+ voucher.set_new_objects_limit::<T>(new_objects_limit)?;
|
|
|
|
+
|
|
|
|
+ //
|
|
|
|
+ // == MUTATION SAFE ==
|
|
|
|
+ //
|
|
|
|
+
|
|
|
|
+ GlobalVoucher::put(voucher);
|
|
|
|
+
|
|
|
|
+ Self::deposit_event(RawEvent::GlobalVoucherObjectsLimitUpdated(new_objects_limit));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// Sets VoucherSizeLimitUpperBound. Requires root privileges.
|
|
|
|
+ #[weight = 10_000_000] // TODO: adjust weight
|
|
|
|
+ pub fn set_voucher_size_limit_upper_bound(
|
|
|
|
+ origin,
|
|
|
|
+ new_upper_bound: u64
|
|
|
|
+ ) {
|
|
|
|
+ ensure_root(origin)?;
|
|
|
|
+
|
|
|
|
+ //
|
|
|
|
+ // == MUTATION SAFE ==
|
|
|
|
+ //
|
|
|
|
+
|
|
|
|
+ VoucherSizeLimitUpperBound::put(new_upper_bound);
|
|
|
|
|
|
- Self::deposit_event(RawEvent::StorageObjectOwnerVoucherSizeLimitUpdated(abstract_owner, new_voucher_size_limit));
|
|
|
|
|
|
+ Self::deposit_event(RawEvent::VoucherSizeLimitUpperBoundUpdated(new_upper_bound));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// Sets VoucherObjectsLimitUpperBound. Requires root privileges.
|
|
|
|
+ #[weight = 10_000_000] // TODO: adjust weight
|
|
|
|
+ pub fn set_voucher_objects_limit_upper_bound(
|
|
|
|
+ origin,
|
|
|
|
+ new_upper_bound: u64
|
|
|
|
+ ) {
|
|
|
|
+ ensure_root(origin)?;
|
|
|
|
+
|
|
|
|
+ //
|
|
|
|
+ // == MUTATION SAFE ==
|
|
|
|
+ //
|
|
|
|
+
|
|
|
|
+ VoucherObjectsLimitUpperBound::put(new_upper_bound);
|
|
|
|
+
|
|
|
|
+ Self::deposit_event(RawEvent::VoucherObjectsLimitUpperBoundUpdated(new_upper_bound));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// Set the default owner voucher
|
|
|
|
+ #[weight = 10_000_000] // TODO: adjust weight
|
|
|
|
+ pub fn set_default_voucher(
|
|
|
|
+ origin,
|
|
|
|
+ size_limit: u64,
|
|
|
|
+ objects_limit: u64
|
|
|
|
+ ) {
|
|
|
|
+ <StorageWorkingGroup<T>>::ensure_origin_is_active_leader(origin)?;
|
|
|
|
+ // constrain to upper bounds
|
|
|
|
+ ensure!(
|
|
|
|
+ size_limit <= Self::voucher_size_limit_upper_bound(),
|
|
|
|
+ Error::<T>::VoucherSizeLimitUpperBoundExceeded
|
|
|
|
+ );
|
|
|
|
+ ensure!(
|
|
|
|
+ objects_limit <= Self::voucher_objects_limit_upper_bound(),
|
|
|
|
+ Error::<T>::VoucherObjectsLimitUpperBoundExceeded
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ // == MUTATION SAFE ==
|
|
|
|
+ DefaultVoucher::put(Voucher::new(size_limit, objects_limit));
|
|
|
|
+
|
|
|
|
+ Self::deposit_event(RawEvent::DefaultVoucherUpdated(size_limit, objects_limit));
|
|
}
|
|
}
|
|
|
|
|
|
/// Storage provider accepts a content. Requires signed storage provider account and its id.
|
|
/// Storage provider accepts a content. Requires signed storage provider account and its id.
|
|
@@ -557,37 +749,6 @@ impl<T: Trait> Module<T> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
- // Ensure owner voucher constraints satisfied, returns total object length and total size voucher delta for this upload.
|
|
|
|
- fn ensure_owner_voucher_constraints_satisfied(
|
|
|
|
- owner_voucher: Voucher,
|
|
|
|
- content: &[ContentParameters<T::ContentId, DataObjectTypeId<T>>],
|
|
|
|
- ) -> Result<Delta, Error<T>> {
|
|
|
|
- let owner_voucher_delta = owner_voucher.calculate_delta();
|
|
|
|
-
|
|
|
|
- // Ensure total content length is less or equal then available per given owner voucher
|
|
|
|
- let content_length = content.len() as u64;
|
|
|
|
-
|
|
|
|
- ensure!(
|
|
|
|
- owner_voucher_delta.objects >= content_length,
|
|
|
|
- Error::<T>::VoucherObjectsLimitExceeded
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- // Ensure total content size is less or equal then available per given owner voucher
|
|
|
|
- let content_size = content
|
|
|
|
- .iter()
|
|
|
|
- .fold(0, |total_size, content| total_size + content.size);
|
|
|
|
-
|
|
|
|
- ensure!(
|
|
|
|
- owner_voucher_delta.size >= content_size,
|
|
|
|
- Error::<T>::VoucherSizeLimitExceeded
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- Ok(Delta {
|
|
|
|
- size: content_size,
|
|
|
|
- objects: content_length,
|
|
|
|
- })
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
// Ensure content under given content ids can be successfully removed
|
|
// Ensure content under given content ids can be successfully removed
|
|
fn ensure_content_can_be_removed(
|
|
fn ensure_content_can_be_removed(
|
|
content_ids: &[T::ContentId],
|
|
content_ids: &[T::ContentId],
|
|
@@ -603,7 +764,7 @@ impl<T: Trait> Module<T> {
|
|
Ok(content)
|
|
Ok(content)
|
|
}
|
|
}
|
|
|
|
|
|
- // Calculates content voucher delta
|
|
|
|
|
|
+ /// Calculates content voucher delta of existing data objects
|
|
fn calculate_content_voucher(content: Vec<DataObject<T>>) -> Delta {
|
|
fn calculate_content_voucher(content: Vec<DataObject<T>>) -> Delta {
|
|
let content_length = content.len() as u64;
|
|
let content_length = content.len() as u64;
|
|
|
|
|
|
@@ -617,27 +778,36 @@ impl<T: Trait> Module<T> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // Ensures global voucher constraints satisfied.
|
|
|
|
- fn ensure_global_voucher_constraints_satisfied(upload_voucher_delta: Delta) -> DispatchResult {
|
|
|
|
- let global_voucher_voucher = Self::global_voucher().calculate_delta();
|
|
|
|
|
|
+ /// Calculates content voucher delta for new content being added
|
|
|
|
+ fn calculate_new_content_voucher(
|
|
|
|
+ content: &[ContentParameters<T::ContentId, DataObjectTypeId<T>>],
|
|
|
|
+ ) -> Delta {
|
|
|
|
+ let objects = content.len() as u64;
|
|
|
|
+ let size = content
|
|
|
|
+ .iter()
|
|
|
|
+ .fold(0, |total_size, content| total_size + content.size);
|
|
|
|
+
|
|
|
|
+ Delta { size, objects }
|
|
|
|
+ }
|
|
|
|
|
|
- ensure!(
|
|
|
|
- global_voucher_voucher.objects >= upload_voucher_delta.objects,
|
|
|
|
- Error::<T>::GlobalVoucherObjectsLimitExceeded
|
|
|
|
- );
|
|
|
|
|
|
+ /// Ensures new content satisfies both owner and global vouchers. Returns new vouchers
|
|
|
|
+ /// if constraints are satisfied, Error otherwise.
|
|
|
|
+ fn ensure_voucher_constraints_satisfied(
|
|
|
|
+ owner: &ObjectOwner<T>,
|
|
|
|
+ content: &[ContentParameters<T::ContentId, DataObjectTypeId<T>>],
|
|
|
|
+ ) -> Result<(Voucher, Voucher), Error<T>> {
|
|
|
|
+ let owner_voucher = Self::get_voucher(owner);
|
|
|
|
+ let global_voucher = Self::global_voucher();
|
|
|
|
+ let content_voucher_delta = Self::calculate_new_content_voucher(content);
|
|
|
|
|
|
- ensure!(
|
|
|
|
- global_voucher_voucher.size >= upload_voucher_delta.size,
|
|
|
|
- Error::<T>::GlobalVoucherSizeLimitExceeded
|
|
|
|
- );
|
|
|
|
|
|
+ let new_owner_voucher = owner_voucher.fill_voucher::<T>(content_voucher_delta)?;
|
|
|
|
+ let new_global_voucher = global_voucher.fill_voucher::<T>(content_voucher_delta)?;
|
|
|
|
|
|
- Ok(())
|
|
|
|
|
|
+ Ok((new_owner_voucher, new_global_voucher))
|
|
}
|
|
}
|
|
|
|
|
|
// Complete content upload, update vouchers
|
|
// Complete content upload, update vouchers
|
|
fn upload_content(
|
|
fn upload_content(
|
|
- owner_voucher: Voucher,
|
|
|
|
- upload_voucher_delta: Delta,
|
|
|
|
liaison: StorageProviderId<T>,
|
|
liaison: StorageProviderId<T>,
|
|
multi_content: Vec<ContentParameters<T::ContentId, DataObjectTypeId<T>>>,
|
|
multi_content: Vec<ContentParameters<T::ContentId, DataObjectTypeId<T>>>,
|
|
owner: ObjectOwner<T>,
|
|
owner: ObjectOwner<T>,
|
|
@@ -655,33 +825,6 @@ impl<T: Trait> Module<T> {
|
|
|
|
|
|
<DataByContentId<T>>::insert(content.content_id, data);
|
|
<DataByContentId<T>>::insert(content.content_id, data);
|
|
}
|
|
}
|
|
-
|
|
|
|
- // Updade or create owner voucher.
|
|
|
|
- <Vouchers<T>>::insert(owner, owner_voucher.fill_voucher(upload_voucher_delta));
|
|
|
|
-
|
|
|
|
- // Update global voucher
|
|
|
|
- <GlobalVoucher>::put(Self::global_voucher().fill_voucher(upload_voucher_delta));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Complete content removal
|
|
|
|
- fn delete_content(
|
|
|
|
- owner: &ObjectOwner<T>,
|
|
|
|
- content_ids: &[T::ContentId],
|
|
|
|
- content: Vec<DataObject<T>>,
|
|
|
|
- ) {
|
|
|
|
- let removal_voucher = Self::calculate_content_voucher(content);
|
|
|
|
-
|
|
|
|
- for content_id in content_ids {
|
|
|
|
- <DataByContentId<T>>::remove(content_id);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Updade owner voucher.
|
|
|
|
- <Vouchers<T>>::mutate(owner, |owner_voucher| {
|
|
|
|
- owner_voucher.release_voucher(removal_voucher)
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- // Update global voucher
|
|
|
|
- <GlobalVoucher>::put(Self::global_voucher().release_voucher(removal_voucher));
|
|
|
|
}
|
|
}
|
|
|
|
|
|
fn ensure_content_is_valid(
|
|
fn ensure_content_is_valid(
|
|
@@ -759,15 +902,9 @@ impl<T: Trait> common::storage::StorageSystem<T> for Module<T> {
|
|
|
|
|
|
Self::ensure_uploading_is_not_blocked()?;
|
|
Self::ensure_uploading_is_not_blocked()?;
|
|
|
|
|
|
- let owner_voucher = Self::get_voucher(&owner);
|
|
|
|
-
|
|
|
|
- // Ensure owner voucher constraints satisfied.
|
|
|
|
- // Calculate upload voucher
|
|
|
|
- let upload_voucher =
|
|
|
|
- Self::ensure_owner_voucher_constraints_satisfied(owner_voucher, &content)?;
|
|
|
|
-
|
|
|
|
- // Ensure global voucher constraints satisfied.
|
|
|
|
- Self::ensure_global_voucher_constraints_satisfied(upload_voucher)?;
|
|
|
|
|
|
+ // Ensure owner and global vouchers constraints satisfied.
|
|
|
|
+ let (new_owner_voucher, new_global_voucher) =
|
|
|
|
+ Self::ensure_voucher_constraints_satisfied(&owner, &content)?;
|
|
|
|
|
|
let liaison = T::StorageProviderHelper::get_random_storage_provider()?;
|
|
let liaison = T::StorageProviderHelper::get_random_storage_provider()?;
|
|
|
|
|
|
@@ -775,9 +912,13 @@ impl<T: Trait> common::storage::StorageSystem<T> for Module<T> {
|
|
// == MUTATION SAFE ==
|
|
// == MUTATION SAFE ==
|
|
//
|
|
//
|
|
|
|
|
|
- // Let's create the entry then
|
|
|
|
|
|
+ // Updade or create owner voucher.
|
|
|
|
+ <Vouchers<T>>::insert(&owner, new_owner_voucher);
|
|
|
|
+
|
|
|
|
+ // Update global voucher
|
|
|
|
+ <GlobalVoucher>::put(new_global_voucher);
|
|
|
|
|
|
- Self::upload_content(owner_voucher, upload_voucher, liaison, content, owner);
|
|
|
|
|
|
+ Self::upload_content(liaison, content, owner);
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
@@ -788,12 +929,26 @@ impl<T: Trait> common::storage::StorageSystem<T> for Module<T> {
|
|
// Ensure content under given content ids can be successfully removed
|
|
// Ensure content under given content ids can be successfully removed
|
|
let content = Self::ensure_content_can_be_removed(content_ids, owner)?;
|
|
let content = Self::ensure_content_can_be_removed(content_ids, owner)?;
|
|
|
|
|
|
|
|
+ let owner_voucher = Self::get_voucher(&owner);
|
|
|
|
+ let removal_voucher = Self::calculate_content_voucher(content);
|
|
|
|
+ let new_owner_voucher = owner_voucher.release_voucher::<T>(removal_voucher)?;
|
|
|
|
+ let new_global_voucher = Self::global_voucher().release_voucher::<T>(removal_voucher)?;
|
|
|
|
+
|
|
//
|
|
//
|
|
// == MUTATION SAFE ==
|
|
// == MUTATION SAFE ==
|
|
//
|
|
//
|
|
|
|
|
|
- // Let's remove a content
|
|
|
|
- Self::delete_content(owner, content_ids, content);
|
|
|
|
|
|
+ // Updade owner voucher.
|
|
|
|
+ <Vouchers<T>>::insert(owner, new_owner_voucher);
|
|
|
|
+
|
|
|
|
+ // Update global voucher
|
|
|
|
+ <GlobalVoucher>::put(new_global_voucher);
|
|
|
|
+
|
|
|
|
+ // Let's remove content
|
|
|
|
+ for content_id in content_ids {
|
|
|
|
+ <DataByContentId<T>>::remove(content_id);
|
|
|
|
+ }
|
|
|
|
+
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
@@ -804,10 +959,9 @@ impl<T: Trait> common::storage::StorageSystem<T> for Module<T> {
|
|
Self::ensure_uploading_is_not_blocked()?;
|
|
Self::ensure_uploading_is_not_blocked()?;
|
|
|
|
|
|
T::StorageProviderHelper::get_random_storage_provider()?;
|
|
T::StorageProviderHelper::get_random_storage_provider()?;
|
|
- let owner_voucher = Self::get_voucher(&owner);
|
|
|
|
|
|
|
|
- // Ensure owner voucher constraints satisfied.
|
|
|
|
- Self::ensure_owner_voucher_constraints_satisfied(owner_voucher, &content)?;
|
|
|
|
|
|
+ let _ = Self::ensure_voucher_constraints_satisfied(&owner, &content)?;
|
|
|
|
+
|
|
Self::ensure_content_is_valid(&content)
|
|
Self::ensure_content_is_valid(&content)
|
|
}
|
|
}
|
|
|
|
|