lib.rs 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309
  1. //! # Storage module
  2. //! Storage module for the Joystream platform. Version 2.
  3. // Ensure we're `no_std` when compiling for Wasm.
  4. #![cfg_attr(not(feature = "std"), no_std)]
  5. #![warn(missing_docs)]
  6. // TODO: Remove old Storage pallet.
  7. // TODO: add module comment
  8. // TODO: make public methods as root extrinsics to enable storage-node dev mode.
  9. // TODO: make public methods "weight-ready".
  10. // TODO: review extrinsic, parameters and error names.
  11. #[cfg(test)]
  12. mod tests;
  13. #[cfg(feature = "runtime-benchmarks")]
  14. mod benchmarking;
  15. mod bag_manager;
  16. pub(crate) mod storage_bucket_picker;
  17. use codec::{Codec, Decode, Encode};
  18. use frame_support::dispatch::{DispatchError, DispatchResult};
  19. use frame_support::traits::{Currency, ExistenceRequirement, Get, Randomness};
  20. use frame_support::{decl_error, decl_event, decl_module, decl_storage, ensure, Parameter};
  21. #[cfg(feature = "std")]
  22. use serde::{Deserialize, Serialize};
  23. use sp_arithmetic::traits::{BaseArithmetic, One, Zero};
  24. use sp_runtime::traits::{AccountIdConversion, MaybeSerialize, Member, Saturating};
  25. use sp_runtime::{ModuleId, SaturatedConversion};
  26. use sp_std::collections::btree_map::BTreeMap;
  27. use sp_std::collections::btree_set::BTreeSet;
  28. use sp_std::iter;
  29. use sp_std::marker::PhantomData;
  30. use sp_std::vec::Vec;
  31. use common::constraints::BoundedValueConstraint;
  32. use common::origin::ActorOriginValidator;
  33. use common::working_group::WorkingGroup;
  34. use bag_manager::BagManager;
  35. use storage_bucket_picker::StorageBucketPicker;
  36. /// Public interface for the storage module.
  37. pub trait DataObjectStorage<T: Trait> {
  38. /// Validates upload parameters and conditions (like global uploading block).
  39. /// Validates voucher usage for affected buckets.
  40. fn can_upload_data_objects(params: &UploadParameters<T>) -> DispatchResult;
  41. /// Upload new data objects.
  42. fn upload_data_objects(params: UploadParameters<T>) -> DispatchResult;
  43. /// Validates moving objects parameters.
  44. /// Validates voucher usage for affected buckets.
  45. fn can_move_data_objects(
  46. src_bag_id: &BagId<T>,
  47. dest_bag_id: &BagId<T>,
  48. objects: &BTreeSet<T::DataObjectId>,
  49. ) -> DispatchResult;
  50. /// Move data objects to a new bag.
  51. fn move_data_objects(
  52. src_bag_id: BagId<T>,
  53. dest_bag_id: BagId<T>,
  54. objects: BTreeSet<T::DataObjectId>,
  55. ) -> DispatchResult;
  56. /// Validates `delete_data_objects` parameters.
  57. /// Validates voucher usage for affected buckets.
  58. fn can_delete_data_objects(
  59. bag_id: &BagId<T>,
  60. objects: &BTreeSet<T::DataObjectId>,
  61. ) -> DispatchResult;
  62. /// Delete storage objects. Transfer deletion prize to the provided account.
  63. fn delete_data_objects(
  64. deletion_prize_account_id: T::AccountId,
  65. bag_id: BagId<T>,
  66. objects: BTreeSet<T::DataObjectId>,
  67. ) -> DispatchResult;
  68. /// Delete dynamic bag. Updates related storage bucket vouchers.
  69. fn delete_dynamic_bag(
  70. deletion_prize_account_id: T::AccountId,
  71. bag_id: DynamicBagId<T>,
  72. ) -> DispatchResult;
  73. /// Validates `delete_dynamic_bag` parameters and conditions.
  74. fn can_delete_dynamic_bag(bag_id: &DynamicBagId<T>) -> DispatchResult;
  75. /// Creates dynamic bag. BagId should provide the caller.
  76. fn create_dynamic_bag(bag_id: DynamicBagId<T>) -> DispatchResult;
  77. /// Validates `create_dynamic_bag` parameters and conditions.
  78. fn can_create_dynamic_bag(bag_id: &DynamicBagId<T>) -> DispatchResult;
  79. }
  80. /// Storage trait.
  81. pub trait Trait: frame_system::Trait + balances::Trait + membership::Trait {
  82. /// Storage event type.
  83. type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
  84. /// Data object ID type.
  85. type DataObjectId: Parameter
  86. + Member
  87. + BaseArithmetic
  88. + Codec
  89. + Default
  90. + Copy
  91. + MaybeSerialize
  92. + PartialEq;
  93. /// Storage bucket ID type.
  94. type StorageBucketId: Parameter
  95. + Member
  96. + BaseArithmetic
  97. + Codec
  98. + Default
  99. + Copy
  100. + MaybeSerialize
  101. + PartialEq;
  102. /// Distribution bucket ID type.
  103. type DistributionBucketId: Parameter
  104. + Member
  105. + BaseArithmetic
  106. + Codec
  107. + Default
  108. + Copy
  109. + MaybeSerialize
  110. + PartialEq;
  111. /// Channel ID type (part of the dynamic bag ID).
  112. type ChannelId: Parameter
  113. + Member
  114. + BaseArithmetic
  115. + Codec
  116. + Default
  117. + Copy
  118. + MaybeSerialize
  119. + PartialEq;
  120. /// Defines max allowed storage bucket number.
  121. type MaxStorageBucketNumber: Get<u64>;
  122. /// Defines max number of data objects per bag.
  123. type MaxNumberOfDataObjectsPerBag: Get<u64>;
  124. /// Defines a prize for a data object deletion.
  125. type DataObjectDeletionPrize: Get<BalanceOf<Self>>;
  126. /// Defines maximum size of the "hash blacklist" collection.
  127. type BlacklistSizeLimit: Get<u64>;
  128. /// The module id, used for deriving its sovereign account ID.
  129. type ModuleId: Get<ModuleId>;
  130. /// Validates member id and origin combination.
  131. type MemberOriginValidator: ActorOriginValidator<Self::Origin, MemberId<Self>, Self::AccountId>;
  132. /// "Storage buckets per bag" value constraint.
  133. type StorageBucketsPerBagValueConstraint: Get<StorageBucketsPerBagValueConstraint>;
  134. /// Defines the default dynamic bag creation policy for members.
  135. type DefaultMemberDynamicBagCreationPolicy: Get<DynamicBagCreationPolicy>;
  136. /// Defines the default dynamic bag creation policy for channels.
  137. type DefaultChannelDynamicBagCreationPolicy: Get<DynamicBagCreationPolicy>;
  138. /// Defines max random iteration number (eg.: when picking the storage buckets).
  139. type MaxRandomIterationNumber: Get<u64>;
  140. /// Something that provides randomness in the runtime.
  141. type Randomness: Randomness<Self::Hash>;
  142. /// Demand the working group leader authorization.
  143. /// TODO: Refactor after merging with the Olympia release.
  144. fn ensure_working_group_leader_origin(origin: Self::Origin) -> DispatchResult;
  145. /// Validate origin for the worker.
  146. /// TODO: Refactor after merging with the Olympia release.
  147. fn ensure_worker_origin(origin: Self::Origin, worker_id: WorkerId<Self>) -> DispatchResult;
  148. /// Validate worker existence.
  149. /// TODO: Refactor after merging with the Olympia release.
  150. fn ensure_worker_exists(worker_id: &WorkerId<Self>) -> DispatchResult;
  151. }
  152. /// Operations with local pallet account.
  153. pub trait ModuleAccount<T: balances::Trait> {
  154. /// The module id, used for deriving its sovereign account ID.
  155. type ModuleId: Get<ModuleId>;
  156. /// The account ID of the module account.
  157. fn module_account_id() -> T::AccountId {
  158. Self::ModuleId::get().into_sub_account(Vec::<u8>::new())
  159. }
  160. /// Transfer tokens from the module account to the destination account (spends from
  161. /// module account).
  162. fn withdraw(dest_account_id: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {
  163. <Balances<T> as Currency<T::AccountId>>::transfer(
  164. &Self::module_account_id(),
  165. dest_account_id,
  166. amount,
  167. ExistenceRequirement::AllowDeath,
  168. )
  169. }
  170. /// Transfer tokens from the destination account to the module account (fills module account).
  171. fn deposit(src_account_id: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {
  172. <Balances<T> as Currency<T::AccountId>>::transfer(
  173. src_account_id,
  174. &Self::module_account_id(),
  175. amount,
  176. ExistenceRequirement::AllowDeath,
  177. )
  178. }
  179. /// Displays usable balance for the module account.
  180. fn usable_balance() -> BalanceOf<T> {
  181. <Balances<T>>::usable_balance(&Self::module_account_id())
  182. }
  183. }
  184. /// Implementation of the ModuleAccountHandler.
  185. pub struct ModuleAccountHandler<T: balances::Trait, ModId: Get<ModuleId>> {
  186. /// Phantom marker for the trait.
  187. trait_marker: PhantomData<T>,
  188. /// Phantom marker for the module id type.
  189. module_id_marker: PhantomData<ModId>,
  190. }
  191. impl<T: balances::Trait, ModId: Get<ModuleId>> ModuleAccount<T> for ModuleAccountHandler<T, ModId> {
  192. type ModuleId = ModId;
  193. }
  194. /// Holds parameter values impacting how exactly the creation of a new dynamic bag occurs,
  195. /// and there is one such policy for each type of dynamic bag.
  196. /// It describes how many storage buckets should store the bag.
  197. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  198. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  199. pub struct DynamicBagCreationPolicy {
  200. /// The number of storage buckets which should replicate the new bag.
  201. pub number_of_storage_buckets: u64,
  202. }
  203. impl DynamicBagCreationPolicy {
  204. // Verifies non-zero number of storage buckets.
  205. pub(crate) fn no_storage_buckets_required(&self) -> bool {
  206. self.number_of_storage_buckets == 0
  207. }
  208. }
  209. /// "Storage buckets per bag" value constraint type.
  210. pub type StorageBucketsPerBagValueConstraint = BoundedValueConstraint<u64>;
  211. /// Local module account handler.
  212. pub type StorageTreasury<T> = ModuleAccountHandler<T, <T as Trait>::ModuleId>;
  213. /// IPFS hash type alias.
  214. pub type ContentId = Vec<u8>;
  215. // Alias for the Substrate balances pallet.
  216. type Balances<T> = balances::Module<T>;
  217. /// Alias for the member id.
  218. pub type MemberId<T> = <T as membership::Trait>::MemberId;
  219. /// Type identifier for worker role, which must be same as membership actor identifier
  220. pub type WorkerId<T> = <T as membership::Trait>::ActorId;
  221. /// Balance alias for `balances` module.
  222. pub type BalanceOf<T> = <T as balances::Trait>::Balance;
  223. /// The fundamental concept in the system, which represents single static binary object in the
  224. /// system. The main goal of the system is to retain an index of all such objects, including who
  225. /// owns them, and information about what actors are currently tasked with storing and distributing
  226. /// them to end users. The system is unaware of the underlying content represented by such an
  227. /// object, as it is used by different parts of the Joystream system.
  228. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  229. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  230. pub struct DataObject<Balance> {
  231. /// Defines whether the data object was accepted by a liaison.
  232. pub accepted: bool,
  233. /// A reward for the data object deletion.
  234. pub deletion_prize: Balance,
  235. /// Object size in bytes.
  236. pub size: u64,
  237. }
  238. /// Type alias for the StaticBagObject.
  239. pub type StaticBag<T> = StaticBagObject<
  240. <T as Trait>::DataObjectId,
  241. <T as Trait>::StorageBucketId,
  242. <T as Trait>::DistributionBucketId,
  243. BalanceOf<T>,
  244. >;
  245. /// Static bag container.
  246. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  247. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  248. pub struct StaticBagObject<
  249. DataObjectId: Ord,
  250. StorageBucketId: Ord,
  251. DistributionBucketId: Ord,
  252. Balance,
  253. > {
  254. /// Associated data objects.
  255. pub objects: BTreeMap<DataObjectId, DataObject<Balance>>,
  256. /// Associated storage buckets.
  257. pub stored_by: BTreeSet<StorageBucketId>,
  258. /// Associated distribution buckets.
  259. pub distributed_by: BTreeSet<DistributionBucketId>,
  260. }
  261. impl<DataObjectId: Ord, StorageBucketId: Ord, DistributionBucketId: Ord, Balance>
  262. StaticBagObject<DataObjectId, StorageBucketId, DistributionBucketId, Balance>
  263. {
  264. // Calculates total object size for static bag.
  265. pub(crate) fn objects_total_size(&self) -> u64 {
  266. self.objects.values().map(|obj| obj.size).sum()
  267. }
  268. // Calculates total objects number for static bag.
  269. pub(crate) fn objects_number(&self) -> u64 {
  270. self.objects.len().saturated_into()
  271. }
  272. }
  273. /// Parameters for the data object creation.
  274. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  275. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  276. pub struct DataObjectCreationParameters {
  277. /// Object size in bytes.
  278. pub size: u64,
  279. /// Content identifier presented as IPFS hash.
  280. pub ipfs_content_id: Vec<u8>,
  281. }
  282. /// Type alias for the BagIdType.
  283. pub type BagId<T> = BagIdType<MemberId<T>, <T as Trait>::ChannelId>;
  284. /// Identifier for a bag.
  285. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  286. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
  287. pub enum BagIdType<MemberId, ChannelId> {
  288. /// Static bag type.
  289. StaticBag(StaticBagId),
  290. /// Dynamic bag type.
  291. DynamicBag(DynamicBagIdType<MemberId, ChannelId>),
  292. }
  293. impl<MemberId, ChannelId> Default for BagIdType<MemberId, ChannelId> {
  294. fn default() -> Self {
  295. Self::StaticBag(Default::default())
  296. }
  297. }
  298. /// Define dynamic bag types.
  299. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  300. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Copy)]
  301. pub enum DynamicBagType {
  302. /// Member dynamic bag type.
  303. Member,
  304. /// Channel dynamic bag type.
  305. Channel,
  306. }
  307. impl Default for DynamicBagType {
  308. fn default() -> Self {
  309. Self::Member
  310. }
  311. }
  312. /// A type for static bags ID.
  313. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  314. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
  315. pub enum StaticBagId {
  316. /// Dedicated bag for a council.
  317. Council,
  318. /// Dedicated bag for some working group.
  319. WorkingGroup(WorkingGroup),
  320. }
  321. impl Default for StaticBagId {
  322. fn default() -> Self {
  323. Self::Council
  324. }
  325. }
  326. /// Type alias for the DynamicBagIdType.
  327. pub type DynamicBagId<T> = DynamicBagIdType<MemberId<T>, <T as Trait>::ChannelId>;
  328. /// A type for dynamic bags ID.
  329. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  330. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
  331. pub enum DynamicBagIdType<MemberId, ChannelId> {
  332. /// Dynamic bag assigned to a member.
  333. Member(MemberId),
  334. /// Dynamic bag assigned to media channel.
  335. Channel(ChannelId),
  336. }
  337. impl<MemberId: Default, ChannelId> Default for DynamicBagIdType<MemberId, ChannelId> {
  338. fn default() -> Self {
  339. Self::Member(Default::default())
  340. }
  341. }
  342. #[allow(clippy::from_over_into)] // Cannot implement From using these types.
  343. impl<MemberId: Default, ChannelId> Into<DynamicBagType> for DynamicBagIdType<MemberId, ChannelId> {
  344. fn into(self) -> DynamicBagType {
  345. match self {
  346. DynamicBagIdType::Member(_) => DynamicBagType::Member,
  347. DynamicBagIdType::Channel(_) => DynamicBagType::Channel,
  348. }
  349. }
  350. }
  351. /// Alias for the UploadParametersObject
  352. pub type UploadParameters<T> = UploadParametersObject<
  353. MemberId<T>,
  354. <T as Trait>::ChannelId,
  355. <T as frame_system::Trait>::AccountId,
  356. >;
  357. /// Data wrapper structure. Helps passing the parameters to the `upload` extrinsic.
  358. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  359. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  360. pub struct UploadParametersObject<MemberId, ChannelId, AccountId> {
  361. /// Public key used authentication in upload to liaison.
  362. pub authentication_key: Vec<u8>,
  363. /// Static or dynamic bag to upload data.
  364. pub bag_id: BagIdType<MemberId, ChannelId>,
  365. /// Data object parameters.
  366. pub object_creation_list: Vec<DataObjectCreationParameters>,
  367. /// Account for the data object deletion prize.
  368. pub deletion_prize_source_account_id: AccountId,
  369. }
  370. /// Defines storage bucket parameters.
  371. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  372. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  373. pub struct Voucher {
  374. /// Total size limit.
  375. pub size_limit: u64,
  376. /// Object number limit.
  377. pub objects_limit: u64,
  378. /// Current size.
  379. pub size_used: u64,
  380. /// Current object number.
  381. pub objects_used: u64,
  382. }
  383. // Defines whether we should increase or decrease parameters during some operation.
  384. #[derive(Clone, PartialEq, Eq, Debug, Copy)]
  385. enum OperationType {
  386. // Increase parameters.
  387. Increase,
  388. // Decrease parameters.
  389. Decrease,
  390. }
  391. // Helper-struct - defines voucher changes.
  392. #[derive(Clone, PartialEq, Eq, Debug, Copy, Default)]
  393. struct VoucherUpdate {
  394. /// Total number.
  395. pub objects_number: u64,
  396. /// Total objects size sum.
  397. pub objects_total_size: u64,
  398. }
  399. impl VoucherUpdate {
  400. fn get_updated_voucher(&self, voucher: &Voucher, voucher_operation: OperationType) -> Voucher {
  401. let (objects_used, size_used) = match voucher_operation {
  402. OperationType::Increase => (
  403. voucher.objects_used.saturating_add(self.objects_number),
  404. voucher.size_used.saturating_add(self.objects_total_size),
  405. ),
  406. OperationType::Decrease => (
  407. voucher.objects_used.saturating_sub(self.objects_number),
  408. voucher.size_used.saturating_sub(self.objects_total_size),
  409. ),
  410. };
  411. Voucher {
  412. objects_used,
  413. size_used,
  414. ..voucher.clone()
  415. }
  416. }
  417. // Adds a single object data to the voucher update (updates objects size and number).
  418. fn add_object(&mut self, size: u64) {
  419. self.objects_number = self.objects_number.saturating_add(1);
  420. self.objects_total_size = self.objects_total_size.saturating_add(size);
  421. }
  422. }
  423. /// Defines the storage bucket connection to the storage operator (storage WG worker).
  424. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  425. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  426. pub enum StorageBucketOperatorStatus<WorkerId> {
  427. /// No connection.
  428. Missing,
  429. /// Storage operator was invited.
  430. InvitedStorageWorker(WorkerId),
  431. /// Storage operator accepted the invitation.
  432. StorageWorker(WorkerId),
  433. }
  434. impl<WorkerId> Default for StorageBucketOperatorStatus<WorkerId> {
  435. fn default() -> Self {
  436. Self::Missing
  437. }
  438. }
  439. /// A commitment to hold some set of bags for long term storage. A bucket may have a bucket
  440. /// operator, which is a single worker in the storage working group.
  441. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  442. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  443. pub struct StorageBucket<WorkerId> {
  444. /// Current storage operator status.
  445. pub operator_status: StorageBucketOperatorStatus<WorkerId>,
  446. /// Defines whether the bucket accepts new bags.
  447. pub accepting_new_bags: bool,
  448. /// Defines limits for a bucket.
  449. pub voucher: Voucher,
  450. /// Defines storage bucket medata (like current storage provider URL).
  451. pub metadata: Vec<u8>,
  452. }
  453. // Helper-struct for the data object uploading.
  454. #[derive(Default, Clone, Debug)]
  455. struct DataObjectCandidates<T: Trait> {
  456. // next data object ID to be saved in the storage.
  457. next_data_object_id: T::DataObjectId,
  458. // 'ID-data object' map.
  459. data_objects_map: BTreeMap<T::DataObjectId, DataObject<BalanceOf<T>>>,
  460. }
  461. /// Type alias for the DynamicBagObject.
  462. pub type DynamicBag<T> = DynamicBagObject<
  463. <T as Trait>::DataObjectId,
  464. <T as Trait>::StorageBucketId,
  465. <T as Trait>::DistributionBucketId,
  466. BalanceOf<T>,
  467. >;
  468. /// Dynamic bag container.
  469. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  470. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  471. pub struct DynamicBagObject<
  472. DataObjectId: Ord,
  473. StorageBucketId: Ord,
  474. DistributionBucketId: Ord,
  475. Balance,
  476. > {
  477. /// Associated data objects.
  478. pub objects: BTreeMap<DataObjectId, DataObject<Balance>>,
  479. /// Associated storage buckets.
  480. pub stored_by: BTreeSet<StorageBucketId>,
  481. /// Associated distribution buckets.
  482. pub distributed_by: BTreeSet<DistributionBucketId>,
  483. /// Dynamic bag deletion prize.
  484. pub deletion_prize: Balance,
  485. }
  486. impl<DataObjectId: Ord, StorageBucketId: Ord, DistributionBucketId: Ord, Balance>
  487. DynamicBagObject<DataObjectId, StorageBucketId, DistributionBucketId, Balance>
  488. {
  489. // Calculates total object size for dynamic bag.
  490. pub(crate) fn objects_total_size(&self) -> u64 {
  491. self.objects.values().map(|obj| obj.size).sum()
  492. }
  493. // Calculates total objects number for dynamic bag.
  494. pub(crate) fn objects_number(&self) -> u64 {
  495. self.objects.len().saturated_into()
  496. }
  497. }
  498. // Helper struct for the dynamic bag changing.
  499. #[derive(Clone, PartialEq, Eq, Debug, Copy, Default)]
  500. struct BagChangeInfo<Balance> {
  501. // Voucher update for data objects
  502. voucher_update: VoucherUpdate,
  503. // Total deletion prize for data objects.
  504. total_deletion_prize: Balance,
  505. }
  506. impl<Balance: Saturating + Copy> BagChangeInfo<Balance> {
  507. // Adds a single object data to the voucher update (updates objects size, number)
  508. // and deletion prize.
  509. fn add_object(&mut self, size: u64, deletion_prize: Balance) {
  510. self.voucher_update.add_object(size);
  511. self.total_deletion_prize = self.total_deletion_prize.saturating_add(deletion_prize);
  512. }
  513. }
  514. decl_storage! {
  515. trait Store for Module<T: Trait> as Storage {
  516. /// Defines whether all new uploads blocked
  517. pub UploadingBlocked get(fn uploading_blocked): bool;
  518. /// Working groups' and council's bags storage map.
  519. pub StaticBags get(fn static_bag): map hasher(blake2_128_concat)
  520. StaticBagId => StaticBag<T>;
  521. /// Dynamic bag storage map.
  522. pub DynamicBags get (fn dynamic_bag): map hasher(blake2_128_concat)
  523. DynamicBagId<T> => DynamicBag<T>;
  524. /// Storage bucket id counter. Starts at zero.
  525. pub NextStorageBucketId get(fn next_storage_bucket_id): T::StorageBucketId;
  526. /// Data object id counter. Starts at zero.
  527. pub NextDataObjectId get(fn next_data_object_id): T::DataObjectId;
  528. /// Total number of the storage buckets in the system.
  529. pub StorageBucketsNumber get(fn storage_buckets_number): u64;
  530. /// Storage buckets.
  531. pub StorageBucketById get (fn storage_bucket_by_id): map hasher(blake2_128_concat)
  532. T::StorageBucketId => StorageBucket<WorkerId<T>>;
  533. /// Blacklisted data object hashes.
  534. pub Blacklist get (fn blacklist): map hasher(blake2_128_concat) ContentId => ();
  535. /// Blacklist collection counter.
  536. pub CurrentBlacklistSize get (fn current_blacklist_size): u64;
  537. /// Size based pricing of new objects uploaded.
  538. pub DataObjectPerMegabyteFee get (fn data_object_per_mega_byte_fee): BalanceOf<T>;
  539. /// "Storage buckets per bag" number limit.
  540. pub StorageBucketsPerBagLimit get (fn storage_buckets_per_bag_limit): u64;
  541. /// "Max objects size for a storage bucket voucher" number limit.
  542. pub VoucherMaxObjectsSizeLimit get (fn voucher_max_objects_size_limit): u64;
  543. /// "Max objects number for a storage bucket voucher" number limit.
  544. pub VoucherMaxObjectsNumberLimit get (fn voucher_max_objects_number_limit): u64;
  545. /// DynamicBagCreationPolicy by bag type storage map.
  546. pub DynamicBagCreationPolicies get (fn dynamic_bag_creation_policy):
  547. map hasher(blake2_128_concat) DynamicBagType => DynamicBagCreationPolicy;
  548. }
  549. }
  550. decl_event! {
  551. /// Storage events
  552. pub enum Event<T>
  553. where
  554. <T as Trait>::StorageBucketId,
  555. WorkerId = WorkerId<T>,
  556. <T as Trait>::DataObjectId,
  557. UploadParameters = UploadParameters<T>,
  558. BagId = BagId<T>,
  559. DynamicBagId = DynamicBagId<T>,
  560. <T as frame_system::Trait>::AccountId,
  561. Balance = BalanceOf<T>,
  562. {
  563. /// Emits on creating the storage bucket.
  564. /// Params
  565. /// - storage bucket ID
  566. /// - invited worker
  567. /// - flag "accepting_new_bags"
  568. /// - size limit for voucher,
  569. /// - objects limit for voucher,
  570. StorageBucketCreated(StorageBucketId, Option<WorkerId>, bool, u64, u64),
  571. /// Emits on accepting the storage bucket invitation.
  572. /// Params
  573. /// - storage bucket ID
  574. /// - invited worker ID
  575. StorageBucketInvitationAccepted(StorageBucketId, WorkerId),
  576. /// Emits on updating storage buckets for bag.
  577. /// Params
  578. /// - bag ID
  579. /// - storage buckets to add ID collection
  580. /// - storage buckets to remove ID collection
  581. StorageBucketsUpdatedForBag(BagId, BTreeSet<StorageBucketId>, BTreeSet<StorageBucketId>),
  582. /// Emits on uploading data objects.
  583. /// Params
  584. /// - data objects IDs
  585. /// - initial uploading parameters
  586. DataObjectdUploaded(Vec<DataObjectId>, UploadParameters),
  587. /// Emits on setting the storage operator metadata.
  588. /// Params
  589. /// - storage bucket ID
  590. /// - invited worker ID
  591. /// - metadata
  592. StorageOperatorMetadataSet(StorageBucketId, WorkerId, Vec<u8>),
  593. /// Emits on setting the storage bucket voucher limits.
  594. /// Params
  595. /// - storage bucket ID
  596. /// - invited worker ID
  597. /// - new total objects size limit
  598. /// - new total objects number limit
  599. StorageBucketVoucherLimitsSet(StorageBucketId, WorkerId, u64, u64),
  600. /// Emits on accepting pending data objects.
  601. /// Params
  602. /// - storage bucket ID
  603. /// - worker ID (storage provider ID)
  604. /// - bag ID
  605. /// - pending data objects
  606. PendingDataObjectsAccepted(StorageBucketId, WorkerId, BagId, BTreeSet<DataObjectId>),
  607. /// Emits on cancelling the storage bucket invitation.
  608. /// Params
  609. /// - storage bucket ID
  610. StorageBucketInvitationCancelled(StorageBucketId),
  611. /// Emits on the storage bucket operator invitation.
  612. /// Params
  613. /// - storage bucket ID
  614. /// - operator worker ID (storage provider ID)
  615. StorageBucketOperatorInvited(StorageBucketId, WorkerId),
  616. /// Emits on the storage bucket operator removal.
  617. /// Params
  618. /// - storage bucket ID
  619. StorageBucketOperatorRemoved(StorageBucketId),
  620. /// Emits on changing the size-based pricing of new objects uploaded.
  621. /// Params
  622. /// - new status
  623. UploadingBlockStatusUpdated(bool),
  624. /// Emits on changing the size-based pricing of new objects uploaded.
  625. /// Params
  626. /// - new data size fee
  627. DataObjectPerMegabyteFeeUpdated(Balance),
  628. /// Emits on changing the "Storage buckets per bag" number limit.
  629. /// Params
  630. /// - new limit
  631. StorageBucketsPerBagLimitUpdated(u64),
  632. /// Emits on changing the "Storage buckets voucher max limits".
  633. /// Params
  634. /// - new objects size limit
  635. /// - new objects number limit
  636. StorageBucketsVoucherMaxLimitsUpdated(u64, u64),
  637. /// Emits on moving data objects between bags.
  638. /// Params
  639. /// - source bag ID
  640. /// - destination bag ID
  641. /// - data object IDs
  642. DataObjectsMoved(BagId, BagId, BTreeSet<DataObjectId>),
  643. /// Emits on data objects deletion from bags.
  644. /// Params
  645. /// - account ID for the deletion prize
  646. /// - bag ID
  647. /// - data object IDs
  648. DataObjectsDeleted(AccountId, BagId, BTreeSet<DataObjectId>),
  649. /// Emits on storage bucket status update.
  650. /// Params
  651. /// - storage bucket ID
  652. /// - worker ID (storage provider ID)
  653. /// - new status
  654. StorageBucketStatusUpdated(StorageBucketId, WorkerId, bool),
  655. /// Emits on updating the blacklist with data hashes.
  656. /// Params
  657. /// - hashes to remove from the blacklist
  658. /// - hashes to add to the blacklist
  659. UpdateBlacklist(BTreeSet<ContentId>, BTreeSet<ContentId>),
  660. /// Emits on deleting a dynamic bag.
  661. /// Params
  662. /// - account ID for the deletion prize
  663. /// - dynamic bag ID
  664. DynamicBagDeleted(AccountId, DynamicBagId),
  665. /// Emits on creating a dynamic bag.
  666. /// Params
  667. /// - dynamic bag ID
  668. DynamicBagCreated(DynamicBagId),
  669. /// Emits on changing the deletion prize for a dynamic bag.
  670. /// Params
  671. /// - dynamic bag ID
  672. /// - new deletion prize
  673. DeletionPrizeChanged(DynamicBagId, Balance),
  674. /// Emits on changing the voucher for a storage bucket.
  675. /// Params
  676. /// - storage bucket ID
  677. /// - new voucher
  678. VoucherChanged(StorageBucketId, Voucher),
  679. /// Emits on storage bucket deleting.
  680. /// Params
  681. /// - storage bucket ID
  682. StorageBucketDeleted(StorageBucketId),
  683. /// Emits on updating the number of storage buckets in dynamic bag creation policy.
  684. /// Params
  685. /// - dynamic bag type
  686. /// - new number of storage buckets
  687. NumberOfStorageBucketsInDynamicBagCreationPolicyUpdated(DynamicBagType, u64),
  688. }
  689. }
  690. decl_error! {
  691. /// Storage module predefined errors
  692. pub enum Error for Module<T: Trait>{
  693. /// Max storage bucket number limit exceeded.
  694. MaxStorageBucketNumberLimitExceeded,
  695. /// Empty "data object creation" collection.
  696. NoObjectsOnUpload,
  697. /// The requested storage bucket doesn't exist.
  698. StorageBucketDoesntExist,
  699. /// The requested storage bucket is not bound to a bag.
  700. StorageBucketIsNotBoundToBag,
  701. /// The requested storage bucket is already bound to a bag.
  702. StorageBucketIsBoundToBag,
  703. /// Invalid operation with invites: there is no storage bucket invitation.
  704. NoStorageBucketInvitation,
  705. /// Invalid operation with invites: storage provider was already set.
  706. StorageProviderAlreadySet,
  707. /// Storage provider must be set.
  708. StorageProviderMustBeSet,
  709. /// Invalid operation with invites: another storage provider was invited.
  710. DifferentStorageProviderInvited,
  711. /// Invalid operation with invites: storage provider was already invited.
  712. InvitedStorageProvider,
  713. /// Storage bucket id collections are empty.
  714. StorageBucketIdCollectionsAreEmpty,
  715. /// Upload data error: empty content ID provided.
  716. EmptyContentId,
  717. /// Upload data error: zero object size.
  718. ZeroObjectSize,
  719. /// Upload data error: invalid deletion prize source account.
  720. InvalidDeletionPrizeSourceAccount,
  721. /// Upload data error: data objects per bag limit exceeded.
  722. DataObjectsPerBagLimitExceeded,
  723. /// Invalid storage provider for bucket.
  724. InvalidStorageProvider,
  725. /// Insufficient balance for an operation.
  726. InsufficientBalance,
  727. /// Data object doesn't exist.
  728. DataObjectDoesntExist,
  729. /// Uploading of the new object is blocked.
  730. UploadingBlocked,
  731. /// Data object id collection is empty.
  732. DataObjectIdCollectionIsEmpty,
  733. /// Cannot move objects within the same bag.
  734. SourceAndDestinationBagsAreEqual,
  735. /// Data object hash is part of the blacklist.
  736. DataObjectBlacklisted,
  737. /// Blacklist size limit exceeded.
  738. BlacklistSizeLimitExceeded,
  739. /// Max object size limit exceeded for voucher.
  740. VoucherMaxObjectSizeLimitExceeded,
  741. /// Max object number limit exceeded for voucher.
  742. VoucherMaxObjectNumberLimitExceeded,
  743. /// Object number limit for the storage bucket reached.
  744. StorageBucketObjectNumberLimitReached,
  745. /// Objects total size limit for the storage bucket reached.
  746. StorageBucketObjectSizeLimitReached,
  747. /// Insufficient module treasury balance for an operation.
  748. InsufficientTreasuryBalance,
  749. /// Cannot delete a non-empty storage bucket.
  750. CannotDeleteNonEmptyStorageBucket,
  751. /// The `data_object_ids` extrinsic parameter collection is empty.
  752. DataObjectIdParamsAreEmpty,
  753. /// The new `StorageBucketsPerBagLimit` number is too low.
  754. StorageBucketsPerBagLimitTooLow,
  755. /// The new `StorageBucketsPerBagLimit` number is too high.
  756. StorageBucketsPerBagLimitTooHigh,
  757. /// `StorageBucketsPerBagLimit` was exceeded for a bag.
  758. StorageBucketPerBagLimitExceeded,
  759. /// The storage bucket doesn't accept new bags.
  760. StorageBucketDoesntAcceptNewBags,
  761. /// Cannot create the dynamic bag: dynamic bag exists.
  762. DynamicBagExists,
  763. /// Dynamic bag doesn't exist.
  764. DynamicBagDoesntExist,
  765. /// Storage provider operator doesn't exist.
  766. StorageProviderOperatorDoesntExist,
  767. }
  768. }
  769. decl_module! {
  770. /// _Storage_ substrate module.
  771. pub struct Module<T: Trait> for enum Call where origin: T::Origin {
  772. /// Default deposit_event() handler
  773. fn deposit_event() = default;
  774. /// Predefined errors.
  775. type Error = Error<T>;
  776. /// Exports const - max allowed storage bucket number.
  777. const MaxStorageBucketNumber: u64 = T::MaxStorageBucketNumber::get();
  778. /// Exports const - max number of data objects per bag.
  779. const MaxNumberOfDataObjectsPerBag: u64 = T::MaxNumberOfDataObjectsPerBag::get();
  780. /// Exports const - a prize for a data object deletion.
  781. const DataObjectDeletionPrize: BalanceOf<T> = T::DataObjectDeletionPrize::get();
  782. /// Exports const - maximum size of the "hash blacklist" collection.
  783. const BlacklistSizeLimit: u64 = T::BlacklistSizeLimit::get();
  784. /// Exports const - "Storage buckets per bag" value constraint.
  785. const StorageBucketsPerBagValueConstraint: StorageBucketsPerBagValueConstraint =
  786. T::StorageBucketsPerBagValueConstraint::get();
  787. /// Exports const - the default dynamic bag creation policy for members.
  788. const DefaultMemberDynamicBagCreationPolicy: DynamicBagCreationPolicy =
  789. T::DefaultMemberDynamicBagCreationPolicy::get();
  790. /// Exports const - the default dynamic bag creation policy for channels.
  791. const DefaultChannelDynamicBagCreationPolicy: DynamicBagCreationPolicy =
  792. T::DefaultChannelDynamicBagCreationPolicy::get();
  793. // ===== Storage Lead actions =====
  794. /// Delete storage bucket. Must be empty. Storage operator must be missing.
  795. #[weight = 10_000_000] // TODO: adjust weight
  796. pub fn delete_storage_bucket(
  797. origin,
  798. storage_bucket_id: T::StorageBucketId,
  799. ){
  800. T::ensure_working_group_leader_origin(origin)?;
  801. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  802. Self::ensure_bucket_missing_invitation_status(&bucket)?;
  803. ensure!(
  804. bucket.voucher.objects_used == 0,
  805. Error::<T>::CannotDeleteNonEmptyStorageBucket
  806. );
  807. //
  808. // == MUTATION SAFE ==
  809. //
  810. <StorageBucketById<T>>::remove(storage_bucket_id);
  811. Self::deposit_event(
  812. RawEvent::StorageBucketDeleted(storage_bucket_id)
  813. );
  814. }
  815. /// Update whether uploading is globally blocked.
  816. #[weight = 10_000_000] // TODO: adjust weight
  817. pub fn update_uploading_blocked_status(origin, new_status: bool) {
  818. T::ensure_working_group_leader_origin(origin)?;
  819. //
  820. // == MUTATION SAFE ==
  821. //
  822. UploadingBlocked::put(new_status);
  823. Self::deposit_event(RawEvent::UploadingBlockStatusUpdated(new_status));
  824. }
  825. /// Updates size-based pricing of new objects uploaded.
  826. #[weight = 10_000_000] // TODO: adjust weight
  827. pub fn update_data_size_fee(origin, new_data_size_fee: BalanceOf<T>) {
  828. T::ensure_working_group_leader_origin(origin)?;
  829. //
  830. // == MUTATION SAFE ==
  831. //
  832. DataObjectPerMegabyteFee::<T>::put(new_data_size_fee);
  833. Self::deposit_event(RawEvent::DataObjectPerMegabyteFeeUpdated(new_data_size_fee));
  834. }
  835. /// Updates "Storage buckets per bag" number limit.
  836. #[weight = 10_000_000] // TODO: adjust weight
  837. pub fn update_storage_buckets_per_bag_limit(origin, new_limit: u64) {
  838. T::ensure_working_group_leader_origin(origin)?;
  839. T::StorageBucketsPerBagValueConstraint::get().ensure_valid(
  840. new_limit,
  841. Error::<T>::StorageBucketsPerBagLimitTooLow,
  842. Error::<T>::StorageBucketsPerBagLimitTooHigh,
  843. )?;
  844. //
  845. // == MUTATION SAFE ==
  846. //
  847. StorageBucketsPerBagLimit::put(new_limit);
  848. Self::deposit_event(RawEvent::StorageBucketsPerBagLimitUpdated(new_limit));
  849. }
  850. /// Updates "Storage buckets voucher max limits".
  851. #[weight = 10_000_000] // TODO: adjust weight
  852. pub fn update_storage_buckets_voucher_max_limits(
  853. origin,
  854. new_objects_size: u64,
  855. new_objects_number: u64,
  856. ) {
  857. T::ensure_working_group_leader_origin(origin)?;
  858. //
  859. // == MUTATION SAFE ==
  860. //
  861. VoucherMaxObjectsSizeLimit::put(new_objects_size);
  862. VoucherMaxObjectsNumberLimit::put(new_objects_number);
  863. Self::deposit_event(
  864. RawEvent::StorageBucketsVoucherMaxLimitsUpdated(new_objects_size, new_objects_number)
  865. );
  866. }
  867. /// Update number of storage buckets used in given dynamic bag creation policy.
  868. #[weight = 10_000_000] // TODO: adjust weight
  869. pub fn update_number_of_storage_buckets_in_dynamic_bag_creation_policy(
  870. origin,
  871. dynamic_bag_type: DynamicBagType,
  872. number_of_storage_buckets: u64,
  873. ) {
  874. T::ensure_working_group_leader_origin(origin)?;
  875. //
  876. // == MUTATION SAFE ==
  877. //
  878. let mut creation_policy = Self::get_dynamic_bag_creation_policy(dynamic_bag_type);
  879. creation_policy.number_of_storage_buckets = number_of_storage_buckets;
  880. DynamicBagCreationPolicies::insert(dynamic_bag_type, creation_policy);
  881. Self::deposit_event(
  882. RawEvent::NumberOfStorageBucketsInDynamicBagCreationPolicyUpdated(
  883. dynamic_bag_type,
  884. number_of_storage_buckets
  885. )
  886. );
  887. }
  888. /// Add and remove hashes to the current blacklist.
  889. #[weight = 10_000_000] // TODO: adjust weight
  890. pub fn update_blacklist(
  891. origin,
  892. remove_hashes: BTreeSet<ContentId>,
  893. add_hashes: BTreeSet<ContentId>
  894. ){
  895. T::ensure_working_group_leader_origin(origin)?;
  896. // Get only hashes that exist in the blacklist.
  897. let verified_remove_hashes = Self::get_existing_hashes(&remove_hashes);
  898. // Get only hashes that doesn't exist in the blacklist.
  899. let verified_add_hashes = Self::get_nonexisting_hashes(&add_hashes);
  900. let updated_blacklist_size: u64 = Self::current_blacklist_size()
  901. .saturating_add(verified_add_hashes.len().saturated_into::<u64>())
  902. .saturating_sub(verified_remove_hashes.len().saturated_into::<u64>());
  903. ensure!(
  904. updated_blacklist_size <= T::BlacklistSizeLimit::get(),
  905. Error::<T>::BlacklistSizeLimitExceeded
  906. );
  907. //
  908. // == MUTATION SAFE ==
  909. //
  910. for cid in verified_remove_hashes.iter() {
  911. Blacklist::remove(cid);
  912. }
  913. for cid in verified_add_hashes.iter() {
  914. Blacklist::insert(cid, ());
  915. }
  916. CurrentBlacklistSize::put(updated_blacklist_size);
  917. Self::deposit_event(RawEvent::UpdateBlacklist(remove_hashes, add_hashes));
  918. }
  919. /// Create storage bucket.
  920. #[weight = 10_000_000] // TODO: adjust weight
  921. pub fn create_storage_bucket(
  922. origin,
  923. invite_worker: Option<WorkerId<T>>,
  924. accepting_new_bags: bool,
  925. size_limit: u64,
  926. objects_limit: u64,
  927. ) {
  928. T::ensure_working_group_leader_origin(origin)?;
  929. let voucher = Voucher {
  930. size_limit,
  931. objects_limit,
  932. ..Default::default()
  933. };
  934. Self::can_create_storage_bucket(&voucher, &invite_worker)?;
  935. //
  936. // == MUTATION SAFE ==
  937. //
  938. let operator_status = invite_worker
  939. .map(StorageBucketOperatorStatus::InvitedStorageWorker)
  940. .unwrap_or(StorageBucketOperatorStatus::Missing);
  941. let storage_bucket = StorageBucket {
  942. operator_status,
  943. accepting_new_bags,
  944. voucher,
  945. metadata: Vec::new(),
  946. };
  947. let storage_bucket_id = Self::next_storage_bucket_id();
  948. StorageBucketsNumber::put(Self::storage_buckets_number() + 1);
  949. <NextStorageBucketId<T>>::put(storage_bucket_id + One::one());
  950. <StorageBucketById<T>>::insert(storage_bucket_id, storage_bucket);
  951. Self::deposit_event(
  952. RawEvent::StorageBucketCreated(
  953. storage_bucket_id,
  954. invite_worker,
  955. accepting_new_bags,
  956. size_limit,
  957. objects_limit,
  958. )
  959. );
  960. }
  961. /// Updates storage buckets for a bag..
  962. #[weight = 10_000_000] // TODO: adjust weight
  963. pub fn update_storage_buckets_for_bag(
  964. origin,
  965. bag_id: BagId<T>,
  966. add_buckets: BTreeSet<T::StorageBucketId>,
  967. remove_buckets: BTreeSet<T::StorageBucketId>,
  968. ) {
  969. T::ensure_working_group_leader_origin(origin)?;
  970. let voucher_update = Self::validate_update_storage_buckets_for_bag_params(
  971. &bag_id,
  972. &add_buckets,
  973. &remove_buckets,
  974. )?;
  975. //
  976. // == MUTATION SAFE ==
  977. //
  978. // Update vouchers.
  979. if !add_buckets.is_empty() {
  980. BagManager::<T>::add_storage_buckets(&bag_id, add_buckets.clone());
  981. Self::change_storage_buckets_vouchers(
  982. &add_buckets,
  983. &voucher_update,
  984. OperationType::Increase
  985. );
  986. }
  987. if !remove_buckets.is_empty() {
  988. BagManager::<T>::remove_storage_buckets(&bag_id, remove_buckets.clone());
  989. Self::change_storage_buckets_vouchers(
  990. &remove_buckets,
  991. &voucher_update,
  992. OperationType::Decrease
  993. );
  994. }
  995. Self::deposit_event(
  996. RawEvent::StorageBucketsUpdatedForBag(bag_id, add_buckets, remove_buckets)
  997. );
  998. }
  999. /// Cancel pending storage bucket invite. An invitation must be pending.
  1000. #[weight = 10_000_000] // TODO: adjust weight
  1001. pub fn cancel_storage_bucket_operator_invite(origin, storage_bucket_id: T::StorageBucketId){
  1002. T::ensure_working_group_leader_origin(origin)?;
  1003. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1004. Self::ensure_bucket_pending_invitation_status(&bucket)?;
  1005. //
  1006. // == MUTATION SAFE ==
  1007. //
  1008. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1009. bucket.operator_status = StorageBucketOperatorStatus::Missing;
  1010. });
  1011. Self::deposit_event(
  1012. RawEvent::StorageBucketInvitationCancelled(storage_bucket_id)
  1013. );
  1014. }
  1015. /// Invite storage bucket operator. Must be missing.
  1016. #[weight = 10_000_000] // TODO: adjust weight
  1017. pub fn invite_storage_bucket_operator(
  1018. origin,
  1019. storage_bucket_id: T::StorageBucketId,
  1020. operator_id: WorkerId<T>,
  1021. ){
  1022. T::ensure_working_group_leader_origin(origin)?;
  1023. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1024. Self::ensure_bucket_missing_invitation_status(&bucket)?;
  1025. Self::ensure_storage_provider_operator_exists(&operator_id)?;
  1026. //
  1027. // == MUTATION SAFE ==
  1028. //
  1029. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1030. bucket.operator_status =
  1031. StorageBucketOperatorStatus::InvitedStorageWorker(operator_id);
  1032. });
  1033. Self::deposit_event(
  1034. RawEvent::StorageBucketOperatorInvited(storage_bucket_id, operator_id)
  1035. );
  1036. }
  1037. /// Removes storage bucket operator. Must be invited.
  1038. #[weight = 10_000_000] // TODO: adjust weight
  1039. pub fn remove_storage_bucket_operator(
  1040. origin,
  1041. storage_bucket_id: T::StorageBucketId,
  1042. ){
  1043. T::ensure_working_group_leader_origin(origin)?;
  1044. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1045. Self::ensure_bucket_storage_provider_invitation_status_for_removal(&bucket)?;
  1046. //
  1047. // == MUTATION SAFE ==
  1048. //
  1049. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1050. bucket.operator_status =
  1051. StorageBucketOperatorStatus::Missing;
  1052. });
  1053. Self::deposit_event(
  1054. RawEvent::StorageBucketOperatorRemoved(storage_bucket_id)
  1055. );
  1056. }
  1057. // ===== Storage Operator actions =====
  1058. /// Accept the storage bucket invitation. An invitation must match the worker_id parameter.
  1059. #[weight = 10_000_000] // TODO: adjust weight
  1060. pub fn accept_storage_bucket_invitation(
  1061. origin,
  1062. worker_id: WorkerId<T>,
  1063. storage_bucket_id: T::StorageBucketId
  1064. ) {
  1065. T::ensure_worker_origin(origin, worker_id)?;
  1066. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1067. Self::ensure_bucket_storage_provider_invitation_status(&bucket, worker_id)?;
  1068. //
  1069. // == MUTATION SAFE ==
  1070. //
  1071. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1072. bucket.operator_status = StorageBucketOperatorStatus::StorageWorker(worker_id);
  1073. });
  1074. Self::deposit_event(
  1075. RawEvent::StorageBucketInvitationAccepted(storage_bucket_id, worker_id)
  1076. );
  1077. }
  1078. /// Sets storage operator metadata (eg.: storage node URL).
  1079. #[weight = 10_000_000] // TODO: adjust weight
  1080. pub fn set_storage_operator_metadata(
  1081. origin,
  1082. worker_id: WorkerId<T>,
  1083. storage_bucket_id: T::StorageBucketId,
  1084. metadata: Vec<u8>
  1085. ) {
  1086. T::ensure_worker_origin(origin, worker_id)?;
  1087. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1088. Self::ensure_bucket_invitation_accepted(&bucket, worker_id)?;
  1089. //
  1090. // == MUTATION SAFE ==
  1091. //
  1092. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1093. bucket.metadata = metadata.clone();
  1094. });
  1095. Self::deposit_event(
  1096. RawEvent::StorageOperatorMetadataSet(storage_bucket_id, worker_id, metadata)
  1097. );
  1098. }
  1099. /// Sets storage bucket voucher limits.
  1100. #[weight = 10_000_000] // TODO: adjust weight
  1101. pub fn set_storage_bucket_voucher_limits(
  1102. origin,
  1103. worker_id: WorkerId<T>,
  1104. storage_bucket_id: T::StorageBucketId,
  1105. new_objects_size_limit: u64,
  1106. new_objects_number_limit: u64,
  1107. ) {
  1108. T::ensure_worker_origin(origin, worker_id)?;
  1109. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1110. Self::ensure_bucket_invitation_accepted(&bucket, worker_id)?;
  1111. ensure!(
  1112. new_objects_size_limit <= Self::voucher_max_objects_size_limit(),
  1113. Error::<T>::VoucherMaxObjectSizeLimitExceeded
  1114. );
  1115. ensure!(
  1116. new_objects_number_limit <= Self::voucher_max_objects_number_limit(),
  1117. Error::<T>::VoucherMaxObjectNumberLimitExceeded
  1118. );
  1119. //
  1120. // == MUTATION SAFE ==
  1121. //
  1122. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1123. bucket.voucher = Voucher{
  1124. size_limit: new_objects_size_limit,
  1125. objects_limit: new_objects_number_limit,
  1126. ..bucket.voucher
  1127. };
  1128. });
  1129. Self::deposit_event(
  1130. RawEvent::StorageBucketVoucherLimitsSet(
  1131. storage_bucket_id,
  1132. worker_id,
  1133. new_objects_size_limit,
  1134. new_objects_number_limit
  1135. )
  1136. );
  1137. }
  1138. /// A storage provider signals that the data object was successfully uploaded to its storage.
  1139. #[weight = 10_000_000] // TODO: adjust weight
  1140. pub fn accept_pending_data_objects(
  1141. origin,
  1142. worker_id: WorkerId<T>,
  1143. storage_bucket_id: T::StorageBucketId,
  1144. bag_id: BagId<T>,
  1145. data_objects: BTreeSet<T::DataObjectId>,
  1146. ) {
  1147. T::ensure_worker_origin(origin, worker_id)?;
  1148. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1149. Self::ensure_bucket_invitation_accepted(&bucket, worker_id)?;
  1150. Self::validate_accept_pending_data_objects_params(
  1151. &bag_id,
  1152. &data_objects,
  1153. &storage_bucket_id
  1154. )?;
  1155. //
  1156. // == MUTATION SAFE ==
  1157. //
  1158. for data_object_id in data_objects.iter() {
  1159. BagManager::<T>::accept_data_objects(&bag_id, &data_object_id);
  1160. }
  1161. Self::deposit_event(
  1162. RawEvent::PendingDataObjectsAccepted(storage_bucket_id, worker_id, bag_id, data_objects)
  1163. );
  1164. }
  1165. /// Update whether new bags are being accepted for storage.
  1166. #[weight = 10_000_000] // TODO: adjust weight
  1167. pub fn update_storage_bucket_status(
  1168. origin,
  1169. worker_id: WorkerId<T>,
  1170. storage_bucket_id: T::StorageBucketId,
  1171. accepting_new_bags: bool
  1172. ) {
  1173. T::ensure_worker_origin(origin, worker_id)?;
  1174. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1175. Self::ensure_bucket_invitation_accepted(&bucket, worker_id)?;
  1176. //
  1177. // == MUTATION SAFE ==
  1178. //
  1179. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1180. bucket.accepting_new_bags = accepting_new_bags;
  1181. });
  1182. Self::deposit_event(
  1183. RawEvent::StorageBucketStatusUpdated(
  1184. storage_bucket_id,
  1185. worker_id,
  1186. accepting_new_bags
  1187. )
  1188. );
  1189. }
  1190. }
  1191. }
  1192. // Public methods
  1193. impl<T: Trait> DataObjectStorage<T> for Module<T> {
  1194. fn can_upload_data_objects(params: &UploadParameters<T>) -> DispatchResult {
  1195. Self::validate_upload_data_objects_parameters(params).map(|_| ())
  1196. }
  1197. fn upload_data_objects(params: UploadParameters<T>) -> DispatchResult {
  1198. let bag_change = Self::validate_upload_data_objects_parameters(&params)?;
  1199. //
  1200. // == MUTATION SAFE ==
  1201. //
  1202. let data = Self::create_data_objects(params.object_creation_list.clone());
  1203. <StorageTreasury<T>>::deposit(
  1204. &params.deletion_prize_source_account_id,
  1205. bag_change.total_deletion_prize,
  1206. )?;
  1207. Self::slash_data_size_fee(
  1208. &params.deletion_prize_source_account_id,
  1209. bag_change.voucher_update.objects_total_size,
  1210. );
  1211. <NextDataObjectId<T>>::put(data.next_data_object_id);
  1212. BagManager::<T>::append_data_objects(&params.bag_id, &data.data_objects_map);
  1213. let operation_type = OperationType::Increase;
  1214. // Add a deletion prize for the dynamic bag only.
  1215. Self::change_deletion_prize_for_bag(
  1216. &params.bag_id,
  1217. bag_change.total_deletion_prize,
  1218. operation_type,
  1219. );
  1220. Self::change_storage_bucket_vouchers_for_bag(
  1221. &params.bag_id,
  1222. &bag_change.voucher_update,
  1223. operation_type,
  1224. );
  1225. Self::deposit_event(RawEvent::DataObjectdUploaded(
  1226. data.data_objects_map.keys().cloned().collect(),
  1227. params,
  1228. ));
  1229. Ok(())
  1230. }
  1231. fn can_move_data_objects(
  1232. src_bag_id: &BagId<T>,
  1233. dest_bag_id: &BagId<T>,
  1234. objects: &BTreeSet<<T as Trait>::DataObjectId>,
  1235. ) -> DispatchResult {
  1236. Self::validate_data_objects_on_moving(src_bag_id, dest_bag_id, objects).map(|_| ())
  1237. }
  1238. fn move_data_objects(
  1239. src_bag_id: BagId<T>,
  1240. dest_bag_id: BagId<T>,
  1241. objects: BTreeSet<T::DataObjectId>,
  1242. ) -> DispatchResult {
  1243. let bag_change =
  1244. Self::validate_data_objects_on_moving(&src_bag_id, &dest_bag_id, &objects)?;
  1245. //
  1246. // == MUTATION SAFE ==
  1247. //
  1248. BagManager::<T>::move_data_objects(&src_bag_id, &dest_bag_id, &objects);
  1249. // Change source bag.
  1250. let src_operation_type = OperationType::Decrease;
  1251. Self::change_storage_bucket_vouchers_for_bag(
  1252. &src_bag_id,
  1253. &bag_change.voucher_update,
  1254. src_operation_type,
  1255. );
  1256. Self::change_deletion_prize_for_bag(
  1257. &src_bag_id,
  1258. bag_change.total_deletion_prize,
  1259. src_operation_type,
  1260. );
  1261. // Change destination bag.
  1262. let dest_operation_type = OperationType::Increase;
  1263. Self::change_storage_bucket_vouchers_for_bag(
  1264. &dest_bag_id,
  1265. &bag_change.voucher_update,
  1266. dest_operation_type,
  1267. );
  1268. Self::change_deletion_prize_for_bag(
  1269. &dest_bag_id,
  1270. bag_change.total_deletion_prize,
  1271. dest_operation_type,
  1272. );
  1273. Self::deposit_event(RawEvent::DataObjectsMoved(src_bag_id, dest_bag_id, objects));
  1274. Ok(())
  1275. }
  1276. fn can_delete_data_objects(
  1277. bag_id: &BagId<T>,
  1278. objects: &BTreeSet<T::DataObjectId>,
  1279. ) -> DispatchResult {
  1280. Self::validate_delete_data_objects_params(bag_id, objects).map(|_| ())
  1281. }
  1282. fn delete_data_objects(
  1283. deletion_prize_account_id: T::AccountId,
  1284. bag_id: BagId<T>,
  1285. objects: BTreeSet<T::DataObjectId>,
  1286. ) -> DispatchResult {
  1287. let bag_change = Self::validate_delete_data_objects_params(&bag_id, &objects)?;
  1288. //
  1289. // == MUTATION SAFE ==
  1290. //
  1291. <StorageTreasury<T>>::withdraw(
  1292. &deletion_prize_account_id,
  1293. bag_change.total_deletion_prize,
  1294. )?;
  1295. for data_object_id in objects.iter() {
  1296. BagManager::<T>::delete_data_object(&bag_id, &data_object_id);
  1297. }
  1298. let operation_type = OperationType::Decrease;
  1299. Self::change_storage_bucket_vouchers_for_bag(
  1300. &bag_id,
  1301. &bag_change.voucher_update,
  1302. operation_type,
  1303. );
  1304. // Subtract deletion prize for dynamic bags only.
  1305. Self::change_deletion_prize_for_bag(
  1306. &bag_id,
  1307. bag_change.total_deletion_prize,
  1308. operation_type,
  1309. );
  1310. Self::deposit_event(RawEvent::DataObjectsDeleted(
  1311. deletion_prize_account_id,
  1312. bag_id,
  1313. objects,
  1314. ));
  1315. Ok(())
  1316. }
  1317. fn can_delete_dynamic_bag(bag_id: &DynamicBagId<T>) -> DispatchResult {
  1318. Self::validate_delete_dynamic_bag_params(bag_id).map(|_| ())
  1319. }
  1320. fn delete_dynamic_bag(
  1321. deletion_prize_account_id: T::AccountId,
  1322. bag_id: DynamicBagId<T>,
  1323. ) -> DispatchResult {
  1324. let bag_change = Self::validate_delete_dynamic_bag_params(&bag_id)?;
  1325. //
  1326. // == MUTATION SAFE ==
  1327. //
  1328. <StorageTreasury<T>>::withdraw(
  1329. &deletion_prize_account_id,
  1330. bag_change.total_deletion_prize,
  1331. )?;
  1332. let dynamic_bag = Self::dynamic_bag(&bag_id);
  1333. Self::change_storage_buckets_vouchers(
  1334. &dynamic_bag.stored_by,
  1335. &bag_change.voucher_update,
  1336. OperationType::Decrease,
  1337. );
  1338. <DynamicBags<T>>::remove(&bag_id);
  1339. Self::deposit_event(RawEvent::DynamicBagDeleted(
  1340. deletion_prize_account_id,
  1341. bag_id,
  1342. ));
  1343. Ok(())
  1344. }
  1345. fn create_dynamic_bag(bag_id: DynamicBagId<T>) -> DispatchResult {
  1346. Self::validate_create_dynamic_bag_params(&bag_id)?;
  1347. //
  1348. // == MUTATION SAFE ==
  1349. //
  1350. let storage_buckets = Self::pick_storage_buckets_for_dynamic_bag(bag_id.clone().into());
  1351. let bag = DynamicBag::<T> {
  1352. stored_by: storage_buckets,
  1353. ..Default::default()
  1354. };
  1355. <DynamicBags<T>>::insert(&bag_id, bag);
  1356. Self::deposit_event(RawEvent::DynamicBagCreated(bag_id));
  1357. Ok(())
  1358. }
  1359. fn can_create_dynamic_bag(bag_id: &DynamicBagId<T>) -> DispatchResult {
  1360. Self::validate_create_dynamic_bag_params(bag_id)
  1361. }
  1362. }
  1363. impl<T: Trait> Module<T> {
  1364. // Validates dynamic bag creation params and conditions.
  1365. fn validate_create_dynamic_bag_params(bag_id: &DynamicBagId<T>) -> DispatchResult {
  1366. ensure!(
  1367. !<DynamicBags<T>>::contains_key(&bag_id),
  1368. Error::<T>::DynamicBagExists
  1369. );
  1370. Ok(())
  1371. }
  1372. // Validates dynamic bag deletion params and conditions.
  1373. fn validate_delete_dynamic_bag_params(
  1374. bag_id: &DynamicBagId<T>,
  1375. ) -> Result<BagChangeInfo<BalanceOf<T>>, DispatchError> {
  1376. BagManager::<T>::ensure_bag_exists(&BagId::<T>::DynamicBag(bag_id.clone()))?;
  1377. let dynamic_bag = Self::dynamic_bag(bag_id);
  1378. let voucher_update = VoucherUpdate {
  1379. objects_number: dynamic_bag.objects_number(),
  1380. objects_total_size: dynamic_bag.objects_total_size(),
  1381. };
  1382. ensure!(
  1383. <StorageTreasury<T>>::usable_balance() >= dynamic_bag.deletion_prize,
  1384. Error::<T>::InsufficientTreasuryBalance
  1385. );
  1386. let bag_change = BagChangeInfo {
  1387. voucher_update,
  1388. total_deletion_prize: dynamic_bag.deletion_prize,
  1389. };
  1390. Ok(bag_change)
  1391. }
  1392. // Ensures the existence of the storage bucket.
  1393. // Returns the StorageBucket object or error.
  1394. fn ensure_storage_bucket_exists(
  1395. storage_bucket_id: &T::StorageBucketId,
  1396. ) -> Result<StorageBucket<WorkerId<T>>, Error<T>> {
  1397. ensure!(
  1398. <StorageBucketById<T>>::contains_key(storage_bucket_id),
  1399. Error::<T>::StorageBucketDoesntExist
  1400. );
  1401. Ok(Self::storage_bucket_by_id(storage_bucket_id))
  1402. }
  1403. // Ensures the correct invitation for the storage bucket and storage provider. Storage provider
  1404. // must be invited.
  1405. fn ensure_bucket_storage_provider_invitation_status(
  1406. bucket: &StorageBucket<WorkerId<T>>,
  1407. worker_id: WorkerId<T>,
  1408. ) -> DispatchResult {
  1409. match bucket.operator_status {
  1410. StorageBucketOperatorStatus::Missing => {
  1411. Err(Error::<T>::NoStorageBucketInvitation.into())
  1412. }
  1413. StorageBucketOperatorStatus::StorageWorker(_) => {
  1414. Err(Error::<T>::StorageProviderAlreadySet.into())
  1415. }
  1416. StorageBucketOperatorStatus::InvitedStorageWorker(invited_worker_id) => {
  1417. ensure!(
  1418. worker_id == invited_worker_id,
  1419. Error::<T>::DifferentStorageProviderInvited
  1420. );
  1421. Ok(())
  1422. }
  1423. }
  1424. }
  1425. // Ensures the correct invitation for the storage bucket and storage provider for removal.
  1426. // Must be invited storage provider.
  1427. fn ensure_bucket_storage_provider_invitation_status_for_removal(
  1428. bucket: &StorageBucket<WorkerId<T>>,
  1429. ) -> DispatchResult {
  1430. if let StorageBucketOperatorStatus::StorageWorker(_) = bucket.operator_status {
  1431. Ok(())
  1432. } else {
  1433. Err(Error::<T>::StorageProviderMustBeSet.into())
  1434. }
  1435. }
  1436. // Ensures the correct invitation for the storage bucket and storage provider. Must be pending.
  1437. fn ensure_bucket_pending_invitation_status(
  1438. bucket: &StorageBucket<WorkerId<T>>,
  1439. ) -> DispatchResult {
  1440. match bucket.operator_status {
  1441. StorageBucketOperatorStatus::Missing => {
  1442. Err(Error::<T>::NoStorageBucketInvitation.into())
  1443. }
  1444. StorageBucketOperatorStatus::StorageWorker(_) => {
  1445. Err(Error::<T>::StorageProviderAlreadySet.into())
  1446. }
  1447. StorageBucketOperatorStatus::InvitedStorageWorker(_) => Ok(()),
  1448. }
  1449. }
  1450. // Ensures the missing invitation for the storage bucket and storage provider.
  1451. fn ensure_bucket_missing_invitation_status(
  1452. bucket: &StorageBucket<WorkerId<T>>,
  1453. ) -> DispatchResult {
  1454. match bucket.operator_status {
  1455. StorageBucketOperatorStatus::Missing => Ok(()),
  1456. StorageBucketOperatorStatus::StorageWorker(_) => {
  1457. Err(Error::<T>::StorageProviderAlreadySet.into())
  1458. }
  1459. StorageBucketOperatorStatus::InvitedStorageWorker(_) => {
  1460. Err(Error::<T>::InvitedStorageProvider.into())
  1461. }
  1462. }
  1463. }
  1464. // Ensures correct storage provider for the storage bucket.
  1465. fn ensure_bucket_invitation_accepted(
  1466. bucket: &StorageBucket<WorkerId<T>>,
  1467. worker_id: WorkerId<T>,
  1468. ) -> DispatchResult {
  1469. match bucket.operator_status {
  1470. StorageBucketOperatorStatus::Missing => {
  1471. Err(Error::<T>::StorageProviderMustBeSet.into())
  1472. }
  1473. StorageBucketOperatorStatus::InvitedStorageWorker(_) => {
  1474. Err(Error::<T>::InvalidStorageProvider.into())
  1475. }
  1476. StorageBucketOperatorStatus::StorageWorker(invited_worker_id) => {
  1477. ensure!(
  1478. worker_id == invited_worker_id,
  1479. Error::<T>::InvalidStorageProvider
  1480. );
  1481. Ok(())
  1482. }
  1483. }
  1484. }
  1485. // Create data objects from the creation data.
  1486. fn create_data_objects(
  1487. object_creation_list: Vec<DataObjectCreationParameters>,
  1488. ) -> DataObjectCandidates<T> {
  1489. let deletion_prize = T::DataObjectDeletionPrize::get();
  1490. let data_objects = object_creation_list.iter().cloned().map(|obj| DataObject {
  1491. accepted: false,
  1492. deletion_prize,
  1493. size: obj.size,
  1494. });
  1495. let mut next_data_object_id = Self::next_data_object_id();
  1496. let ids = iter::repeat_with(|| {
  1497. let id = next_data_object_id;
  1498. next_data_object_id += One::one();
  1499. id
  1500. })
  1501. .take(data_objects.len());
  1502. let data_objects_map = ids.zip(data_objects).collect::<BTreeMap<_, _>>();
  1503. DataObjectCandidates {
  1504. next_data_object_id,
  1505. data_objects_map,
  1506. }
  1507. }
  1508. // Ensures validity of the `accept_pending_data_objects` extrinsic parameters
  1509. fn validate_accept_pending_data_objects_params(
  1510. bag_id: &BagId<T>,
  1511. data_objects: &BTreeSet<T::DataObjectId>,
  1512. storage_bucket_id: &T::StorageBucketId,
  1513. ) -> DispatchResult {
  1514. ensure!(
  1515. !data_objects.is_empty(),
  1516. Error::<T>::DataObjectIdParamsAreEmpty
  1517. );
  1518. BagManager::<T>::ensure_bag_exists(bag_id)?;
  1519. BagManager::<T>::ensure_storage_bucket_bound(bag_id, storage_bucket_id)?;
  1520. for data_object_id in data_objects.iter() {
  1521. BagManager::<T>::ensure_data_object_existence(bag_id, data_object_id)?;
  1522. }
  1523. Ok(())
  1524. }
  1525. // Ensures validity of the `update_storage_buckets_for_bag` extrinsic parameters
  1526. fn validate_update_storage_buckets_for_bag_params(
  1527. bag_id: &BagId<T>,
  1528. add_buckets: &BTreeSet<T::StorageBucketId>,
  1529. remove_buckets: &BTreeSet<T::StorageBucketId>,
  1530. ) -> Result<VoucherUpdate, DispatchError> {
  1531. ensure!(
  1532. !add_buckets.is_empty() || !remove_buckets.is_empty(),
  1533. Error::<T>::StorageBucketIdCollectionsAreEmpty
  1534. );
  1535. BagManager::<T>::ensure_bag_exists(&bag_id)?;
  1536. let storage_bucket_ids = BagManager::<T>::get_storage_bucket_ids(bag_id);
  1537. ensure!(
  1538. storage_bucket_ids.len().saturated_into::<u64>()
  1539. <= Self::storage_buckets_per_bag_limit(),
  1540. Error::<T>::StorageBucketPerBagLimitExceeded
  1541. );
  1542. for bucket_id in remove_buckets.iter() {
  1543. ensure!(
  1544. <StorageBucketById<T>>::contains_key(&bucket_id),
  1545. Error::<T>::StorageBucketDoesntExist
  1546. );
  1547. ensure!(
  1548. storage_bucket_ids.contains(&bucket_id),
  1549. Error::<T>::StorageBucketIsNotBoundToBag
  1550. );
  1551. }
  1552. for bucket_id in add_buckets.iter() {
  1553. let bucket = Self::ensure_storage_bucket_exists(bucket_id)?;
  1554. ensure!(
  1555. bucket.accepting_new_bags,
  1556. Error::<T>::StorageBucketDoesntAcceptNewBags
  1557. );
  1558. ensure!(
  1559. !storage_bucket_ids.contains(&bucket_id),
  1560. Error::<T>::StorageBucketIsBoundToBag
  1561. );
  1562. }
  1563. let objects_total_size = BagManager::<T>::get_data_objects_total_size(bag_id);
  1564. let objects_number = BagManager::<T>::get_data_objects_number(bag_id);
  1565. let voucher_update = VoucherUpdate {
  1566. objects_number,
  1567. objects_total_size,
  1568. };
  1569. Self::check_buckets_for_overflow(&add_buckets, &voucher_update)?;
  1570. Ok(voucher_update)
  1571. }
  1572. // Validate the "Move data objects between bags" operation data.
  1573. fn validate_data_objects_on_moving(
  1574. src_bag_id: &BagId<T>,
  1575. dest_bag_id: &BagId<T>,
  1576. object_ids: &BTreeSet<T::DataObjectId>,
  1577. ) -> Result<BagChangeInfo<BalanceOf<T>>, DispatchError> {
  1578. ensure!(
  1579. *src_bag_id != *dest_bag_id,
  1580. Error::<T>::SourceAndDestinationBagsAreEqual
  1581. );
  1582. ensure!(
  1583. !object_ids.is_empty(),
  1584. Error::<T>::DataObjectIdCollectionIsEmpty
  1585. );
  1586. BagManager::<T>::ensure_bag_exists(src_bag_id)?;
  1587. BagManager::<T>::ensure_bag_exists(dest_bag_id)?;
  1588. let mut bag_change = BagChangeInfo::<BalanceOf<T>>::default();
  1589. for object_id in object_ids.iter() {
  1590. let data_object = BagManager::<T>::ensure_data_object_existence(src_bag_id, object_id)?;
  1591. bag_change.add_object(data_object.size, data_object.deletion_prize);
  1592. }
  1593. Self::check_bag_for_buckets_overflow(dest_bag_id, &bag_change.voucher_update)?;
  1594. Ok(bag_change)
  1595. }
  1596. // Returns only existing hashes in the blacklist from the original collection.
  1597. #[allow(clippy::redundant_closure)] // doesn't work with Substrate storage functions.
  1598. fn get_existing_hashes(hashes: &BTreeSet<ContentId>) -> BTreeSet<ContentId> {
  1599. Self::get_hashes_by_predicate(hashes, |cid| Blacklist::contains_key(cid))
  1600. }
  1601. // Returns only nonexisting hashes in the blacklist from the original collection.
  1602. fn get_nonexisting_hashes(hashes: &BTreeSet<ContentId>) -> BTreeSet<ContentId> {
  1603. Self::get_hashes_by_predicate(hashes, |cid| !Blacklist::contains_key(cid))
  1604. }
  1605. // Returns hashes from the original collection selected by predicate.
  1606. fn get_hashes_by_predicate<P: FnMut(&&ContentId) -> bool>(
  1607. hashes: &BTreeSet<ContentId>,
  1608. predicate: P,
  1609. ) -> BTreeSet<ContentId> {
  1610. hashes
  1611. .iter()
  1612. .filter(predicate)
  1613. .cloned()
  1614. .collect::<BTreeSet<_>>()
  1615. }
  1616. // Ensure the new bucket could be created. It also validates some parameters.
  1617. fn can_create_storage_bucket(
  1618. voucher: &Voucher,
  1619. invited_worker: &Option<WorkerId<T>>,
  1620. ) -> DispatchResult {
  1621. ensure!(
  1622. Self::storage_buckets_number() < T::MaxStorageBucketNumber::get(),
  1623. Error::<T>::MaxStorageBucketNumberLimitExceeded
  1624. );
  1625. ensure!(
  1626. voucher.size_limit <= Self::voucher_max_objects_size_limit(),
  1627. Error::<T>::VoucherMaxObjectSizeLimitExceeded
  1628. );
  1629. ensure!(
  1630. voucher.objects_limit <= Self::voucher_max_objects_number_limit(),
  1631. Error::<T>::VoucherMaxObjectNumberLimitExceeded
  1632. );
  1633. if let Some(operator_id) = invited_worker {
  1634. Self::ensure_storage_provider_operator_exists(operator_id)?;
  1635. }
  1636. Ok(())
  1637. }
  1638. // Update total objects size and number for all storage buckets assigned to a bag.
  1639. fn change_storage_bucket_vouchers_for_bag(
  1640. bag_id: &BagId<T>,
  1641. voucher_update: &VoucherUpdate,
  1642. voucher_operation: OperationType,
  1643. ) {
  1644. let bucket_ids = BagManager::<T>::get_storage_bucket_ids(bag_id);
  1645. Self::change_storage_buckets_vouchers(&bucket_ids, voucher_update, voucher_operation);
  1646. }
  1647. // Update total objects size and number for provided storage buckets.
  1648. fn change_storage_buckets_vouchers(
  1649. bucket_ids: &BTreeSet<T::StorageBucketId>,
  1650. voucher_update: &VoucherUpdate,
  1651. voucher_operation: OperationType,
  1652. ) {
  1653. for bucket_id in bucket_ids.iter() {
  1654. <StorageBucketById<T>>::mutate(bucket_id, |bucket| {
  1655. bucket.voucher =
  1656. voucher_update.get_updated_voucher(&bucket.voucher, voucher_operation);
  1657. Self::deposit_event(RawEvent::VoucherChanged(*bucket_id, bucket.voucher.clone()));
  1658. });
  1659. }
  1660. }
  1661. // Validates `delete_data_objects` parameters.
  1662. // Returns voucher update for an affected bag.
  1663. fn validate_delete_data_objects_params(
  1664. bag_id: &BagId<T>,
  1665. data_object_ids: &BTreeSet<T::DataObjectId>,
  1666. ) -> Result<BagChangeInfo<BalanceOf<T>>, DispatchError> {
  1667. ensure!(
  1668. !data_object_ids.is_empty(),
  1669. Error::<T>::DataObjectIdParamsAreEmpty
  1670. );
  1671. BagManager::<T>::ensure_bag_exists(bag_id)?;
  1672. let mut bag_change = BagChangeInfo::default();
  1673. for data_object_id in data_object_ids.iter() {
  1674. let data_object =
  1675. BagManager::<T>::ensure_data_object_existence(bag_id, data_object_id)?;
  1676. bag_change.add_object(data_object.size, data_object.deletion_prize);
  1677. }
  1678. ensure!(
  1679. <StorageTreasury<T>>::usable_balance() >= bag_change.total_deletion_prize,
  1680. Error::<T>::InsufficientTreasuryBalance
  1681. );
  1682. Ok(bag_change)
  1683. }
  1684. // Validates upload parameters and conditions (like global uploading block).
  1685. // Returns voucher update parameters for the storage buckets.
  1686. fn validate_upload_data_objects_parameters(
  1687. params: &UploadParameters<T>,
  1688. ) -> Result<BagChangeInfo<BalanceOf<T>>, DispatchError> {
  1689. // TODO: consider refactoring and splitting the method.
  1690. // Check global uploading block.
  1691. ensure!(!Self::uploading_blocked(), Error::<T>::UploadingBlocked);
  1692. // Check object creation list validity.
  1693. ensure!(
  1694. !params.object_creation_list.is_empty(),
  1695. Error::<T>::NoObjectsOnUpload
  1696. );
  1697. BagManager::<T>::ensure_bag_exists(&params.bag_id)?;
  1698. let bag_objects_number = BagManager::<T>::get_data_objects_number(&params.bag_id.clone());
  1699. let new_objects_number: u64 = params.object_creation_list.len().saturated_into();
  1700. let total_possible_data_objects_number: u64 = new_objects_number + bag_objects_number;
  1701. // Check bag capacity.
  1702. ensure!(
  1703. total_possible_data_objects_number <= T::MaxNumberOfDataObjectsPerBag::get(),
  1704. Error::<T>::DataObjectsPerBagLimitExceeded
  1705. );
  1706. let mut bag_change = BagChangeInfo::default();
  1707. // Check data objects.
  1708. for object_params in params.object_creation_list.iter() {
  1709. // Should be non-empty hash.
  1710. ensure!(
  1711. !object_params.ipfs_content_id.is_empty(),
  1712. Error::<T>::EmptyContentId
  1713. );
  1714. // Should be non-zero size.
  1715. ensure!(object_params.size != 0, Error::<T>::ZeroObjectSize);
  1716. // Should not be blacklisted.
  1717. ensure!(
  1718. !Blacklist::contains_key(&object_params.ipfs_content_id),
  1719. Error::<T>::DataObjectBlacklisted,
  1720. );
  1721. bag_change.add_object(object_params.size, T::DataObjectDeletionPrize::get());
  1722. }
  1723. let size_fee =
  1724. Self::calculate_data_storage_fee(bag_change.voucher_update.objects_total_size);
  1725. let usable_balance =
  1726. Balances::<T>::usable_balance(&params.deletion_prize_source_account_id);
  1727. // Check account balance to satisfy deletion prize and storage fee.
  1728. let total_fee = bag_change.total_deletion_prize + size_fee;
  1729. ensure!(usable_balance >= total_fee, Error::<T>::InsufficientBalance);
  1730. // Check buckets.
  1731. Self::check_bag_for_buckets_overflow(&params.bag_id, &bag_change.voucher_update)?;
  1732. Ok(bag_change)
  1733. }
  1734. // Iterates through buckets in the bag. Verifies voucher parameters to fit the new limits:
  1735. // objects number and total objects size.
  1736. fn check_bag_for_buckets_overflow(
  1737. bag_id: &BagId<T>,
  1738. voucher_update: &VoucherUpdate,
  1739. ) -> DispatchResult {
  1740. let bucket_ids = BagManager::<T>::get_storage_bucket_ids(bag_id);
  1741. Self::check_buckets_for_overflow(&bucket_ids, voucher_update)
  1742. }
  1743. // Iterates through buckets. Verifies voucher parameters to fit the new limits:
  1744. // objects number and total objects size.
  1745. fn check_buckets_for_overflow(
  1746. bucket_ids: &BTreeSet<T::StorageBucketId>,
  1747. voucher_update: &VoucherUpdate,
  1748. ) -> DispatchResult {
  1749. for bucket_id in bucket_ids.iter() {
  1750. let bucket = Self::storage_bucket_by_id(bucket_id);
  1751. // Total object number limit is not exceeded.
  1752. ensure!(
  1753. voucher_update.objects_number + bucket.voucher.objects_used
  1754. <= bucket.voucher.objects_limit,
  1755. Error::<T>::StorageBucketObjectNumberLimitReached
  1756. );
  1757. // Total object size limit is not exceeded.
  1758. ensure!(
  1759. voucher_update.objects_total_size + bucket.voucher.size_used
  1760. <= bucket.voucher.size_limit,
  1761. Error::<T>::StorageBucketObjectSizeLimitReached
  1762. );
  1763. }
  1764. Ok(())
  1765. }
  1766. // Increase or decrease a deletion prize for a dynamic bag.
  1767. fn change_deletion_prize_for_dynamic_bag(
  1768. dynamic_bag_id: &DynamicBagId<T>,
  1769. deletion_prize: BalanceOf<T>,
  1770. operation: OperationType,
  1771. ) {
  1772. <DynamicBags<T>>::mutate(dynamic_bag_id, |bag| {
  1773. bag.deletion_prize = match operation {
  1774. OperationType::Increase => bag.deletion_prize.saturating_add(deletion_prize),
  1775. OperationType::Decrease => bag.deletion_prize.saturating_sub(deletion_prize),
  1776. };
  1777. Self::deposit_event(RawEvent::DeletionPrizeChanged(
  1778. dynamic_bag_id.clone(),
  1779. bag.deletion_prize,
  1780. ));
  1781. });
  1782. }
  1783. // Increase or decrease a deletion prize for a dynamic bag.
  1784. // Affect dynamic bags only. Skips static bags.
  1785. fn change_deletion_prize_for_bag(
  1786. bag_id: &BagId<T>,
  1787. deletion_prize: BalanceOf<T>,
  1788. operation: OperationType,
  1789. ) {
  1790. if let BagId::<T>::DynamicBag(ref dynamic_bag_id) = bag_id {
  1791. Self::change_deletion_prize_for_dynamic_bag(dynamic_bag_id, deletion_prize, operation);
  1792. }
  1793. }
  1794. // Calculate data storage fee based on size. Fee-value uses megabytes as measure value.
  1795. // Data size will be rounded to nearest greater MB integer.
  1796. pub(crate) fn calculate_data_storage_fee(bytes: u64) -> BalanceOf<T> {
  1797. let mb_fee = Self::data_object_per_mega_byte_fee();
  1798. const ONE_MB: u64 = 1_048_576;
  1799. let mut megabytes = bytes / ONE_MB;
  1800. if bytes % ONE_MB > 0 {
  1801. megabytes += 1; // rounding to the nearest greater integer
  1802. }
  1803. mb_fee.saturating_mul(megabytes.saturated_into())
  1804. }
  1805. // Slash data size fee if fee value is set to non-zero.
  1806. fn slash_data_size_fee(account_id: &T::AccountId, bytes: u64) {
  1807. let fee = Self::calculate_data_storage_fee(bytes);
  1808. if fee != Zero::zero() {
  1809. let _ = Balances::<T>::slash(account_id, fee);
  1810. }
  1811. }
  1812. // Selects storage bucket ID sets to assign to the storage bucket.
  1813. pub(crate) fn pick_storage_buckets_for_dynamic_bag(
  1814. bag_type: DynamicBagType,
  1815. ) -> BTreeSet<T::StorageBucketId> {
  1816. StorageBucketPicker::<T>::pick_storage_buckets(bag_type)
  1817. }
  1818. // Get default dynamic bag policy by bag type.
  1819. fn get_default_dynamic_bag_creation_policy(
  1820. bag_type: DynamicBagType,
  1821. ) -> DynamicBagCreationPolicy {
  1822. match bag_type {
  1823. DynamicBagType::Member => T::DefaultMemberDynamicBagCreationPolicy::get(),
  1824. DynamicBagType::Channel => T::DefaultChannelDynamicBagCreationPolicy::get(),
  1825. }
  1826. }
  1827. // Loads dynamic bag creation policy or use default values.
  1828. pub(crate) fn get_dynamic_bag_creation_policy(
  1829. bag_type: DynamicBagType,
  1830. ) -> DynamicBagCreationPolicy {
  1831. if DynamicBagCreationPolicies::contains_key(bag_type) {
  1832. return Self::dynamic_bag_creation_policy(bag_type);
  1833. }
  1834. Self::get_default_dynamic_bag_creation_policy(bag_type)
  1835. }
  1836. // Verifies storage provider operator existence.
  1837. fn ensure_storage_provider_operator_exists(operator_id: &WorkerId<T>) -> DispatchResult {
  1838. ensure!(
  1839. T::ensure_worker_exists(operator_id).is_ok(),
  1840. Error::<T>::StorageProviderOperatorDoesntExist
  1841. );
  1842. Ok(())
  1843. }
  1844. }