lib.rs 132 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823
  1. //! # Storage module
  2. //! Storage module for the Joystream platform.
  3. //!
  4. //! Initial spec links:
  5. //! - [spec](https://github.com/Joystream/joystream/issues/2224)
  6. //! - [utilization model](https://github.com/Joystream/joystream/issues/2359)
  7. //!
  8. //! Pallet functionality could be split in five distinct groups:
  9. //! - extrinsics for the storage working group leader
  10. //! - extrinsics for the distribution group leader
  11. //! - extrinsics for the storage provider
  12. //! - extrinsics for the distribution provider
  13. //! - public methods for the pallet integration
  14. //!
  15. //! #### Storage working group leader extrinsics
  16. //! - [create_storage_bucket](./struct.Module.html#method.create_storage_bucket) - creates storage
  17. //! bucket.
  18. //! - [update_storage_buckets_for_bag](./struct.Module.html#method.update_storage_buckets_for_bag) -
  19. //! updates storage buckets for a bag.
  20. //! - [delete_storage_bucket](./struct.Module.html#method.delete_storage_bucket) - deletes storage
  21. //! bucket.
  22. //! - [invite_storage_bucket_operator](./struct.Module.html#method.invite_storage_bucket_operator) -
  23. //! invites storage bucket operator.
  24. //! - [cancel_storage_bucket_operator_invite](./struct.Module.html#method.cancel_storage_bucket_operator_invite) -
  25. //! cancels pending storage bucket invite.
  26. //! - [remove_storage_bucket_operator](./struct.Module.html#method.remove_storage_bucket_operator) -
  27. //! removes storage bucket operator.
  28. //! - [update_uploading_blocked_status](./struct.Module.html#method.update_uploading_blocked_status) -
  29. //! updates global uploading status.
  30. //! - [update_data_size_fee](./struct.Module.html#method.update_data_size_fee) - updates size-based
  31. //! pricing of new objects uploaded.
  32. //! - [update_storage_buckets_per_bag_limit](./struct.Module.html#method.update_storage_buckets_per_bag_limit) -
  33. //! updates "Storage buckets per bag" number limit.
  34. //! - [update_storage_buckets_voucher_max_limits](./struct.Module.html#method.update_storage_buckets_voucher_max_limits) -
  35. //! updates "Storage buckets voucher max limits".
  36. //! - [update_number_of_storage_buckets_in_dynamic_bag_creation_policy](./struct.Module.html#method.update_number_of_storage_buckets_in_dynamic_bag_creation_policy) -
  37. //! updates number of storage buckets used in given dynamic bag creation policy.
  38. //! - [update_blacklist](./struct.Module.html#method.update_blacklist) - adds and removes hashes to
  39. //! the current blacklist.
  40. //! - [update_storage_bucket_status](./struct.Module.html#method.update_storage_bucket_status) -
  41. //! updates whether new bags are being accepted for storage.
  42. //! - [set_storage_bucket_voucher_limits](./struct.Module.html#method.set_storage_bucket_voucher_limits) -
  43. //! sets storage bucket voucher limits.
  44. //!
  45. //!
  46. //! #### Storage provider extrinsics
  47. //! - [accept_storage_bucket_invitation](./struct.Module.html#method.accept_storage_bucket_invitation) -
  48. //! accepts the storage bucket invitation.
  49. //! - [set_storage_operator_metadata](./struct.Module.html#method.set_storage_operator_metadata) -
  50. //! sets storage operator metadata.
  51. //! - [accept_pending_data_objects](./struct.Module.html#method.accept_pending_data_objects) - a
  52. //! storage provider signals that the data object was successfully uploaded to its storage.
  53. //!
  54. //! #### Distribution working group leader extrinsics
  55. //! - [create_distribution_bucket_family](./struct.Module.html#method.create_distribution_bucket_family) -
  56. //! creates distribution bucket family.
  57. //! - [delete_distribution_bucket_family](./struct.Module.html#method.delete_distribution_bucket_family) -
  58. //! deletes distribution bucket family.
  59. //! - [create_distribution_bucket](./struct.Module.html#method.create_distribution_bucket) -
  60. //! creates distribution bucket.
  61. //! - [delete_distribution_bucket](./struct.Module.html#method.delete_distribution_bucket) -
  62. //! deletes distribution bucket.
  63. //! - [update_distribution_bucket_status](./struct.Module.html#method.update_distribution_bucket_status) -
  64. //! updates distribution bucket status (accepting new bags).
  65. //! - [update_distribution_buckets_for_bag](./struct.Module.html#method.update_distribution_buckets_for_bag) -
  66. //! updates distribution buckets for a bag.
  67. //! - [distribution_buckets_per_bag_limit](./struct.Module.html#method.distribution_buckets_per_bag_limit) -
  68. //! updates "Distribution buckets per bag" number limit.
  69. //! - [update_distribution_bucket_mode](./struct.Module.html#method.distribution_buckets_per_bag_limit) -
  70. //! updates "distributing" flag for a distribution bucket.
  71. //! - [update_families_in_dynamic_bag_creation_policy](./struct.Module.html#method.update_families_in_dynamic_bag_creation_policy) -
  72. //! updates distribution bucket families used in given dynamic bag creation policy.
  73. //! - [invite_distribution_bucket_operator](./struct.Module.html#method.invite_distribution_bucket_operator) -
  74. //! invites a distribution bucket operator.
  75. //! - [cancel_distribution_bucket_operator_invite](./struct.Module.html#method.cancel_distribution_bucket_operator_invite) -
  76. //! Cancels pending invite for a distribution bucket.
  77. //! - [remove_distribution_bucket_operator](./struct.Module.html#method.remove_distribution_bucket_operator) -
  78. //! Removes a distribution bucket operator.
  79. //! - [set_distribution_bucket_family_metadata](./struct.Module.html#method.set_distribution_bucket_family_metadata) -
  80. //! Sets distribution bucket family metadata.
  81. //!
  82. //! #### Distribution provider extrinsics
  83. //! - [accept_distribution_bucket_invitation](./struct.Module.html#method.accept_distribution_bucket_invitation) -
  84. //! Accepts pending invite for a distribution bucket.
  85. //! - [set_distribution_operator_metadata](./struct.Module.html#method.set_distribution_operator_metadata) -
  86. //! Set distribution operator metadata for the distribution bucket.
  87. //!
  88. //! #### Public methods
  89. //! Public integration methods are exposed via the [DataObjectStorage](./trait.DataObjectStorage.html)
  90. //! - can_upload_data_objects
  91. //! - upload_data_objects
  92. //! - can_move_data_objects
  93. //! - move_data_objects
  94. //! - can_delete_data_objects
  95. //! - delete_data_objects
  96. //! - can_delete_dynamic_bag
  97. //! - delete_dynamic_bag
  98. //! - can_create_dynamic_bag
  99. //! - create_dynamic_bag
  100. //! - can_create_dynamic_bag_with_objects_constraints
  101. //! - create_dynamic_bag_with_objects_constraints
  102. //! - can_delete_non_empty_dynamic_bag
  103. //!
  104. //! ### Pallet constants
  105. //! - DataObjectDeletionPrize
  106. //! - BlacklistSizeLimit
  107. //! - StorageBucketsPerBagValueConstraint
  108. //! - DefaultMemberDynamicBagNumberOfStorageBuckets
  109. //! - DefaultChannelDynamicBagNumberOfStorageBuckets
  110. //! - MaxDistributionBucketFamilyNumber
  111. //! - DistributionBucketsPerBagValueConstraint
  112. //! - MaxNumberOfPendingInvitationsPerDistributionBucket
  113. // Compiler demand.
  114. #![recursion_limit = "256"]
  115. // Ensure we're `no_std` when compiling for Wasm.
  116. #![cfg_attr(not(feature = "std"), no_std)]
  117. // #![warn(missing_docs)] // Cannot be enabled by default because of the Substrate issue.
  118. // Internal Substrate warning (decl_event).
  119. #![allow(clippy::unused_unit)]
  120. // needed for step iteration over DataObjectId range
  121. #![feature(step_trait)]
  122. #[cfg(test)]
  123. mod tests;
  124. #[cfg(feature = "runtime-benchmarks")]
  125. mod benchmarking;
  126. //pub(crate) mod distribution_bucket_picker;
  127. pub(crate) mod random_buckets;
  128. use codec::{Codec, Decode, Encode};
  129. use frame_support::dispatch::{DispatchError, DispatchResult};
  130. use frame_support::traits::{Currency, ExistenceRequirement, Get, Randomness};
  131. use frame_support::{
  132. decl_error, decl_event, decl_module, decl_storage, ensure, IterableStorageDoubleMap, Parameter,
  133. };
  134. use frame_system::ensure_root;
  135. #[cfg(feature = "std")]
  136. use serde::{Deserialize, Serialize};
  137. use sp_arithmetic::traits::{BaseArithmetic, One, Zero};
  138. use sp_runtime::traits::{AccountIdConversion, MaybeSerialize, Member, Saturating};
  139. use sp_runtime::{ModuleId, SaturatedConversion};
  140. use sp_std::collections::btree_map::BTreeMap;
  141. use sp_std::collections::btree_set::BTreeSet;
  142. use sp_std::iter;
  143. use sp_std::marker::PhantomData;
  144. use sp_std::vec::Vec;
  145. use common::constraints::BoundedValueConstraint;
  146. use common::origin::ActorOriginValidator;
  147. use common::working_group::WorkingGroup;
  148. use random_buckets::DistributionBucketPicker;
  149. use random_buckets::StorageBucketPicker;
  150. /// Public interface for the storage module.
  151. pub trait DataObjectStorage<T: Trait> {
  152. /// Validates upload parameters and conditions (like global uploading block).
  153. /// Validates voucher usage for affected buckets.
  154. fn can_upload_data_objects(params: &UploadParameters<T>) -> DispatchResult;
  155. /// Upload new data objects.
  156. fn upload_data_objects(params: UploadParameters<T>) -> DispatchResult;
  157. /// Validates moving objects parameters.
  158. /// Validates voucher usage for affected buckets.
  159. fn can_move_data_objects(
  160. src_bag_id: &BagId<T>,
  161. dest_bag_id: &BagId<T>,
  162. objects: &BTreeSet<T::DataObjectId>,
  163. ) -> DispatchResult;
  164. /// Move data objects to a new bag.
  165. fn move_data_objects(
  166. src_bag_id: BagId<T>,
  167. dest_bag_id: BagId<T>,
  168. objects: BTreeSet<T::DataObjectId>,
  169. ) -> DispatchResult;
  170. /// Validates `delete_data_objects` parameters.
  171. /// Validates voucher usage for affected buckets.
  172. fn can_delete_data_objects(
  173. bag_id: &BagId<T>,
  174. objects: &BTreeSet<T::DataObjectId>,
  175. ) -> DispatchResult;
  176. /// Delete storage objects. Transfer deletion prize to the provided account.
  177. fn delete_data_objects(
  178. deletion_prize_account_id: T::AccountId,
  179. bag_id: BagId<T>,
  180. objects: BTreeSet<T::DataObjectId>,
  181. ) -> DispatchResult;
  182. /// Delete dynamic bag. Updates related storage bucket vouchers.
  183. fn delete_dynamic_bag(
  184. deletion_prize_account_id: T::AccountId,
  185. bag_id: DynamicBagId<T>,
  186. ) -> DispatchResult;
  187. /// Validates `delete_dynamic_bag` parameters and conditions.
  188. fn can_delete_dynamic_bag(bag_id: &DynamicBagId<T>) -> DispatchResult;
  189. /// Validates `delete_dynamic_bag` without checking for num objects == 0
  190. fn can_delete_dynamic_bag_with_objects(bag_id: &DynamicBagId<T>) -> DispatchResult;
  191. /// Creates dynamic bag. BagId should provide the caller.
  192. fn create_dynamic_bag(
  193. bag_id: DynamicBagId<T>,
  194. deletion_prize: Option<DynamicBagDeletionPrize<T>>,
  195. ) -> DispatchResult;
  196. /// Validates `create_dynamic_bag` parameters and conditions.
  197. fn can_create_dynamic_bag(
  198. bag_id: &DynamicBagId<T>,
  199. deletion_prize: &Option<DynamicBagDeletionPrize<T>>,
  200. ) -> DispatchResult;
  201. /// Same as create_dynamic_bag but with caller provided objects/data
  202. fn create_dynamic_bag_with_objects_constraints(
  203. bag_id: DynamicBagId<T>,
  204. deletion_prize: Option<DynamicBagDeletionPrize<T>>,
  205. params: UploadParameters<T>,
  206. ) -> DispatchResult;
  207. /// Same as can_create_dynamic_bag but with caller provided objects/data
  208. fn can_create_dynamic_bag_with_objects_constraints(
  209. bag_id: &DynamicBagId<T>,
  210. deletion_prize: &Option<DynamicBagDeletionPrize<T>>,
  211. params: &UploadParameters<T>,
  212. ) -> DispatchResult;
  213. /// Checks if a bag does exists and returns it. Static Always exists
  214. fn ensure_bag_exists(bag_id: &BagId<T>) -> Result<Bag<T>, DispatchError>;
  215. /// Get all objects id in a bag, without checking its existence
  216. fn get_data_objects_id(bag_id: &BagId<T>) -> BTreeSet<T::DataObjectId>;
  217. }
  218. /// Storage trait.
  219. pub trait Trait: frame_system::Trait + balances::Trait + membership::Trait {
  220. /// Storage event type.
  221. type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
  222. /// Content id representation.
  223. type ContentId: Parameter + Member + Codec + Default + Copy + MaybeSerialize + Ord + PartialEq;
  224. /// Data object ID type.
  225. type DataObjectId: Parameter
  226. + Member
  227. + BaseArithmetic
  228. + Codec
  229. + Default
  230. + Copy
  231. + MaybeSerialize
  232. + PartialEq
  233. + iter::Step; // needed for iteration
  234. /// Storage bucket ID type.
  235. type StorageBucketId: Parameter
  236. + Member
  237. + BaseArithmetic
  238. + Codec
  239. + Default
  240. + Copy
  241. + MaybeSerialize
  242. + PartialEq
  243. + Into<u64>
  244. + From<u64>;
  245. /// Distribution bucket index within a distribution bucket family type.
  246. type DistributionBucketIndex: Parameter
  247. + Member
  248. + BaseArithmetic
  249. + Codec
  250. + Default
  251. + Copy
  252. + MaybeSerialize
  253. + PartialEq
  254. + Into<u64>
  255. + From<u64>;
  256. /// Distribution bucket family ID type.
  257. type DistributionBucketFamilyId: Parameter
  258. + Member
  259. + BaseArithmetic
  260. + Codec
  261. + Default
  262. + Copy
  263. + MaybeSerialize
  264. + PartialEq;
  265. /// Channel ID type (part of the dynamic bag ID).
  266. type ChannelId: Parameter
  267. + Member
  268. + BaseArithmetic
  269. + Codec
  270. + Default
  271. + Copy
  272. + MaybeSerialize
  273. + PartialEq;
  274. /// Distribution bucket operator ID type (relationship between distribution bucket and
  275. /// distribution operator).
  276. type DistributionBucketOperatorId: Parameter
  277. + Member
  278. + BaseArithmetic
  279. + Codec
  280. + Default
  281. + Copy
  282. + MaybeSerialize
  283. + PartialEq;
  284. /// Defines a prize for a data object deletion.
  285. type DataObjectDeletionPrize: Get<BalanceOf<Self>>;
  286. /// Defines maximum size of the "hash blacklist" collection.
  287. type BlacklistSizeLimit: Get<u64>;
  288. /// The module id, used for deriving its sovereign account ID.
  289. type ModuleId: Get<ModuleId>;
  290. /// Validates member id and origin combination.
  291. type MemberOriginValidator: ActorOriginValidator<Self::Origin, MemberId<Self>, Self::AccountId>;
  292. /// "Storage buckets per bag" value constraint.
  293. type StorageBucketsPerBagValueConstraint: Get<StorageBucketsPerBagValueConstraint>;
  294. /// "Distribution buckets per bag" value constraint.
  295. type DistributionBucketsPerBagValueConstraint: Get<DistributionBucketsPerBagValueConstraint>;
  296. /// Defines the default dynamic bag creation policy for members (storage bucket number).
  297. type DefaultMemberDynamicBagNumberOfStorageBuckets: Get<u64>;
  298. /// Defines the default dynamic bag creation policy for channels (storage bucket number).
  299. type DefaultChannelDynamicBagNumberOfStorageBuckets: Get<u64>;
  300. /// Defines max random iteration number (eg.: when picking the storage buckets).
  301. type MaxRandomIterationNumber: Get<u64>;
  302. /// Something that provides randomness in the runtime.
  303. type Randomness: Randomness<Self::Hash>;
  304. /// Defines max allowed distribution bucket family number.
  305. type MaxDistributionBucketFamilyNumber: Get<u64>;
  306. /// Max number of pending invitations per distribution bucket.
  307. type MaxNumberOfPendingInvitationsPerDistributionBucket: Get<u64>;
  308. /// Max data object size in bytes.
  309. type MaxDataObjectSize: Get<u64>;
  310. /// Demand the storage working group leader authorization.
  311. /// TODO: Refactor after merging with the Olympia release.
  312. fn ensure_storage_working_group_leader_origin(origin: Self::Origin) -> DispatchResult;
  313. /// Validate origin for the storage worker.
  314. /// TODO: Refactor after merging with the Olympia release.
  315. fn ensure_storage_worker_origin(
  316. origin: Self::Origin,
  317. worker_id: WorkerId<Self>,
  318. ) -> DispatchResult;
  319. /// Validate storage worker existence.
  320. /// TODO: Refactor after merging with the Olympia release.
  321. fn ensure_storage_worker_exists(worker_id: &WorkerId<Self>) -> DispatchResult;
  322. /// Demand the distribution group leader authorization.
  323. /// TODO: Refactor after merging with the Olympia release.
  324. fn ensure_distribution_working_group_leader_origin(origin: Self::Origin) -> DispatchResult;
  325. /// Validate origin for the distribution worker.
  326. /// TODO: Refactor after merging with the Olympia release.
  327. fn ensure_distribution_worker_origin(
  328. origin: Self::Origin,
  329. worker_id: WorkerId<Self>,
  330. ) -> DispatchResult;
  331. /// Validate distribution worker existence.
  332. /// TODO: Refactor after merging with the Olympia release.
  333. fn ensure_distribution_worker_exists(worker_id: &WorkerId<Self>) -> DispatchResult;
  334. }
  335. /// Operations with local pallet account.
  336. pub trait ModuleAccount<T: balances::Trait> {
  337. /// The module id, used for deriving its sovereign account ID.
  338. type ModuleId: Get<ModuleId>;
  339. /// The account ID of the module account.
  340. fn module_account_id() -> T::AccountId {
  341. Self::ModuleId::get().into_sub_account(Vec::<u8>::new())
  342. }
  343. /// Transfer tokens from the module account to the destination account (spends from
  344. /// module account).
  345. fn withdraw(dest_account_id: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {
  346. <Balances<T> as Currency<T::AccountId>>::transfer(
  347. &Self::module_account_id(),
  348. dest_account_id,
  349. amount,
  350. ExistenceRequirement::AllowDeath,
  351. )
  352. }
  353. /// Transfer tokens from the destination account to the module account (fills module account).
  354. fn deposit(src_account_id: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {
  355. <Balances<T> as Currency<T::AccountId>>::transfer(
  356. src_account_id,
  357. &Self::module_account_id(),
  358. amount,
  359. ExistenceRequirement::AllowDeath,
  360. )
  361. }
  362. /// Displays usable balance for the module account.
  363. fn usable_balance() -> BalanceOf<T> {
  364. <Balances<T>>::usable_balance(&Self::module_account_id())
  365. }
  366. }
  367. /// Implementation of the ModuleAccountHandler.
  368. pub struct ModuleAccountHandler<T: balances::Trait, ModId: Get<ModuleId>> {
  369. /// Phantom marker for the trait.
  370. trait_marker: PhantomData<T>,
  371. /// Phantom marker for the module id type.
  372. module_id_marker: PhantomData<ModId>,
  373. }
  374. impl<T: balances::Trait, ModId: Get<ModuleId>> ModuleAccount<T> for ModuleAccountHandler<T, ModId> {
  375. type ModuleId = ModId;
  376. }
  377. /// Holds parameter values impacting how exactly the creation of a new dynamic bag occurs,
  378. /// and there is one such policy for each type of dynamic bag.
  379. /// It describes how many storage buckets should store the bag.
  380. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  381. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  382. pub struct DynamicBagCreationPolicy<DistributionBucketFamilyId: Ord> {
  383. /// The number of storage buckets which should replicate the new bag.
  384. pub number_of_storage_buckets: u64,
  385. /// The set of distribution bucket families which should be sampled
  386. /// to distribute bag, and for each the number of buckets in that family
  387. /// which should be used.
  388. pub families: BTreeMap<DistributionBucketFamilyId, u32>,
  389. }
  390. impl<DistributionBucketFamilyId: Ord> DynamicBagCreationPolicy<DistributionBucketFamilyId> {
  391. // Verifies non-zero number of storage buckets.
  392. pub(crate) fn no_storage_buckets_required(&self) -> bool {
  393. self.number_of_storage_buckets == 0
  394. }
  395. // Verifies non-zero number of required distribution buckets.
  396. pub(crate) fn no_distribution_buckets_required(&self) -> bool {
  397. self.families.iter().map(|(_, num)| num).sum::<u32>() == 0
  398. }
  399. }
  400. /// "Storage buckets per bag" value constraint type.
  401. pub type StorageBucketsPerBagValueConstraint = BoundedValueConstraint<u64>;
  402. /// "Distribution buckets per bag" value constraint type.
  403. pub type DistributionBucketsPerBagValueConstraint = BoundedValueConstraint<u64>;
  404. /// Local module account handler.
  405. pub type StorageTreasury<T> = ModuleAccountHandler<T, <T as Trait>::ModuleId>;
  406. /// IPFS hash type alias (content ID).
  407. pub type Cid = Vec<u8>;
  408. // Alias for the Substrate balances pallet.
  409. type Balances<T> = balances::Module<T>;
  410. /// Alias for the member id.
  411. pub type MemberId<T> = <T as common::MembershipTypes>::MemberId;
  412. /// Type identifier for worker role, which must be same as membership actor identifier
  413. pub type WorkerId<T> = <T as common::MembershipTypes>::ActorId;
  414. /// Balance alias for `balances` module.
  415. pub type BalanceOf<T> = <T as balances::Trait>::Balance;
  416. /// Type alias for the storage & distribution bucket ids pair
  417. pub type BucketPair<T> = (
  418. BTreeSet<<T as Trait>::StorageBucketId>,
  419. BTreeSet<DistributionBucketId<T>>,
  420. );
  421. /// The fundamental concept in the system, which represents single static binary object in the
  422. /// system. The main goal of the system is to retain an index of all such objects, including who
  423. /// owns them, and information about what actors are currently tasked with storing and distributing
  424. /// them to end users. The system is unaware of the underlying content represented by such an
  425. /// object, as it is used by different parts of the Joystream system.
  426. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  427. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  428. pub struct DataObject<Balance> {
  429. /// Defines whether the data object was accepted by a liason.
  430. pub accepted: bool,
  431. /// A reward for the data object deletion.
  432. pub deletion_prize: Balance,
  433. /// Object size in bytes.
  434. pub size: u64,
  435. /// Content identifier presented as IPFS hash.
  436. pub ipfs_content_id: Vec<u8>,
  437. }
  438. /// Type alias for the BagRecord.
  439. pub type Bag<T> = BagRecord<<T as Trait>::StorageBucketId, DistributionBucketId<T>, BalanceOf<T>>;
  440. /// Bag container.
  441. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  442. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  443. pub struct BagRecord<StorageBucketId: Ord, DistributionBucketId: Ord, Balance> {
  444. /// Associated storage buckets.
  445. pub stored_by: BTreeSet<StorageBucketId>,
  446. /// Associated distribution buckets.
  447. pub distributed_by: BTreeSet<DistributionBucketId>,
  448. /// Bag deletion prize (valid for dynamic bags).
  449. pub deletion_prize: Option<Balance>,
  450. /// Total object size for bag.
  451. pub objects_total_size: u64,
  452. /// Total object number for bag.
  453. pub objects_number: u64,
  454. }
  455. impl<StorageBucketId: Ord, DistributionBucketId: Ord, Balance>
  456. BagRecord<StorageBucketId, DistributionBucketId, Balance>
  457. {
  458. // Add and/or remove storage buckets.
  459. fn update_storage_buckets(
  460. &mut self,
  461. add_buckets: &mut BTreeSet<StorageBucketId>,
  462. remove_buckets: &BTreeSet<StorageBucketId>,
  463. ) {
  464. if !add_buckets.is_empty() {
  465. self.stored_by.append(add_buckets);
  466. }
  467. if !remove_buckets.is_empty() {
  468. for bucket_id in remove_buckets.iter() {
  469. self.stored_by.remove(bucket_id);
  470. }
  471. }
  472. }
  473. // Add and/or remove distribution buckets.
  474. fn update_distribution_buckets(
  475. &mut self,
  476. add_buckets: &mut BTreeSet<DistributionBucketId>,
  477. remove_buckets: &BTreeSet<DistributionBucketId>,
  478. ) {
  479. if !add_buckets.is_empty() {
  480. self.distributed_by.append(add_buckets);
  481. }
  482. if !remove_buckets.is_empty() {
  483. for bucket_id in remove_buckets.iter() {
  484. self.distributed_by.remove(bucket_id);
  485. }
  486. }
  487. }
  488. }
  489. /// Parameters for the data object creation.
  490. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  491. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  492. pub struct DataObjectCreationParameters {
  493. /// Object size in bytes.
  494. pub size: u64,
  495. /// Content identifier presented as IPFS hash.
  496. pub ipfs_content_id: Vec<u8>,
  497. }
  498. /// Type alias for the BagIdType.
  499. pub type BagId<T> = BagIdType<MemberId<T>, <T as Trait>::ChannelId>;
  500. /// Identifier for a bag.
  501. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  502. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
  503. pub enum BagIdType<MemberId, ChannelId> {
  504. /// Static bag type.
  505. Static(StaticBagId),
  506. /// Dynamic bag type.
  507. Dynamic(DynamicBagIdType<MemberId, ChannelId>),
  508. }
  509. impl<MemberId, ChannelId> Default for BagIdType<MemberId, ChannelId> {
  510. fn default() -> Self {
  511. Self::Static(Default::default())
  512. }
  513. }
  514. /// Define dynamic bag types.
  515. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  516. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Copy)]
  517. pub enum DynamicBagType {
  518. /// Member dynamic bag type.
  519. Member,
  520. /// Channel dynamic bag type.
  521. Channel,
  522. // Modify 'delete_distribution_bucket_family' on adding the new type!
  523. }
  524. impl Default for DynamicBagType {
  525. fn default() -> Self {
  526. Self::Member
  527. }
  528. }
  529. /// A type for static bags ID.
  530. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  531. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
  532. pub enum StaticBagId {
  533. /// Dedicated bag for a council.
  534. Council,
  535. /// Dedicated bag for some working group.
  536. WorkingGroup(WorkingGroup),
  537. }
  538. impl Default for StaticBagId {
  539. fn default() -> Self {
  540. Self::Council
  541. }
  542. }
  543. impl<MemberId, ChannelId> From<StaticBagId> for BagIdType<MemberId, ChannelId> {
  544. fn from(static_bag_id: StaticBagId) -> Self {
  545. BagIdType::Static(static_bag_id)
  546. }
  547. }
  548. /// Type alias for the DynamicBagIdType.
  549. pub type DynamicBagId<T> = DynamicBagIdType<MemberId<T>, <T as Trait>::ChannelId>;
  550. /// A type for dynamic bags ID.
  551. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  552. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
  553. pub enum DynamicBagIdType<MemberId, ChannelId> {
  554. /// Dynamic bag assigned to a member.
  555. Member(MemberId),
  556. /// Dynamic bag assigned to media channel.
  557. Channel(ChannelId),
  558. }
  559. impl<MemberId: Default, ChannelId> Default for DynamicBagIdType<MemberId, ChannelId> {
  560. fn default() -> Self {
  561. Self::Member(Default::default())
  562. }
  563. }
  564. impl<MemberId, ChannelId> From<DynamicBagIdType<MemberId, ChannelId>>
  565. for BagIdType<MemberId, ChannelId>
  566. {
  567. fn from(dynamic_bag_id: DynamicBagIdType<MemberId, ChannelId>) -> Self {
  568. BagIdType::Dynamic(dynamic_bag_id)
  569. }
  570. }
  571. #[allow(clippy::from_over_into)] // Cannot implement From using these types.
  572. impl<MemberId: Default, ChannelId> Into<DynamicBagType> for DynamicBagIdType<MemberId, ChannelId> {
  573. fn into(self) -> DynamicBagType {
  574. match self {
  575. DynamicBagIdType::Member(_) => DynamicBagType::Member,
  576. DynamicBagIdType::Channel(_) => DynamicBagType::Channel,
  577. }
  578. }
  579. }
  580. /// Alias for the UploadParametersRecord
  581. pub type UploadParameters<T> = UploadParametersRecord<
  582. MemberId<T>,
  583. <T as Trait>::ChannelId,
  584. <T as frame_system::Trait>::AccountId,
  585. BalanceOf<T>,
  586. >;
  587. /// Data wrapper structure. Helps passing the parameters to the `upload` extrinsic.
  588. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  589. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  590. pub struct UploadParametersRecord<MemberId, ChannelId, AccountId, Balance> {
  591. /// Static or dynamic bag to upload data.
  592. pub bag_id: BagIdType<MemberId, ChannelId>,
  593. /// Data object parameters.
  594. pub object_creation_list: Vec<DataObjectCreationParameters>,
  595. /// Account for the data object deletion prize.
  596. pub deletion_prize_source_account_id: AccountId,
  597. /// Expected data size fee value for this extrinsic call.
  598. pub expected_data_size_fee: Balance,
  599. }
  600. /// Alias for the DynamicBagDeletionPrizeRecord
  601. pub type DynamicBagDeletionPrize<T> =
  602. DynamicBagDeletionPrizeRecord<<T as frame_system::Trait>::AccountId, BalanceOf<T>>;
  603. /// Deletion prize data for the dynamic bag. Requires on the dynamic bag creation.
  604. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  605. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  606. pub struct DynamicBagDeletionPrizeRecord<AccountId, Balance> {
  607. /// Account ID to withdraw the deletion prize.
  608. pub account_id: AccountId,
  609. /// Deletion prize value.
  610. pub prize: Balance,
  611. }
  612. /// Defines storage bucket parameters.
  613. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  614. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  615. pub struct Voucher {
  616. /// Total size limit.
  617. pub size_limit: u64,
  618. /// Object number limit.
  619. pub objects_limit: u64,
  620. /// Current size.
  621. pub size_used: u64,
  622. /// Current object number.
  623. pub objects_used: u64,
  624. }
  625. // Defines whether we should increase or decrease parameters during some operation.
  626. #[derive(Clone, PartialEq, Eq, Debug, Copy)]
  627. enum OperationType {
  628. // Increase parameters.
  629. Increase,
  630. // Decrease parameters.
  631. Decrease,
  632. }
  633. // Helper-struct - defines voucher changes.
  634. #[derive(Clone, PartialEq, Eq, Debug, Copy, Default)]
  635. struct VoucherUpdate {
  636. /// Total number.
  637. pub objects_number: u64,
  638. /// Total objects size sum.
  639. pub objects_total_size: u64,
  640. }
  641. impl VoucherUpdate {
  642. fn get_updated_voucher(&self, voucher: &Voucher, voucher_operation: OperationType) -> Voucher {
  643. let (objects_used, size_used) = match voucher_operation {
  644. OperationType::Increase => (
  645. voucher.objects_used.saturating_add(self.objects_number),
  646. voucher.size_used.saturating_add(self.objects_total_size),
  647. ),
  648. OperationType::Decrease => (
  649. voucher.objects_used.saturating_sub(self.objects_number),
  650. voucher.size_used.saturating_sub(self.objects_total_size),
  651. ),
  652. };
  653. Voucher {
  654. size_used,
  655. objects_used,
  656. ..voucher.clone()
  657. }
  658. }
  659. // Adds a single object data to the voucher update (updates objects size and number).
  660. fn add_object(&mut self, size: u64) {
  661. self.objects_number = self.objects_number.saturating_add(1);
  662. self.objects_total_size = self.objects_total_size.saturating_add(size);
  663. }
  664. }
  665. /// Defines the storage bucket connection to the storage operator (storage WG worker).
  666. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  667. #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
  668. pub enum StorageBucketOperatorStatus<WorkerId> {
  669. /// No connection.
  670. Missing,
  671. /// Storage operator was invited.
  672. InvitedStorageWorker(WorkerId),
  673. /// Storage operator accepted the invitation.
  674. StorageWorker(WorkerId),
  675. }
  676. impl<WorkerId> Default for StorageBucketOperatorStatus<WorkerId> {
  677. fn default() -> Self {
  678. Self::Missing
  679. }
  680. }
  681. /// A commitment to hold some set of bags for long term storage. A bucket may have a bucket
  682. /// operator, which is a single worker in the storage working group.
  683. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  684. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  685. pub struct StorageBucket<WorkerId> {
  686. /// Current storage operator status.
  687. pub operator_status: StorageBucketOperatorStatus<WorkerId>,
  688. /// Defines whether the bucket accepts new bags.
  689. pub accepting_new_bags: bool,
  690. /// Defines limits for a bucket.
  691. pub voucher: Voucher,
  692. }
  693. // Helper-struct for the data object uploading.
  694. #[derive(Default, Clone, Debug)]
  695. struct DataObjectCandidates<T: Trait> {
  696. // next data object ID to be saved in the storage.
  697. next_data_object_id: T::DataObjectId,
  698. // 'ID-data object' map.
  699. data_objects_map: BTreeMap<T::DataObjectId, DataObject<BalanceOf<T>>>,
  700. }
  701. // Helper struct for the dynamic bag changing.
  702. #[derive(Clone, PartialEq, Eq, Debug, Copy, Default)]
  703. struct BagUpdate<Balance> {
  704. // Voucher update for data objects
  705. voucher_update: VoucherUpdate,
  706. // Total deletion prize for data objects.
  707. total_deletion_prize: Balance,
  708. }
  709. impl<Balance: Saturating + Copy> BagUpdate<Balance> {
  710. // Adds a single object data to the voucher update (updates objects size, number)
  711. // and deletion prize.
  712. fn add_object(&mut self, size: u64, deletion_prize: Balance) -> Self {
  713. self.voucher_update.add_object(size);
  714. self.total_deletion_prize = self.total_deletion_prize.saturating_add(deletion_prize);
  715. *self
  716. }
  717. }
  718. /// Type alias for the DistributionBucketFamilyRecord.
  719. pub type DistributionBucketFamily<T> =
  720. DistributionBucketFamilyRecord<<T as Trait>::DistributionBucketIndex>;
  721. /// Distribution bucket family.
  722. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  723. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  724. pub struct DistributionBucketFamilyRecord<DistributionBucketIndex> {
  725. /// Next distribution bucket index.
  726. pub next_distribution_bucket_index: DistributionBucketIndex,
  727. }
  728. impl<DistributionBucketIndex: BaseArithmetic>
  729. DistributionBucketFamilyRecord<DistributionBucketIndex>
  730. {
  731. // Increments the next distribution bucket index variable.
  732. fn increment_next_distribution_bucket_index_counter(&mut self) {
  733. self.next_distribution_bucket_index += One::one()
  734. }
  735. }
  736. /// Type alias for the DistributionBucketIdRecord.
  737. pub type DistributionBucketId<T> = DistributionBucketIdRecord<
  738. <T as Trait>::DistributionBucketFamilyId,
  739. <T as Trait>::DistributionBucketIndex,
  740. >;
  741. /// Complex distribution bucket ID type.
  742. /// Joins a distribution bucket family ID and a distribution bucket index within the family.
  743. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  744. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
  745. pub struct DistributionBucketIdRecord<DistributionBucketFamilyId: Ord, DistributionBucketIndex: Ord>
  746. {
  747. /// Distribution bucket family ID.
  748. pub distribution_bucket_family_id: DistributionBucketFamilyId,
  749. /// Distribution bucket ID.
  750. pub distribution_bucket_index: DistributionBucketIndex,
  751. }
  752. /// Type alias for the DistributionBucketRecord.
  753. pub type DistributionBucket<T> = DistributionBucketRecord<WorkerId<T>>;
  754. /// Distribution bucket.
  755. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
  756. #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
  757. pub struct DistributionBucketRecord<WorkerId: Ord> {
  758. /// Distribution bucket accepts new bags.
  759. pub accepting_new_bags: bool,
  760. /// Distribution bucket serves objects.
  761. pub distributing: bool,
  762. /// Pending invitations for workers to distribute the bucket.
  763. pub pending_invitations: BTreeSet<WorkerId>,
  764. /// Active operators to distribute the bucket.
  765. pub operators: BTreeSet<WorkerId>,
  766. /// Number of assigned bags.
  767. pub assigned_bags: u64,
  768. }
  769. impl<WorkerId: Ord> DistributionBucketRecord<WorkerId> {
  770. // Increment the assigned bags number.
  771. fn register_bag_assignment(&mut self) {
  772. self.assigned_bags = self.assigned_bags.saturating_add(1);
  773. }
  774. // Decrement the assigned bags number.
  775. fn unregister_bag_assignment(&mut self) {
  776. self.assigned_bags = self.assigned_bags.saturating_sub(1);
  777. }
  778. // Checks the bag assignment number. Returns true if it equals zero.
  779. fn no_bags_assigned(&self) -> bool {
  780. self.assigned_bags == 0
  781. }
  782. }
  783. decl_storage! {
  784. trait Store for Module<T: Trait> as Storage {
  785. /// Defines whether all new uploads blocked
  786. pub UploadingBlocked get(fn uploading_blocked): bool;
  787. /// Bags storage map.
  788. pub Bags get(fn bag): map hasher(blake2_128_concat) BagId<T> => Bag<T>;
  789. /// Storage bucket id counter. Starts at zero.
  790. pub NextStorageBucketId get(fn next_storage_bucket_id): T::StorageBucketId;
  791. /// Data object id counter. Starts at zero.
  792. pub NextDataObjectId get(fn next_data_object_id): T::DataObjectId;
  793. /// Storage buckets.
  794. pub StorageBucketById get (fn storage_bucket_by_id): map hasher(blake2_128_concat)
  795. T::StorageBucketId => StorageBucket<WorkerId<T>>;
  796. /// Blacklisted data object hashes.
  797. pub Blacklist get (fn blacklist): map hasher(blake2_128_concat) Cid => ();
  798. /// Blacklist collection counter.
  799. pub CurrentBlacklistSize get (fn current_blacklist_size): u64;
  800. /// Size based pricing of new objects uploaded.
  801. pub DataObjectPerMegabyteFee get (fn data_object_per_mega_byte_fee): BalanceOf<T>;
  802. /// "Storage buckets per bag" number limit.
  803. pub StorageBucketsPerBagLimit get (fn storage_buckets_per_bag_limit): u64;
  804. /// "Max objects size for a storage bucket voucher" number limit.
  805. pub VoucherMaxObjectsSizeLimit get (fn voucher_max_objects_size_limit): u64;
  806. /// "Max objects number for a storage bucket voucher" number limit.
  807. pub VoucherMaxObjectsNumberLimit get (fn voucher_max_objects_number_limit): u64;
  808. /// DynamicBagCreationPolicy by bag type storage map.
  809. pub DynamicBagCreationPolicies get (fn dynamic_bag_creation_policy):
  810. map hasher(blake2_128_concat) DynamicBagType =>
  811. DynamicBagCreationPolicy<T::DistributionBucketFamilyId>;
  812. /// 'Data objects for bags' storage double map.
  813. pub DataObjectsById get (fn data_object_by_id): double_map
  814. hasher(blake2_128_concat) BagId<T>,
  815. hasher(blake2_128_concat) T::DataObjectId => DataObject<BalanceOf<T>>;
  816. /// Distribution bucket family id counter. Starts at zero.
  817. pub NextDistributionBucketFamilyId get(fn next_distribution_bucket_family_id):
  818. T::DistributionBucketFamilyId;
  819. /// Distribution bucket families.
  820. pub DistributionBucketFamilyById get (fn distribution_bucket_family_by_id):
  821. map hasher(blake2_128_concat) T::DistributionBucketFamilyId =>
  822. DistributionBucketFamily<T>;
  823. /// 'Distribution bucket' storage double map.
  824. pub DistributionBucketByFamilyIdById get (fn distribution_bucket_by_family_id_by_index):
  825. double_map
  826. hasher(blake2_128_concat) T::DistributionBucketFamilyId,
  827. hasher(blake2_128_concat) T::DistributionBucketIndex => DistributionBucket<T>;
  828. /// Total number of distribution bucket families in the system.
  829. pub DistributionBucketFamilyNumber get(fn distribution_bucket_family_number): u64;
  830. /// "Distribution buckets per bag" number limit.
  831. pub DistributionBucketsPerBagLimit get (fn distribution_buckets_per_bag_limit): u64;
  832. }
  833. }
  834. decl_event! {
  835. /// Storage events
  836. pub enum Event<T>
  837. where
  838. <T as Trait>::StorageBucketId,
  839. WorkerId = WorkerId<T>,
  840. <T as Trait>::DataObjectId,
  841. UploadParameters = UploadParameters<T>,
  842. BagId = BagId<T>,
  843. DynamicBagId = DynamicBagId<T>,
  844. <T as frame_system::Trait>::AccountId,
  845. Balance = BalanceOf<T>,
  846. <T as Trait>::DistributionBucketFamilyId,
  847. DistributionBucketId = DistributionBucketId<T>,
  848. <T as Trait>::DistributionBucketIndex,
  849. {
  850. /// Emits on creating the storage bucket.
  851. /// Params
  852. /// - storage bucket ID
  853. /// - invited worker
  854. /// - flag "accepting_new_bags"
  855. /// - size limit for voucher,
  856. /// - objects limit for voucher,
  857. StorageBucketCreated(StorageBucketId, Option<WorkerId>, bool, u64, u64),
  858. /// Emits on accepting the storage bucket invitation.
  859. /// Params
  860. /// - storage bucket ID
  861. /// - invited worker ID
  862. StorageBucketInvitationAccepted(StorageBucketId, WorkerId),
  863. /// Emits on updating storage buckets for bag.
  864. /// Params
  865. /// - bag ID
  866. /// - storage buckets to add ID collection
  867. /// - storage buckets to remove ID collection
  868. StorageBucketsUpdatedForBag(BagId, BTreeSet<StorageBucketId>, BTreeSet<StorageBucketId>),
  869. /// Emits on uploading data objects.
  870. /// Params
  871. /// - data objects IDs
  872. /// - initial uploading parameters
  873. /// - deletion prize for objects
  874. DataObjectsUploaded(Vec<DataObjectId>, UploadParameters, Balance),
  875. /// Emits on setting the storage operator metadata.
  876. /// Params
  877. /// - storage bucket ID
  878. /// - invited worker ID
  879. /// - metadata
  880. StorageOperatorMetadataSet(StorageBucketId, WorkerId, Vec<u8>),
  881. /// Emits on setting the storage bucket voucher limits.
  882. /// Params
  883. /// - storage bucket ID
  884. /// - new total objects size limit
  885. /// - new total objects number limit
  886. StorageBucketVoucherLimitsSet(StorageBucketId, u64, u64),
  887. /// Emits on accepting pending data objects.
  888. /// Params
  889. /// - storage bucket ID
  890. /// - worker ID (storage provider ID)
  891. /// - bag ID
  892. /// - pending data objects
  893. PendingDataObjectsAccepted(StorageBucketId, WorkerId, BagId, BTreeSet<DataObjectId>),
  894. /// Emits on cancelling the storage bucket invitation.
  895. /// Params
  896. /// - storage bucket ID
  897. StorageBucketInvitationCancelled(StorageBucketId),
  898. /// Emits on the storage bucket operator invitation.
  899. /// Params
  900. /// - storage bucket ID
  901. /// - operator worker ID (storage provider ID)
  902. StorageBucketOperatorInvited(StorageBucketId, WorkerId),
  903. /// Emits on the storage bucket operator removal.
  904. /// Params
  905. /// - storage bucket ID
  906. StorageBucketOperatorRemoved(StorageBucketId),
  907. /// Emits on changing the size-based pricing of new objects uploaded.
  908. /// Params
  909. /// - new status
  910. UploadingBlockStatusUpdated(bool),
  911. /// Emits on changing the size-based pricing of new objects uploaded.
  912. /// Params
  913. /// - new data size fee
  914. DataObjectPerMegabyteFeeUpdated(Balance),
  915. /// Emits on changing the "Storage buckets per bag" number limit.
  916. /// Params
  917. /// - new limit
  918. StorageBucketsPerBagLimitUpdated(u64),
  919. /// Emits on changing the "Storage buckets voucher max limits".
  920. /// Params
  921. /// - new objects size limit
  922. /// - new objects number limit
  923. StorageBucketsVoucherMaxLimitsUpdated(u64, u64),
  924. /// Emits on moving data objects between bags.
  925. /// Params
  926. /// - source bag ID
  927. /// - destination bag ID
  928. /// - data object IDs
  929. DataObjectsMoved(BagId, BagId, BTreeSet<DataObjectId>),
  930. /// Emits on data objects deletion from bags.
  931. /// Params
  932. /// - account ID for the deletion prize
  933. /// - bag ID
  934. /// - data object IDs
  935. DataObjectsDeleted(AccountId, BagId, BTreeSet<DataObjectId>),
  936. /// Emits on storage bucket status update.
  937. /// Params
  938. /// - storage bucket ID
  939. /// - new status
  940. StorageBucketStatusUpdated(StorageBucketId, bool),
  941. /// Emits on updating the blacklist with data hashes.
  942. /// Params
  943. /// - hashes to remove from the blacklist
  944. /// - hashes to add to the blacklist
  945. UpdateBlacklist(BTreeSet<Cid>, BTreeSet<Cid>),
  946. /// Emits on deleting a dynamic bag.
  947. /// Params
  948. /// - account ID for the deletion prize
  949. /// - dynamic bag ID
  950. DynamicBagDeleted(AccountId, DynamicBagId),
  951. /// Emits on creating a dynamic bag.
  952. /// Params
  953. /// - dynamic bag ID
  954. /// - optional DynamicBagDeletionPrize instance
  955. /// - assigned storage buckets' IDs
  956. /// - assigned distribution buckets' IDs
  957. DynamicBagCreated(
  958. DynamicBagId,
  959. Option<DynamicBagDeletionPrizeRecord<AccountId, Balance>>,
  960. BTreeSet<StorageBucketId>,
  961. BTreeSet<DistributionBucketId>,
  962. ),
  963. /// Emits on changing the voucher for a storage bucket.
  964. /// Params
  965. /// - storage bucket ID
  966. /// - new voucher
  967. VoucherChanged(StorageBucketId, Voucher),
  968. /// Emits on storage bucket deleting.
  969. /// Params
  970. /// - storage bucket ID
  971. StorageBucketDeleted(StorageBucketId),
  972. /// Emits on updating the number of storage buckets in dynamic bag creation policy.
  973. /// Params
  974. /// - dynamic bag type
  975. /// - new number of storage buckets
  976. NumberOfStorageBucketsInDynamicBagCreationPolicyUpdated(DynamicBagType, u64),
  977. /// Bag objects changed.
  978. /// Params
  979. /// - bag id
  980. /// - new total objects size
  981. /// - new total objects number
  982. BagObjectsChanged(BagId, u64, u64),
  983. /// Emits on creating distribution bucket family.
  984. /// Params
  985. /// - distribution family bucket ID
  986. DistributionBucketFamilyCreated(DistributionBucketFamilyId),
  987. /// Emits on deleting distribution bucket family.
  988. /// Params
  989. /// - distribution family bucket ID
  990. DistributionBucketFamilyDeleted(DistributionBucketFamilyId),
  991. /// Emits on creating distribution bucket.
  992. /// Params
  993. /// - distribution bucket family ID
  994. /// - accepting new bags
  995. /// - distribution bucket ID
  996. DistributionBucketCreated(DistributionBucketFamilyId, bool, DistributionBucketId),
  997. /// Emits on storage bucket status update (accepting new bags).
  998. /// Params
  999. /// - distribution bucket ID
  1000. /// - new status (accepting new bags)
  1001. DistributionBucketStatusUpdated(DistributionBucketId, bool),
  1002. /// Emits on deleting distribution bucket.
  1003. /// Params
  1004. /// - distribution bucket ID
  1005. DistributionBucketDeleted(DistributionBucketId),
  1006. /// Emits on updating distribution buckets for bag.
  1007. /// Params
  1008. /// - bag ID
  1009. /// - storage buckets to add ID collection
  1010. /// - storage buckets to remove ID collection
  1011. DistributionBucketsUpdatedForBag(
  1012. BagId,
  1013. DistributionBucketFamilyId,
  1014. BTreeSet<DistributionBucketIndex>,
  1015. BTreeSet<DistributionBucketIndex>
  1016. ),
  1017. /// Emits on changing the "Distribution buckets per bag" number limit.
  1018. /// Params
  1019. /// - new limit
  1020. DistributionBucketsPerBagLimitUpdated(u64),
  1021. /// Emits on storage bucket mode update (distributing flag).
  1022. /// Params
  1023. /// - distribution bucket ID
  1024. /// - distributing
  1025. DistributionBucketModeUpdated(DistributionBucketId, bool),
  1026. /// Emits on dynamic bag creation policy update (distribution bucket families).
  1027. /// Params
  1028. /// - dynamic bag type
  1029. /// - families and bucket numbers
  1030. FamiliesInDynamicBagCreationPolicyUpdated(
  1031. DynamicBagType,
  1032. BTreeMap<DistributionBucketFamilyId, u32>
  1033. ),
  1034. /// Emits on creating a distribution bucket invitation for the operator.
  1035. /// Params
  1036. /// - distribution bucket ID
  1037. /// - worker ID
  1038. DistributionBucketOperatorInvited(
  1039. DistributionBucketId,
  1040. WorkerId,
  1041. ),
  1042. /// Emits on canceling a distribution bucket invitation for the operator.
  1043. /// Params
  1044. /// - distribution bucket ID
  1045. /// - operator worker ID
  1046. DistributionBucketInvitationCancelled(
  1047. DistributionBucketId,
  1048. WorkerId,
  1049. ),
  1050. /// Emits on accepting a distribution bucket invitation for the operator.
  1051. /// Params
  1052. /// - worker ID
  1053. /// - distribution bucket ID
  1054. DistributionBucketInvitationAccepted(
  1055. WorkerId,
  1056. DistributionBucketId,
  1057. ),
  1058. /// Emits on setting the metadata by a distribution bucket operator.
  1059. /// Params
  1060. /// - worker ID
  1061. /// - distribution bucket ID
  1062. /// - metadata
  1063. DistributionBucketMetadataSet(
  1064. WorkerId,
  1065. DistributionBucketId,
  1066. Vec<u8>
  1067. ),
  1068. /// Emits on the distribution bucket operator removal.
  1069. /// Params
  1070. /// - distribution bucket ID
  1071. /// - distribution bucket operator ID
  1072. DistributionBucketOperatorRemoved(
  1073. DistributionBucketId,
  1074. WorkerId
  1075. ),
  1076. /// Emits on setting the metadata by a distribution bucket family.
  1077. /// Params
  1078. /// - distribution bucket family ID
  1079. /// - metadata
  1080. DistributionBucketFamilyMetadataSet(
  1081. DistributionBucketFamilyId,
  1082. Vec<u8>
  1083. ),
  1084. }
  1085. }
  1086. decl_error! {
  1087. /// Storage module predefined errors
  1088. pub enum Error for Module<T: Trait>{
  1089. /// Empty "data object creation" collection.
  1090. NoObjectsOnUpload,
  1091. /// The requested storage bucket doesn't exist.
  1092. StorageBucketDoesntExist,
  1093. /// The requested storage bucket is not bound to a bag.
  1094. StorageBucketIsNotBoundToBag,
  1095. /// The requested storage bucket is already bound to a bag.
  1096. StorageBucketIsBoundToBag,
  1097. /// Invalid operation with invites: there is no storage bucket invitation.
  1098. NoStorageBucketInvitation,
  1099. /// Invalid operation with invites: storage provider was already set.
  1100. StorageProviderAlreadySet,
  1101. /// Storage provider must be set.
  1102. StorageProviderMustBeSet,
  1103. /// Invalid operation with invites: another storage provider was invited.
  1104. DifferentStorageProviderInvited,
  1105. /// Invalid operation with invites: storage provider was already invited.
  1106. InvitedStorageProvider,
  1107. /// Storage bucket id collections are empty.
  1108. StorageBucketIdCollectionsAreEmpty,
  1109. /// Upload data error: empty content ID provided.
  1110. EmptyContentId,
  1111. /// Upload data error: zero object size.
  1112. ZeroObjectSize,
  1113. /// Upload data error: invalid deletion prize source account.
  1114. InvalidDeletionPrizeSourceAccount,
  1115. /// Invalid storage provider for bucket.
  1116. InvalidStorageProvider,
  1117. /// Insufficient balance for an operation.
  1118. InsufficientBalance,
  1119. /// Data object doesn't exist.
  1120. DataObjectDoesntExist,
  1121. /// Uploading of the new object is blocked.
  1122. UploadingBlocked,
  1123. /// Data object id collection is empty.
  1124. DataObjectIdCollectionIsEmpty,
  1125. /// Cannot move objects within the same bag.
  1126. SourceAndDestinationBagsAreEqual,
  1127. /// Data object hash is part of the blacklist.
  1128. DataObjectBlacklisted,
  1129. /// Blacklist size limit exceeded.
  1130. BlacklistSizeLimitExceeded,
  1131. /// Max object size limit exceeded for voucher.
  1132. VoucherMaxObjectSizeLimitExceeded,
  1133. /// Max object number limit exceeded for voucher.
  1134. VoucherMaxObjectNumberLimitExceeded,
  1135. /// Object number limit for the storage bucket reached.
  1136. StorageBucketObjectNumberLimitReached,
  1137. /// Objects total size limit for the storage bucket reached.
  1138. StorageBucketObjectSizeLimitReached,
  1139. /// Insufficient module treasury balance for an operation.
  1140. InsufficientTreasuryBalance,
  1141. /// Cannot delete a non-empty storage bucket.
  1142. CannotDeleteNonEmptyStorageBucket,
  1143. /// The `data_object_ids` extrinsic parameter collection is empty.
  1144. DataObjectIdParamsAreEmpty,
  1145. /// The new `StorageBucketsPerBagLimit` number is too low.
  1146. StorageBucketsPerBagLimitTooLow,
  1147. /// The new `StorageBucketsPerBagLimit` number is too high.
  1148. StorageBucketsPerBagLimitTooHigh,
  1149. /// `StorageBucketsPerBagLimit` was exceeded for a bag.
  1150. StorageBucketPerBagLimitExceeded,
  1151. /// The storage bucket doesn't accept new bags.
  1152. StorageBucketDoesntAcceptNewBags,
  1153. /// Cannot create the dynamic bag: dynamic bag exists.
  1154. DynamicBagExists,
  1155. /// Dynamic bag doesn't exist.
  1156. DynamicBagDoesntExist,
  1157. /// Storage provider operator doesn't exist.
  1158. StorageProviderOperatorDoesntExist,
  1159. /// Invalid extrinsic call: data size fee changed.
  1160. DataSizeFeeChanged,
  1161. /// Cannot delete non empty dynamic bag.
  1162. CannotDeleteNonEmptyDynamicBag,
  1163. /// Max distribution bucket family number limit exceeded.
  1164. MaxDistributionBucketFamilyNumberLimitExceeded,
  1165. /// Distribution bucket family doesn't exist.
  1166. DistributionBucketFamilyDoesntExist,
  1167. /// Distribution bucket doesn't exist.
  1168. DistributionBucketDoesntExist,
  1169. /// Distribution bucket id collections are empty.
  1170. DistributionBucketIdCollectionsAreEmpty,
  1171. /// Distribution bucket doesn't accept new bags.
  1172. DistributionBucketDoesntAcceptNewBags,
  1173. /// Max distribution bucket number per bag limit exceeded.
  1174. MaxDistributionBucketNumberPerBagLimitExceeded,
  1175. /// Distribution bucket is not bound to a bag.
  1176. DistributionBucketIsNotBoundToBag,
  1177. /// Distribution bucket is bound to a bag.
  1178. DistributionBucketIsBoundToBag,
  1179. /// The new `DistributionBucketsPerBagLimit` number is too low.
  1180. DistributionBucketsPerBagLimitTooLow,
  1181. /// The new `DistributionBucketsPerBagLimit` number is too high.
  1182. DistributionBucketsPerBagLimitTooHigh,
  1183. /// Distribution provider operator doesn't exist.
  1184. DistributionProviderOperatorDoesntExist,
  1185. /// Distribution provider operator already invited.
  1186. DistributionProviderOperatorAlreadyInvited,
  1187. /// Distribution provider operator already set.
  1188. DistributionProviderOperatorSet,
  1189. /// No distribution bucket invitation.
  1190. NoDistributionBucketInvitation,
  1191. /// Invalid operations: must be a distribution provider operator for a bucket.
  1192. MustBeDistributionProviderOperatorForBucket,
  1193. /// Max number of pending invitations limit for a distribution bucket reached.
  1194. MaxNumberOfPendingInvitationsLimitForDistributionBucketReached,
  1195. /// Distribution family bound to a bag creation policy.
  1196. DistributionFamilyBoundToBagCreationPolicy,
  1197. /// Max data object size exceeded.
  1198. MaxDataObjectSizeExceeded,
  1199. /// Different Accounts for dynamic bag deletion prize and upload fees
  1200. AccountsNotCoherent,
  1201. }
  1202. }
  1203. decl_module! {
  1204. /// _Storage_ substrate module.
  1205. pub struct Module<T: Trait> for enum Call where origin: T::Origin {
  1206. /// Default deposit_event() handler
  1207. fn deposit_event() = default;
  1208. /// Predefined errors.
  1209. type Error = Error<T>;
  1210. /// Exports const - a prize for a data object deletion.
  1211. const DataObjectDeletionPrize: BalanceOf<T> = T::DataObjectDeletionPrize::get();
  1212. /// Exports const - maximum size of the "hash blacklist" collection.
  1213. const BlacklistSizeLimit: u64 = T::BlacklistSizeLimit::get();
  1214. /// Exports const - "Storage buckets per bag" value constraint.
  1215. const StorageBucketsPerBagValueConstraint: StorageBucketsPerBagValueConstraint =
  1216. T::StorageBucketsPerBagValueConstraint::get();
  1217. /// Exports const - the default dynamic bag creation policy for members (storage bucket
  1218. /// number).
  1219. const DefaultMemberDynamicBagNumberOfStorageBuckets: u64 =
  1220. T::DefaultMemberDynamicBagNumberOfStorageBuckets::get();
  1221. /// Exports const - the default dynamic bag creation policy for channels (storage bucket
  1222. /// number).
  1223. const DefaultChannelDynamicBagNumberOfStorageBuckets: u64 =
  1224. T::DefaultChannelDynamicBagNumberOfStorageBuckets::get();
  1225. /// Exports const - max allowed distribution bucket family number.
  1226. const MaxDistributionBucketFamilyNumber: u64 = T::MaxDistributionBucketFamilyNumber::get();
  1227. /// Exports const - "Distribution buckets per bag" value constraint.
  1228. const DistributionBucketsPerBagValueConstraint: StorageBucketsPerBagValueConstraint =
  1229. T::DistributionBucketsPerBagValueConstraint::get();
  1230. /// Exports const - max number of pending invitations per distribution bucket.
  1231. const MaxNumberOfPendingInvitationsPerDistributionBucket: u64 =
  1232. T::MaxNumberOfPendingInvitationsPerDistributionBucket::get();
  1233. /// Exports const - max data object size in bytes.
  1234. const MaxDataObjectSize: u64 = T::MaxDataObjectSize::get();
  1235. // ===== Storage Lead actions =====
  1236. /// Delete storage bucket. Must be empty. Storage operator must be missing.
  1237. #[weight = 10_000_000] // TODO: adjust weight
  1238. pub fn delete_storage_bucket(
  1239. origin,
  1240. storage_bucket_id: T::StorageBucketId,
  1241. ){
  1242. T::ensure_storage_working_group_leader_origin(origin)?;
  1243. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1244. ensure!(
  1245. bucket.voucher.objects_used == 0,
  1246. Error::<T>::CannotDeleteNonEmptyStorageBucket
  1247. );
  1248. //
  1249. // == MUTATION SAFE ==
  1250. //
  1251. <StorageBucketById<T>>::remove(storage_bucket_id);
  1252. Self::deposit_event(
  1253. RawEvent::StorageBucketDeleted(storage_bucket_id)
  1254. );
  1255. }
  1256. /// Updates global uploading flag.
  1257. #[weight = 10_000_000] // TODO: adjust weight
  1258. pub fn update_uploading_blocked_status(origin, new_status: bool) {
  1259. T::ensure_storage_working_group_leader_origin(origin)?;
  1260. //
  1261. // == MUTATION SAFE ==
  1262. //
  1263. UploadingBlocked::put(new_status);
  1264. Self::deposit_event(RawEvent::UploadingBlockStatusUpdated(new_status));
  1265. }
  1266. /// Updates size-based pricing of new objects uploaded.
  1267. #[weight = 10_000_000] // TODO: adjust weight
  1268. pub fn update_data_size_fee(origin, new_data_size_fee: BalanceOf<T>) {
  1269. T::ensure_storage_working_group_leader_origin(origin)?;
  1270. //
  1271. // == MUTATION SAFE ==
  1272. //
  1273. DataObjectPerMegabyteFee::<T>::put(new_data_size_fee);
  1274. Self::deposit_event(RawEvent::DataObjectPerMegabyteFeeUpdated(new_data_size_fee));
  1275. }
  1276. /// Updates "Storage buckets per bag" number limit.
  1277. #[weight = 10_000_000] // TODO: adjust weight
  1278. pub fn update_storage_buckets_per_bag_limit(origin, new_limit: u64) {
  1279. T::ensure_storage_working_group_leader_origin(origin)?;
  1280. T::StorageBucketsPerBagValueConstraint::get().ensure_valid(
  1281. new_limit,
  1282. Error::<T>::StorageBucketsPerBagLimitTooLow,
  1283. Error::<T>::StorageBucketsPerBagLimitTooHigh,
  1284. )?;
  1285. //
  1286. // == MUTATION SAFE ==
  1287. //
  1288. StorageBucketsPerBagLimit::put(new_limit);
  1289. Self::deposit_event(RawEvent::StorageBucketsPerBagLimitUpdated(new_limit));
  1290. }
  1291. /// Updates "Storage buckets voucher max limits".
  1292. #[weight = 10_000_000] // TODO: adjust weight
  1293. pub fn update_storage_buckets_voucher_max_limits(
  1294. origin,
  1295. new_objects_size: u64,
  1296. new_objects_number: u64,
  1297. ) {
  1298. T::ensure_storage_working_group_leader_origin(origin)?;
  1299. //
  1300. // == MUTATION SAFE ==
  1301. //
  1302. VoucherMaxObjectsSizeLimit::put(new_objects_size);
  1303. VoucherMaxObjectsNumberLimit::put(new_objects_number);
  1304. Self::deposit_event(
  1305. RawEvent::StorageBucketsVoucherMaxLimitsUpdated(new_objects_size, new_objects_number)
  1306. );
  1307. }
  1308. /// Update number of storage buckets used in given dynamic bag creation policy.
  1309. #[weight = 10_000_000] // TODO: adjust weight
  1310. pub fn update_number_of_storage_buckets_in_dynamic_bag_creation_policy(
  1311. origin,
  1312. dynamic_bag_type: DynamicBagType,
  1313. number_of_storage_buckets: u64,
  1314. ) {
  1315. T::ensure_storage_working_group_leader_origin(origin)?;
  1316. //
  1317. // == MUTATION SAFE ==
  1318. //
  1319. let mut creation_policy = Self::get_dynamic_bag_creation_policy(dynamic_bag_type);
  1320. creation_policy.number_of_storage_buckets = number_of_storage_buckets;
  1321. DynamicBagCreationPolicies::<T>::insert(dynamic_bag_type, creation_policy);
  1322. Self::deposit_event(
  1323. RawEvent::NumberOfStorageBucketsInDynamicBagCreationPolicyUpdated(
  1324. dynamic_bag_type,
  1325. number_of_storage_buckets
  1326. )
  1327. );
  1328. }
  1329. /// Add and remove hashes to the current blacklist.
  1330. #[weight = 10_000_000] // TODO: adjust weight
  1331. pub fn update_blacklist(
  1332. origin,
  1333. remove_hashes: BTreeSet<Cid>,
  1334. add_hashes: BTreeSet<Cid>
  1335. ){
  1336. T::ensure_storage_working_group_leader_origin(origin)?;
  1337. // Get only hashes that exist in the blacklist.
  1338. let verified_remove_hashes = Self::get_existing_hashes(&remove_hashes);
  1339. // Get only hashes that doesn't exist in the blacklist.
  1340. let verified_add_hashes = Self::get_nonexisting_hashes(&add_hashes);
  1341. let updated_blacklist_size: u64 = Self::current_blacklist_size()
  1342. .saturating_add(verified_add_hashes.len().saturated_into::<u64>())
  1343. .saturating_sub(verified_remove_hashes.len().saturated_into::<u64>());
  1344. ensure!(
  1345. updated_blacklist_size <= T::BlacklistSizeLimit::get(),
  1346. Error::<T>::BlacklistSizeLimitExceeded
  1347. );
  1348. //
  1349. // == MUTATION SAFE ==
  1350. //
  1351. for cid in verified_remove_hashes.iter() {
  1352. Blacklist::remove(cid);
  1353. }
  1354. for cid in verified_add_hashes.iter() {
  1355. Blacklist::insert(cid, ());
  1356. }
  1357. CurrentBlacklistSize::put(updated_blacklist_size);
  1358. Self::deposit_event(RawEvent::UpdateBlacklist(remove_hashes, add_hashes));
  1359. }
  1360. /// Create storage bucket.
  1361. #[weight = 10_000_000] // TODO: adjust weight
  1362. pub fn create_storage_bucket(
  1363. origin,
  1364. invite_worker: Option<WorkerId<T>>,
  1365. accepting_new_bags: bool,
  1366. size_limit: u64,
  1367. objects_limit: u64,
  1368. ) {
  1369. T::ensure_storage_working_group_leader_origin(origin)?;
  1370. let voucher = Voucher {
  1371. size_limit,
  1372. objects_limit,
  1373. ..Default::default()
  1374. };
  1375. Self::can_create_storage_bucket(&voucher, &invite_worker)?;
  1376. //
  1377. // == MUTATION SAFE ==
  1378. //
  1379. let operator_status = invite_worker
  1380. .map(StorageBucketOperatorStatus::InvitedStorageWorker)
  1381. .unwrap_or(StorageBucketOperatorStatus::Missing);
  1382. let storage_bucket = StorageBucket {
  1383. operator_status,
  1384. accepting_new_bags,
  1385. voucher,
  1386. };
  1387. let storage_bucket_id = Self::next_storage_bucket_id();
  1388. <NextStorageBucketId<T>>::put(storage_bucket_id + One::one());
  1389. <StorageBucketById<T>>::insert(storage_bucket_id, storage_bucket);
  1390. Self::deposit_event(
  1391. RawEvent::StorageBucketCreated(
  1392. storage_bucket_id,
  1393. invite_worker,
  1394. accepting_new_bags,
  1395. size_limit,
  1396. objects_limit,
  1397. )
  1398. );
  1399. }
  1400. /// Updates storage buckets for a bag..
  1401. #[weight = 10_000_000] // TODO: adjust weight
  1402. pub fn update_storage_buckets_for_bag(
  1403. origin,
  1404. bag_id: BagId<T>,
  1405. add_buckets: BTreeSet<T::StorageBucketId>,
  1406. remove_buckets: BTreeSet<T::StorageBucketId>,
  1407. ) {
  1408. T::ensure_storage_working_group_leader_origin(origin)?;
  1409. Self::ensure_bag_exists(&bag_id)?;
  1410. let voucher_update = Self::validate_update_storage_buckets_for_bag_params(
  1411. &bag_id,
  1412. &add_buckets,
  1413. &remove_buckets,
  1414. )?;
  1415. //
  1416. // == MUTATION SAFE ==
  1417. //
  1418. // Update vouchers.
  1419. if !add_buckets.is_empty() {
  1420. Self::change_storage_buckets_vouchers(
  1421. &add_buckets,
  1422. &voucher_update,
  1423. OperationType::Increase
  1424. );
  1425. }
  1426. if !remove_buckets.is_empty() {
  1427. Self::change_storage_buckets_vouchers(
  1428. &remove_buckets,
  1429. &voucher_update,
  1430. OperationType::Decrease
  1431. );
  1432. }
  1433. Bags::<T>::mutate(&bag_id, |bag| {
  1434. bag.update_storage_buckets(&mut add_buckets.clone(), &remove_buckets);
  1435. });
  1436. Self::deposit_event(
  1437. RawEvent::StorageBucketsUpdatedForBag(bag_id, add_buckets, remove_buckets)
  1438. );
  1439. }
  1440. /// Cancel pending storage bucket invite. An invitation must be pending.
  1441. #[weight = 10_000_000] // TODO: adjust weight
  1442. pub fn cancel_storage_bucket_operator_invite(origin, storage_bucket_id: T::StorageBucketId){
  1443. T::ensure_storage_working_group_leader_origin(origin)?;
  1444. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1445. Self::ensure_bucket_pending_invitation_status(&bucket)?;
  1446. //
  1447. // == MUTATION SAFE ==
  1448. //
  1449. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1450. bucket.operator_status = StorageBucketOperatorStatus::Missing;
  1451. });
  1452. Self::deposit_event(
  1453. RawEvent::StorageBucketInvitationCancelled(storage_bucket_id)
  1454. );
  1455. }
  1456. /// Invite storage bucket operator. Must be missing.
  1457. #[weight = 10_000_000] // TODO: adjust weight
  1458. pub fn invite_storage_bucket_operator(
  1459. origin,
  1460. storage_bucket_id: T::StorageBucketId,
  1461. operator_id: WorkerId<T>,
  1462. ){
  1463. T::ensure_storage_working_group_leader_origin(origin)?;
  1464. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1465. Self::ensure_bucket_missing_invitation_status(&bucket)?;
  1466. Self::ensure_storage_provider_operator_exists(&operator_id)?;
  1467. //
  1468. // == MUTATION SAFE ==
  1469. //
  1470. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1471. bucket.operator_status =
  1472. StorageBucketOperatorStatus::InvitedStorageWorker(operator_id);
  1473. });
  1474. Self::deposit_event(
  1475. RawEvent::StorageBucketOperatorInvited(storage_bucket_id, operator_id)
  1476. );
  1477. }
  1478. /// Removes storage bucket operator.
  1479. #[weight = 10_000_000] // TODO: adjust weight
  1480. pub fn remove_storage_bucket_operator(
  1481. origin,
  1482. storage_bucket_id: T::StorageBucketId,
  1483. ){
  1484. T::ensure_storage_working_group_leader_origin(origin)?;
  1485. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1486. Self::ensure_bucket_storage_provider_invitation_status_for_removal(&bucket)?;
  1487. //
  1488. // == MUTATION SAFE ==
  1489. //
  1490. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1491. bucket.operator_status =
  1492. StorageBucketOperatorStatus::Missing;
  1493. });
  1494. Self::deposit_event(
  1495. RawEvent::StorageBucketOperatorRemoved(storage_bucket_id)
  1496. );
  1497. }
  1498. /// Update whether new bags are being accepted for storage.
  1499. #[weight = 10_000_000] // TODO: adjust weight
  1500. pub fn update_storage_bucket_status(
  1501. origin,
  1502. storage_bucket_id: T::StorageBucketId,
  1503. accepting_new_bags: bool
  1504. ) {
  1505. T::ensure_storage_working_group_leader_origin(origin)?;
  1506. Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1507. //
  1508. // == MUTATION SAFE ==
  1509. //
  1510. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1511. bucket.accepting_new_bags = accepting_new_bags;
  1512. });
  1513. Self::deposit_event(
  1514. RawEvent::StorageBucketStatusUpdated(storage_bucket_id, accepting_new_bags)
  1515. );
  1516. }
  1517. /// Sets storage bucket voucher limits.
  1518. #[weight = 10_000_000] // TODO: adjust weight
  1519. pub fn set_storage_bucket_voucher_limits(
  1520. origin,
  1521. storage_bucket_id: T::StorageBucketId,
  1522. new_objects_size_limit: u64,
  1523. new_objects_number_limit: u64,
  1524. ) {
  1525. T::ensure_storage_working_group_leader_origin(origin)?;
  1526. Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1527. ensure!(
  1528. new_objects_size_limit <= Self::voucher_max_objects_size_limit(),
  1529. Error::<T>::VoucherMaxObjectSizeLimitExceeded
  1530. );
  1531. ensure!(
  1532. new_objects_number_limit <= Self::voucher_max_objects_number_limit(),
  1533. Error::<T>::VoucherMaxObjectNumberLimitExceeded
  1534. );
  1535. //
  1536. // == MUTATION SAFE ==
  1537. //
  1538. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1539. bucket.voucher = Voucher{
  1540. size_limit: new_objects_size_limit,
  1541. objects_limit: new_objects_number_limit,
  1542. ..bucket.voucher
  1543. };
  1544. });
  1545. Self::deposit_event(
  1546. RawEvent::StorageBucketVoucherLimitsSet(
  1547. storage_bucket_id,
  1548. new_objects_size_limit,
  1549. new_objects_number_limit
  1550. )
  1551. );
  1552. }
  1553. // ===== Storage Operator actions =====
  1554. /// Accept the storage bucket invitation. An invitation must match the worker_id parameter.
  1555. #[weight = 10_000_000] // TODO: adjust weight
  1556. pub fn accept_storage_bucket_invitation(
  1557. origin,
  1558. worker_id: WorkerId<T>,
  1559. storage_bucket_id: T::StorageBucketId
  1560. ) {
  1561. T::ensure_storage_worker_origin(origin, worker_id)?;
  1562. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1563. Self::ensure_bucket_storage_provider_invitation_status(&bucket, worker_id)?;
  1564. //
  1565. // == MUTATION SAFE ==
  1566. //
  1567. <StorageBucketById<T>>::mutate(storage_bucket_id, |bucket| {
  1568. bucket.operator_status = StorageBucketOperatorStatus::StorageWorker(worker_id);
  1569. });
  1570. Self::deposit_event(
  1571. RawEvent::StorageBucketInvitationAccepted(storage_bucket_id, worker_id)
  1572. );
  1573. }
  1574. /// Sets storage operator metadata (eg.: storage node URL).
  1575. #[weight = 10_000_000] // TODO: adjust weight
  1576. pub fn set_storage_operator_metadata(
  1577. origin,
  1578. worker_id: WorkerId<T>,
  1579. storage_bucket_id: T::StorageBucketId,
  1580. metadata: Vec<u8>
  1581. ) {
  1582. T::ensure_storage_worker_origin(origin, worker_id)?;
  1583. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1584. Self::ensure_bucket_invitation_accepted(&bucket, worker_id)?;
  1585. //
  1586. // == MUTATION SAFE ==
  1587. //
  1588. Self::deposit_event(
  1589. RawEvent::StorageOperatorMetadataSet(storage_bucket_id, worker_id, metadata)
  1590. );
  1591. }
  1592. /// A storage provider signals that the data object was successfully uploaded to its storage.
  1593. #[weight = 10_000_000] // TODO: adjust weight
  1594. pub fn accept_pending_data_objects(
  1595. origin,
  1596. worker_id: WorkerId<T>,
  1597. storage_bucket_id: T::StorageBucketId,
  1598. bag_id: BagId<T>,
  1599. data_objects: BTreeSet<T::DataObjectId>,
  1600. ) {
  1601. T::ensure_storage_worker_origin(origin, worker_id)?;
  1602. let bucket = Self::ensure_storage_bucket_exists(&storage_bucket_id)?;
  1603. Self::ensure_bucket_invitation_accepted(&bucket, worker_id)?;
  1604. Self::ensure_bag_exists(&bag_id)?;
  1605. Self::validate_accept_pending_data_objects_params(
  1606. &bag_id,
  1607. &data_objects,
  1608. &storage_bucket_id
  1609. )?;
  1610. //
  1611. // == MUTATION SAFE ==
  1612. //
  1613. // Accept data objects for a bag.
  1614. for data_object_id in data_objects.iter() {
  1615. DataObjectsById::<T>::mutate(&bag_id, data_object_id, |data_object| {
  1616. data_object.accepted = true;
  1617. });
  1618. }
  1619. Self::deposit_event(
  1620. RawEvent::PendingDataObjectsAccepted(
  1621. storage_bucket_id,
  1622. worker_id,
  1623. bag_id,
  1624. data_objects
  1625. )
  1626. );
  1627. }
  1628. // ===== Distribution Lead actions =====
  1629. /// Create a distribution bucket family.
  1630. #[weight = 10_000_000] // TODO: adjust weight
  1631. pub fn create_distribution_bucket_family(origin) {
  1632. T::ensure_distribution_working_group_leader_origin(origin)?;
  1633. ensure!(
  1634. Self::distribution_bucket_family_number() <
  1635. T::MaxDistributionBucketFamilyNumber::get(),
  1636. Error::<T>::MaxDistributionBucketFamilyNumberLimitExceeded
  1637. );
  1638. //
  1639. // == MUTATION SAFE ==
  1640. //
  1641. Self::increment_distribution_family_number();
  1642. let family = DistributionBucketFamily::<T>::default();
  1643. let family_id = Self::next_distribution_bucket_family_id();
  1644. <NextDistributionBucketFamilyId<T>>::put(family_id + One::one());
  1645. <DistributionBucketFamilyById<T>>::insert(family_id, family);
  1646. Self::deposit_event(RawEvent::DistributionBucketFamilyCreated(family_id));
  1647. }
  1648. /// Deletes a distribution bucket family.
  1649. #[weight = 10_000_000] // TODO: adjust weight
  1650. pub fn delete_distribution_bucket_family(origin, family_id: T::DistributionBucketFamilyId) {
  1651. T::ensure_distribution_working_group_leader_origin(origin)?;
  1652. Self::ensure_distribution_bucket_family_exists(&family_id)?;
  1653. // Check that no assigned bags left.
  1654. ensure!(Self::no_bags_assigned(&family_id), Error::<T>::DistributionBucketIsBoundToBag);
  1655. Self::check_dynamic_bag_creation_policy_for_dependencies(
  1656. &family_id,
  1657. DynamicBagType::Member
  1658. )?;
  1659. Self::check_dynamic_bag_creation_policy_for_dependencies(
  1660. &family_id,
  1661. DynamicBagType::Channel
  1662. )?;
  1663. //
  1664. // == MUTATION SAFE ==
  1665. //
  1666. Self::decrement_distribution_family_number();
  1667. <DistributionBucketFamilyById<T>>::remove(family_id);
  1668. Self::deposit_event(RawEvent::DistributionBucketFamilyDeleted(family_id));
  1669. }
  1670. /// Create a distribution bucket.
  1671. #[weight = 10_000_000] // TODO: adjust weight
  1672. pub fn create_distribution_bucket(
  1673. origin,
  1674. family_id: T::DistributionBucketFamilyId,
  1675. accepting_new_bags: bool,
  1676. ) {
  1677. T::ensure_distribution_working_group_leader_origin(origin)?;
  1678. let family = Self::ensure_distribution_bucket_family_exists(&family_id)?;
  1679. //
  1680. // == MUTATION SAFE ==
  1681. //
  1682. let bucket = DistributionBucket::<T> {
  1683. accepting_new_bags,
  1684. distributing: true,
  1685. pending_invitations: BTreeSet::new(),
  1686. operators: BTreeSet::new(),
  1687. assigned_bags: 0,
  1688. };
  1689. let bucket_index = family.next_distribution_bucket_index;
  1690. let bucket_id = Self::create_distribution_bucket_id(family_id, bucket_index);
  1691. <DistributionBucketFamilyById<T>>::mutate(family_id, |family|{
  1692. family.increment_next_distribution_bucket_index_counter();
  1693. });
  1694. <DistributionBucketByFamilyIdById<T>>::insert(family_id, bucket_index, bucket);
  1695. Self::deposit_event(
  1696. RawEvent::DistributionBucketCreated(family_id, accepting_new_bags, bucket_id)
  1697. );
  1698. }
  1699. /// Updates a distribution bucket 'accepts new bags' flag.
  1700. #[weight = 10_000_000] // TODO: adjust weight
  1701. pub fn update_distribution_bucket_status(
  1702. origin,
  1703. bucket_id: DistributionBucketId<T>,
  1704. accepting_new_bags: bool
  1705. ) {
  1706. T::ensure_distribution_working_group_leader_origin(origin)?;
  1707. Self::ensure_distribution_bucket_exists(&bucket_id)?;
  1708. //
  1709. // == MUTATION SAFE ==
  1710. //
  1711. <DistributionBucketByFamilyIdById<T>>::mutate(
  1712. bucket_id.distribution_bucket_family_id,
  1713. bucket_id.distribution_bucket_index,
  1714. |bucket| {
  1715. bucket.accepting_new_bags = accepting_new_bags;
  1716. }
  1717. );
  1718. Self::deposit_event(
  1719. RawEvent::DistributionBucketStatusUpdated(bucket_id, accepting_new_bags)
  1720. );
  1721. }
  1722. /// Delete distribution bucket. Must be empty.
  1723. #[weight = 10_000_000] // TODO: adjust weight
  1724. pub fn delete_distribution_bucket(
  1725. origin,
  1726. bucket_id: DistributionBucketId<T>,
  1727. ){
  1728. T::ensure_distribution_working_group_leader_origin(origin)?;
  1729. let bucket = Self::ensure_distribution_bucket_exists(&bucket_id)?;
  1730. // Check that no assigned bags left.
  1731. ensure!(bucket.no_bags_assigned(), Error::<T>::DistributionBucketIsBoundToBag);
  1732. // Check that all operators were removed.
  1733. ensure!(bucket.operators.is_empty(), Error::<T>::DistributionProviderOperatorSet);
  1734. //
  1735. // == MUTATION SAFE ==
  1736. //
  1737. <DistributionBucketByFamilyIdById<T>>::remove(
  1738. &bucket_id.distribution_bucket_family_id,
  1739. &bucket_id.distribution_bucket_index
  1740. );
  1741. Self::deposit_event(
  1742. RawEvent::DistributionBucketDeleted(bucket_id)
  1743. );
  1744. }
  1745. /// Updates distribution buckets for a bag.
  1746. #[weight = 10_000_000] // TODO: adjust weight
  1747. pub fn update_distribution_buckets_for_bag(
  1748. origin,
  1749. bag_id: BagId<T>,
  1750. family_id: T::DistributionBucketFamilyId,
  1751. add_buckets_indices: BTreeSet<T::DistributionBucketIndex>,
  1752. remove_buckets_indices: BTreeSet<T::DistributionBucketIndex>,
  1753. ) {
  1754. T::ensure_distribution_working_group_leader_origin(origin)?;
  1755. Self::validate_update_distribution_buckets_for_bag_params(
  1756. &bag_id,
  1757. &family_id,
  1758. &add_buckets_indices,
  1759. &remove_buckets_indices,
  1760. )?;
  1761. //
  1762. // == MUTATION SAFE ==
  1763. //
  1764. let add_buckets_ids = add_buckets_indices
  1765. .iter()
  1766. .map(|idx| Self::create_distribution_bucket_id(family_id, *idx))
  1767. .collect::<BTreeSet<_>>();
  1768. let remove_buckets_ids = remove_buckets_indices
  1769. .iter()
  1770. .map(|idx| Self::create_distribution_bucket_id(family_id, *idx))
  1771. .collect::<BTreeSet<_>>();
  1772. Bags::<T>::mutate(&bag_id, |bag| {
  1773. bag.update_distribution_buckets(&mut add_buckets_ids.clone(), &remove_buckets_ids);
  1774. });
  1775. Self::change_bag_assignments(&add_buckets_ids, &remove_buckets_ids);
  1776. Self::deposit_event(
  1777. RawEvent::DistributionBucketsUpdatedForBag(
  1778. bag_id,
  1779. family_id,
  1780. add_buckets_indices,
  1781. remove_buckets_indices
  1782. )
  1783. );
  1784. }
  1785. /// Updates "Distribution buckets per bag" number limit.
  1786. #[weight = 10_000_000] // TODO: adjust weight
  1787. pub fn update_distribution_buckets_per_bag_limit(origin, new_limit: u64) {
  1788. T::ensure_distribution_working_group_leader_origin(origin)?;
  1789. T::DistributionBucketsPerBagValueConstraint::get().ensure_valid(
  1790. new_limit,
  1791. Error::<T>::DistributionBucketsPerBagLimitTooLow,
  1792. Error::<T>::DistributionBucketsPerBagLimitTooHigh,
  1793. )?;
  1794. //
  1795. // == MUTATION SAFE ==
  1796. //
  1797. DistributionBucketsPerBagLimit::put(new_limit);
  1798. Self::deposit_event(RawEvent::DistributionBucketsPerBagLimitUpdated(new_limit));
  1799. }
  1800. /// Updates 'distributing' flag for the distributing flag.
  1801. #[weight = 10_000_000] // TODO: adjust weight
  1802. pub fn update_distribution_bucket_mode(
  1803. origin,
  1804. bucket_id: DistributionBucketId<T>,
  1805. distributing: bool
  1806. ) {
  1807. T::ensure_distribution_working_group_leader_origin(origin)?;
  1808. Self::ensure_distribution_bucket_exists(&bucket_id)?;
  1809. //
  1810. // == MUTATION SAFE ==
  1811. //
  1812. <DistributionBucketByFamilyIdById<T>>::mutate(
  1813. bucket_id.distribution_bucket_family_id,
  1814. bucket_id.distribution_bucket_index,
  1815. |bucket| {
  1816. bucket.distributing = distributing;
  1817. }
  1818. );
  1819. Self::deposit_event(
  1820. RawEvent::DistributionBucketModeUpdated(bucket_id, distributing)
  1821. );
  1822. }
  1823. /// Update number of distributed buckets used in given dynamic bag creation policy.
  1824. #[weight = 10_000_000] // TODO: adjust weight
  1825. pub fn update_families_in_dynamic_bag_creation_policy(
  1826. origin,
  1827. dynamic_bag_type: DynamicBagType,
  1828. families: BTreeMap<T::DistributionBucketFamilyId, u32>
  1829. ) {
  1830. T::ensure_distribution_working_group_leader_origin(origin)?;
  1831. Self::validate_update_families_in_dynamic_bag_creation_policy_params(&families)?;
  1832. //
  1833. // == MUTATION SAFE ==
  1834. //
  1835. DynamicBagCreationPolicies::<T>::mutate(dynamic_bag_type, |creation_policy| {
  1836. creation_policy.families = families.clone();
  1837. });
  1838. Self::deposit_event(
  1839. RawEvent::FamiliesInDynamicBagCreationPolicyUpdated(
  1840. dynamic_bag_type,
  1841. families
  1842. )
  1843. );
  1844. }
  1845. /// Invite an operator. Must be missing.
  1846. #[weight = 10_000_000] // TODO: adjust weight
  1847. pub fn invite_distribution_bucket_operator(
  1848. origin,
  1849. bucket_id: DistributionBucketId<T>,
  1850. operator_worker_id: WorkerId<T>
  1851. ) {
  1852. T::ensure_distribution_working_group_leader_origin(origin)?;
  1853. let bucket = Self::ensure_distribution_bucket_exists(&bucket_id)?;
  1854. Self::ensure_distribution_provider_can_be_invited(&bucket, &operator_worker_id)?;
  1855. //
  1856. // == MUTATION SAFE ==
  1857. //
  1858. <DistributionBucketByFamilyIdById<T>>::mutate(
  1859. bucket_id.distribution_bucket_family_id,
  1860. bucket_id.distribution_bucket_index,
  1861. |bucket| {
  1862. bucket.pending_invitations.insert(operator_worker_id);
  1863. }
  1864. );
  1865. Self::deposit_event(
  1866. RawEvent::DistributionBucketOperatorInvited(bucket_id, operator_worker_id)
  1867. );
  1868. }
  1869. /// Cancel pending invite. Must be pending.
  1870. #[weight = 10_000_000] // TODO: adjust weight
  1871. pub fn cancel_distribution_bucket_operator_invite(
  1872. origin,
  1873. bucket_id: DistributionBucketId<T>,
  1874. operator_worker_id: WorkerId<T>
  1875. ) {
  1876. T::ensure_distribution_working_group_leader_origin(origin)?;
  1877. let bucket = Self::ensure_distribution_bucket_exists(&bucket_id)?;
  1878. ensure!(
  1879. bucket.pending_invitations.contains(&operator_worker_id),
  1880. Error::<T>::NoDistributionBucketInvitation
  1881. );
  1882. //
  1883. // == MUTATION SAFE ==
  1884. //
  1885. <DistributionBucketByFamilyIdById<T>>::mutate(
  1886. bucket_id.distribution_bucket_family_id,
  1887. bucket_id.distribution_bucket_index,
  1888. |bucket| {
  1889. bucket.pending_invitations.remove(&operator_worker_id);
  1890. }
  1891. );
  1892. Self::deposit_event(
  1893. RawEvent::DistributionBucketInvitationCancelled(
  1894. bucket_id,
  1895. operator_worker_id
  1896. )
  1897. );
  1898. }
  1899. /// Removes distribution bucket operator.
  1900. #[weight = 10_000_000] // TODO: adjust weight
  1901. pub fn remove_distribution_bucket_operator(
  1902. origin,
  1903. bucket_id: DistributionBucketId<T>,
  1904. operator_worker_id: WorkerId<T>,
  1905. ){
  1906. T::ensure_distribution_working_group_leader_origin(origin)?;
  1907. let bucket = Self::ensure_distribution_bucket_exists(&bucket_id)?;
  1908. ensure!(
  1909. bucket.operators.contains(&operator_worker_id),
  1910. Error::<T>::MustBeDistributionProviderOperatorForBucket
  1911. );
  1912. //
  1913. // == MUTATION SAFE ==
  1914. //
  1915. <DistributionBucketByFamilyIdById<T>>::mutate(
  1916. bucket_id.distribution_bucket_family_id,
  1917. bucket_id.distribution_bucket_index,
  1918. |bucket| {
  1919. bucket.operators.remove(&operator_worker_id);
  1920. }
  1921. );
  1922. Self::deposit_event(
  1923. RawEvent::DistributionBucketOperatorRemoved(bucket_id, operator_worker_id)
  1924. );
  1925. }
  1926. /// Set distribution bucket family metadata.
  1927. #[weight = 10_000_000] // TODO: adjust weight
  1928. pub fn set_distribution_bucket_family_metadata(
  1929. origin,
  1930. family_id: T::DistributionBucketFamilyId,
  1931. metadata: Vec<u8>,
  1932. ) {
  1933. T::ensure_distribution_working_group_leader_origin(origin)?;
  1934. Self::ensure_distribution_bucket_family_exists(&family_id)?;
  1935. //
  1936. // == MUTATION SAFE ==
  1937. //
  1938. Self::deposit_event(
  1939. RawEvent::DistributionBucketFamilyMetadataSet(
  1940. family_id,
  1941. metadata
  1942. )
  1943. );
  1944. }
  1945. // ===== Distribution Operator actions =====
  1946. /// Accept pending invite.
  1947. #[weight = 10_000_000] // TODO: adjust weight
  1948. pub fn accept_distribution_bucket_invitation(
  1949. origin,
  1950. worker_id: WorkerId<T>,
  1951. bucket_id: DistributionBucketId<T>,
  1952. ) {
  1953. T::ensure_distribution_worker_origin(origin, worker_id)?;
  1954. let bucket = Self::ensure_distribution_bucket_exists(&bucket_id)?;
  1955. ensure!(
  1956. bucket.pending_invitations.contains(&worker_id),
  1957. Error::<T>::NoDistributionBucketInvitation
  1958. );
  1959. //
  1960. // == MUTATION SAFE ==
  1961. //
  1962. <DistributionBucketByFamilyIdById<T>>::mutate(
  1963. bucket_id.distribution_bucket_family_id,
  1964. bucket_id.distribution_bucket_index,
  1965. |bucket| {
  1966. bucket.pending_invitations.remove(&worker_id);
  1967. bucket.operators.insert(worker_id);
  1968. }
  1969. );
  1970. Self::deposit_event(
  1971. RawEvent::DistributionBucketInvitationAccepted(worker_id, bucket_id)
  1972. );
  1973. }
  1974. /// Set distribution operator metadata for the distribution bucket.
  1975. #[weight = 10_000_000] // TODO: adjust weight
  1976. pub fn set_distribution_operator_metadata(
  1977. origin,
  1978. worker_id: WorkerId<T>,
  1979. bucket_id: DistributionBucketId<T>,
  1980. metadata: Vec<u8>,
  1981. ) {
  1982. T::ensure_distribution_worker_origin(origin, worker_id)?;
  1983. let bucket = Self::ensure_distribution_bucket_exists(&bucket_id)?;
  1984. ensure!(
  1985. bucket.operators.contains(&worker_id),
  1986. Error::<T>::MustBeDistributionProviderOperatorForBucket
  1987. );
  1988. //
  1989. // == MUTATION SAFE ==
  1990. //
  1991. Self::deposit_event(
  1992. RawEvent::DistributionBucketMetadataSet(worker_id, bucket_id, metadata)
  1993. );
  1994. }
  1995. // ===== Sudo actions (development mode) =====
  1996. /// Upload new data objects. Development mode.
  1997. #[weight = 10_000_000] // TODO: adjust weight
  1998. pub fn sudo_upload_data_objects(origin, params: UploadParameters<T>) {
  1999. ensure_root(origin)?;
  2000. Self::upload_data_objects(params)?;
  2001. }
  2002. /// Create a dynamic bag. Development mode.
  2003. #[weight = 10_000_000] // TODO: adjust weight
  2004. pub fn sudo_create_dynamic_bag(
  2005. origin,
  2006. bag_id: DynamicBagId<T>,
  2007. deletion_prize: Option<DynamicBagDeletionPrize<T>>,
  2008. ) {
  2009. ensure_root(origin)?;
  2010. Self::create_dynamic_bag(bag_id, deletion_prize)?;
  2011. }
  2012. }
  2013. }
  2014. // Public methods
  2015. impl<T: Trait> DataObjectStorage<T> for Module<T> {
  2016. fn can_upload_data_objects(params: &UploadParameters<T>) -> DispatchResult {
  2017. Self::validate_upload_data_objects_parameters(params).map(|_| ())
  2018. }
  2019. fn upload_data_objects(params: UploadParameters<T>) -> DispatchResult {
  2020. let bag = Self::ensure_bag_exists(&params.bag_id)?;
  2021. let bag_change = Self::validate_upload_data_objects_parameters(&params)?;
  2022. Self::upload_data_objects_inner(&params, &bag_change, &bag)?;
  2023. Ok(())
  2024. }
  2025. fn can_move_data_objects(
  2026. src_bag_id: &BagId<T>,
  2027. dest_bag_id: &BagId<T>,
  2028. objects: &BTreeSet<<T as Trait>::DataObjectId>,
  2029. ) -> DispatchResult {
  2030. Self::validate_data_objects_on_moving(src_bag_id, dest_bag_id, objects).map(|_| ())
  2031. }
  2032. fn move_data_objects(
  2033. src_bag_id: BagId<T>,
  2034. dest_bag_id: BagId<T>,
  2035. objects: BTreeSet<T::DataObjectId>,
  2036. ) -> DispatchResult {
  2037. let src_bag = Self::ensure_bag_exists(&src_bag_id)?;
  2038. let dest_bag = Self::ensure_bag_exists(&dest_bag_id)?;
  2039. let bag_change =
  2040. Self::validate_data_objects_on_moving(&src_bag_id, &dest_bag_id, &objects)?;
  2041. //
  2042. // == MUTATION SAFE ==
  2043. //
  2044. for object_id in objects.iter() {
  2045. DataObjectsById::<T>::swap(&src_bag_id, &object_id, &dest_bag_id, &object_id);
  2046. }
  2047. // Change source bag.
  2048. Self::change_storage_bucket_vouchers_for_bag(
  2049. &src_bag_id,
  2050. &src_bag,
  2051. &bag_change.voucher_update,
  2052. OperationType::Decrease,
  2053. );
  2054. // Change destination bag.
  2055. Self::change_storage_bucket_vouchers_for_bag(
  2056. &dest_bag_id,
  2057. &dest_bag,
  2058. &bag_change.voucher_update,
  2059. OperationType::Increase,
  2060. );
  2061. Self::deposit_event(RawEvent::DataObjectsMoved(src_bag_id, dest_bag_id, objects));
  2062. Ok(())
  2063. }
  2064. fn can_delete_data_objects(
  2065. bag_id: &BagId<T>,
  2066. objects: &BTreeSet<T::DataObjectId>,
  2067. ) -> DispatchResult {
  2068. Self::validate_delete_data_objects_params(bag_id, objects).map(|_| ())
  2069. }
  2070. fn delete_data_objects(
  2071. deletion_prize_account_id: T::AccountId,
  2072. bag_id: BagId<T>,
  2073. objects: BTreeSet<T::DataObjectId>,
  2074. ) -> DispatchResult {
  2075. let bag = Self::ensure_bag_exists(&bag_id)?;
  2076. let bag_change = Self::validate_delete_data_objects_params(&bag_id, &objects)?;
  2077. //
  2078. // == MUTATION SAFE ==
  2079. //
  2080. <StorageTreasury<T>>::withdraw(
  2081. &deletion_prize_account_id,
  2082. bag_change.total_deletion_prize,
  2083. )?;
  2084. for data_object_id in objects.iter() {
  2085. DataObjectsById::<T>::remove(&bag_id, &data_object_id);
  2086. }
  2087. Self::change_storage_bucket_vouchers_for_bag(
  2088. &bag_id,
  2089. &bag,
  2090. &bag_change.voucher_update,
  2091. OperationType::Decrease,
  2092. );
  2093. Self::deposit_event(RawEvent::DataObjectsDeleted(
  2094. deletion_prize_account_id,
  2095. bag_id,
  2096. objects,
  2097. ));
  2098. Ok(())
  2099. }
  2100. fn can_delete_dynamic_bag(dynamic_bag_id: &DynamicBagId<T>) -> DispatchResult {
  2101. Self::validate_delete_dynamic_bag_params(dynamic_bag_id, false).map(|_| ())
  2102. }
  2103. fn can_delete_dynamic_bag_with_objects(dynamic_bag_id: &DynamicBagId<T>) -> DispatchResult {
  2104. Self::validate_delete_dynamic_bag_params(dynamic_bag_id, true).map(|_| ())
  2105. }
  2106. fn delete_dynamic_bag(
  2107. deletion_prize_account_id: T::AccountId,
  2108. dynamic_bag_id: DynamicBagId<T>,
  2109. ) -> DispatchResult {
  2110. // make deletion always be performed on an empty bag
  2111. let deletion_prize = Self::validate_delete_dynamic_bag_params(&dynamic_bag_id, false)?;
  2112. let bag_id: BagId<T> = dynamic_bag_id.clone().into();
  2113. //
  2114. // == MUTATION SAFE ==
  2115. //
  2116. if let Some(deletion_prize) = deletion_prize {
  2117. <StorageTreasury<T>>::withdraw(&deletion_prize_account_id, deletion_prize)?;
  2118. }
  2119. <Bags<T>>::remove(&bag_id);
  2120. Self::deposit_event(RawEvent::DynamicBagDeleted(
  2121. deletion_prize_account_id,
  2122. dynamic_bag_id,
  2123. ));
  2124. Ok(())
  2125. }
  2126. fn create_dynamic_bag(
  2127. dynamic_bag_id: DynamicBagId<T>,
  2128. deletion_prize: Option<DynamicBagDeletionPrize<T>>,
  2129. ) -> DispatchResult {
  2130. // validate params and get storage & distribution buckets
  2131. let bag_change =
  2132. Self::validate_create_dynamic_bag_params(&dynamic_bag_id, &deletion_prize, &None)?;
  2133. let (storage_bucket_ids, distribution_bucket_ids) =
  2134. Self::pick_buckets_for_bag(dynamic_bag_id.clone(), &bag_change)?;
  2135. //
  2136. // == MUTATION SAFE ==
  2137. //
  2138. Self::create_dynamic_bag_inner(
  2139. &dynamic_bag_id,
  2140. &deletion_prize,
  2141. &storage_bucket_ids,
  2142. &distribution_bucket_ids,
  2143. )?;
  2144. Ok(())
  2145. }
  2146. fn create_dynamic_bag_with_objects_constraints(
  2147. dynamic_bag_id: DynamicBagId<T>,
  2148. deletion_prize: Option<DynamicBagDeletionPrize<T>>,
  2149. params: UploadParameters<T>,
  2150. ) -> DispatchResult {
  2151. let bag_change = Self::validate_create_dynamic_bag_params(
  2152. &dynamic_bag_id,
  2153. &deletion_prize,
  2154. &Some(params),
  2155. )?;
  2156. let (storage_bucket_ids, distribution_bucket_ids) =
  2157. Self::pick_buckets_for_bag(dynamic_bag_id.clone(), &bag_change)?;
  2158. //
  2159. // == MUTATION SAFE ==
  2160. //
  2161. Self::create_dynamic_bag_inner(
  2162. &dynamic_bag_id,
  2163. &deletion_prize,
  2164. &storage_bucket_ids,
  2165. &distribution_bucket_ids,
  2166. )?;
  2167. Ok(())
  2168. }
  2169. fn can_create_dynamic_bag(
  2170. bag_id: &DynamicBagId<T>,
  2171. deletion_prize: &Option<DynamicBagDeletionPrize<T>>,
  2172. ) -> DispatchResult {
  2173. Self::validate_create_dynamic_bag_params(bag_id, deletion_prize, &None).map(|_| ())
  2174. }
  2175. fn can_create_dynamic_bag_with_objects_constraints(
  2176. dynamic_bag_id: &DynamicBagId<T>,
  2177. deletion_prize: &Option<DynamicBagDeletionPrize<T>>,
  2178. params: &UploadParameters<T>,
  2179. ) -> DispatchResult {
  2180. let bag_change = Self::validate_create_dynamic_bag_params(
  2181. dynamic_bag_id,
  2182. deletion_prize,
  2183. &Some(params.clone()),
  2184. )?;
  2185. Self::pick_buckets_for_bag(dynamic_bag_id.clone(), &bag_change).map(|_| ())
  2186. }
  2187. fn ensure_bag_exists(bag_id: &BagId<T>) -> Result<Bag<T>, DispatchError> {
  2188. Self::ensure_bag_exists(bag_id)
  2189. }
  2190. fn get_data_objects_id(bag_id: &BagId<T>) -> BTreeSet<T::DataObjectId> {
  2191. DataObjectsById::<T>::iter_prefix(&bag_id)
  2192. .map(|x| x.0)
  2193. .collect()
  2194. }
  2195. }
  2196. impl<T: Trait> Module<T> {
  2197. // dynamic bag creation logic
  2198. fn create_dynamic_bag_inner(
  2199. dynamic_bag_id: &DynamicBagId<T>,
  2200. deletion_prize: &Option<DynamicBagDeletionPrize<T>>,
  2201. storage_buckets: &BTreeSet<T::StorageBucketId>,
  2202. distribution_buckets: &BTreeSet<DistributionBucketId<T>>,
  2203. ) -> DispatchResult {
  2204. //
  2205. // = MUTATION SAFE =
  2206. //
  2207. if let Some(deletion_prize) = deletion_prize.clone() {
  2208. <StorageTreasury<T>>::deposit(&deletion_prize.account_id, deletion_prize.prize)?;
  2209. }
  2210. let bag = Bag::<T> {
  2211. stored_by: storage_buckets.clone(),
  2212. deletion_prize: deletion_prize.clone().map(|dp| dp.prize),
  2213. distributed_by: distribution_buckets.clone(),
  2214. ..Default::default()
  2215. };
  2216. let bag_id: BagId<T> = dynamic_bag_id.clone().into();
  2217. <Bags<T>>::insert(&bag_id, bag);
  2218. Self::deposit_event(RawEvent::DynamicBagCreated(
  2219. dynamic_bag_id.clone(),
  2220. deletion_prize.clone(),
  2221. storage_buckets.clone(),
  2222. distribution_buckets.clone(),
  2223. ));
  2224. Ok(())
  2225. }
  2226. fn upload_data_objects_inner(
  2227. params: &UploadParameters<T>,
  2228. bag_change: &BagUpdate<BalanceOf<T>>,
  2229. bag: &Bag<T>,
  2230. ) -> DispatchResult {
  2231. let data = Self::create_data_objects(params.object_creation_list.clone());
  2232. //
  2233. // == MUTATION SAFE ==
  2234. //
  2235. <StorageTreasury<T>>::deposit(
  2236. &params.deletion_prize_source_account_id,
  2237. bag_change.total_deletion_prize,
  2238. )?;
  2239. Self::slash_data_size_fee(
  2240. &params.deletion_prize_source_account_id,
  2241. bag_change.voucher_update.objects_total_size,
  2242. );
  2243. // Save next object id.
  2244. <NextDataObjectId<T>>::put(data.next_data_object_id);
  2245. // Insert new objects.
  2246. for (data_object_id, data_object) in data.data_objects_map.iter() {
  2247. DataObjectsById::<T>::insert(&params.bag_id, &data_object_id, data_object);
  2248. }
  2249. Self::change_storage_bucket_vouchers_for_bag(
  2250. &params.bag_id,
  2251. &bag,
  2252. &bag_change.voucher_update,
  2253. OperationType::Increase,
  2254. );
  2255. Self::deposit_event(RawEvent::DataObjectsUploaded(
  2256. data.data_objects_map.keys().cloned().collect(),
  2257. params.clone(),
  2258. T::DataObjectDeletionPrize::get(),
  2259. ));
  2260. Ok(())
  2261. }
  2262. // Increment distribution family number in the storage.
  2263. fn increment_distribution_family_number() {
  2264. DistributionBucketFamilyNumber::put(Self::distribution_bucket_family_number() + 1);
  2265. }
  2266. // Decrement distribution family number in the storage. No effect on zero number.
  2267. fn decrement_distribution_family_number() {
  2268. if Self::distribution_bucket_family_number() > 0 {
  2269. DistributionBucketFamilyNumber::put(Self::distribution_bucket_family_number() - 1);
  2270. }
  2271. }
  2272. // Validates dynamic bag creation params and conditions.
  2273. fn validate_create_dynamic_bag_params(
  2274. dynamic_bag_id: &DynamicBagId<T>,
  2275. deletion_prize: &Option<DynamicBagDeletionPrize<T>>,
  2276. upload_params: &Option<UploadParameters<T>>,
  2277. ) -> Result<Option<BagUpdate<BalanceOf<T>>>, DispatchError> {
  2278. let bag_id: BagId<T> = dynamic_bag_id.clone().into();
  2279. ensure!(
  2280. !<Bags<T>>::contains_key(bag_id),
  2281. Error::<T>::DynamicBagExists
  2282. );
  2283. // call can upload data explicitly
  2284. let bag_change = upload_params
  2285. .as_ref()
  2286. .map(|params| {
  2287. // ensure coherent account ids for prize
  2288. if let Some(deletion_prize) = deletion_prize {
  2289. ensure!(
  2290. params.deletion_prize_source_account_id == deletion_prize.account_id,
  2291. Error::<T>::AccountsNotCoherent,
  2292. );
  2293. }
  2294. Self::validate_bag_change(params)
  2295. })
  2296. .transpose()?;
  2297. // check that fees are sufficient
  2298. let total_upload_fee = deletion_prize
  2299. .as_ref()
  2300. .map_or(Zero::zero(), |del_prize| del_prize.prize)
  2301. .saturating_add(bag_change.as_ref().map_or(Zero::zero(), |bag_change| {
  2302. Self::compute_upload_fees(bag_change)
  2303. }));
  2304. Self::ensure_sufficient_balance_for_upload(
  2305. deletion_prize
  2306. .as_ref()
  2307. .map(|deletion_prize| deletion_prize.account_id.clone()),
  2308. total_upload_fee,
  2309. )?;
  2310. Ok(bag_change)
  2311. }
  2312. fn ensure_sufficient_balance_for_upload(
  2313. deletion_prize_source_account_id: Option<T::AccountId>,
  2314. required_balance: BalanceOf<T>,
  2315. ) -> DispatchResult {
  2316. let usable_balance = deletion_prize_source_account_id.map_or(Zero::zero(), |account_id| {
  2317. Balances::<T>::usable_balance(account_id)
  2318. });
  2319. ensure!(
  2320. usable_balance >= required_balance,
  2321. Error::<T>::InsufficientBalance
  2322. );
  2323. Ok(())
  2324. }
  2325. // Validates dynamic bag deletion params and conditions. Returns bag's deletion prize.
  2326. fn validate_delete_dynamic_bag_params(
  2327. dynamic_bag_id: &DynamicBagId<T>,
  2328. with_objects: bool,
  2329. ) -> Result<Option<BalanceOf<T>>, DispatchError> {
  2330. Self::ensure_dynamic_bag_exists(dynamic_bag_id)?;
  2331. let dynamic_bag = Self::dynamic_bag(dynamic_bag_id);
  2332. // deletion prize = bag.deletion_prize + total_objects fees if any
  2333. let deletion_prize = if !with_objects {
  2334. ensure!(
  2335. dynamic_bag.objects_number == 0,
  2336. Error::<T>::CannotDeleteNonEmptyDynamicBag
  2337. );
  2338. dynamic_bag.deletion_prize.unwrap_or_else(Zero::zero)
  2339. } else {
  2340. let bag_id: BagId<T> = dynamic_bag_id.clone().into();
  2341. let objects_del_prize = <DataObjectsById<T>>::iter_prefix(bag_id)
  2342. .fold(BalanceOf::<T>::zero(), |acc, (_, data_object)| {
  2343. acc.saturating_add(data_object.deletion_prize)
  2344. });
  2345. dynamic_bag
  2346. .deletion_prize
  2347. .unwrap_or_else(Zero::zero)
  2348. .saturating_add(objects_del_prize)
  2349. };
  2350. ensure!(
  2351. <StorageTreasury<T>>::usable_balance() >= deletion_prize,
  2352. Error::<T>::InsufficientTreasuryBalance
  2353. );
  2354. Ok(dynamic_bag.deletion_prize)
  2355. }
  2356. // Ensures the existence of the storage bucket.
  2357. // Returns the StorageBucket object or error.
  2358. fn ensure_storage_bucket_exists(
  2359. storage_bucket_id: &T::StorageBucketId,
  2360. ) -> Result<StorageBucket<WorkerId<T>>, Error<T>> {
  2361. ensure!(
  2362. <StorageBucketById<T>>::contains_key(storage_bucket_id),
  2363. Error::<T>::StorageBucketDoesntExist
  2364. );
  2365. Ok(Self::storage_bucket_by_id(storage_bucket_id))
  2366. }
  2367. // Ensures the correct invitation for the storage bucket and storage provider. Storage provider
  2368. // must be invited.
  2369. fn ensure_bucket_storage_provider_invitation_status(
  2370. bucket: &StorageBucket<WorkerId<T>>,
  2371. worker_id: WorkerId<T>,
  2372. ) -> DispatchResult {
  2373. match bucket.operator_status {
  2374. StorageBucketOperatorStatus::Missing => {
  2375. Err(Error::<T>::NoStorageBucketInvitation.into())
  2376. }
  2377. StorageBucketOperatorStatus::StorageWorker(_) => {
  2378. Err(Error::<T>::StorageProviderAlreadySet.into())
  2379. }
  2380. StorageBucketOperatorStatus::InvitedStorageWorker(invited_worker_id) => {
  2381. ensure!(
  2382. worker_id == invited_worker_id,
  2383. Error::<T>::DifferentStorageProviderInvited
  2384. );
  2385. Ok(())
  2386. }
  2387. }
  2388. }
  2389. // Ensures the correct invitation for the storage bucket and storage provider for removal.
  2390. // Must be invited storage provider.
  2391. fn ensure_bucket_storage_provider_invitation_status_for_removal(
  2392. bucket: &StorageBucket<WorkerId<T>>,
  2393. ) -> DispatchResult {
  2394. if let StorageBucketOperatorStatus::StorageWorker(_) = bucket.operator_status {
  2395. Ok(())
  2396. } else {
  2397. Err(Error::<T>::StorageProviderMustBeSet.into())
  2398. }
  2399. }
  2400. // Ensures the correct invitation for the storage bucket and storage provider. Must be pending.
  2401. fn ensure_bucket_pending_invitation_status(
  2402. bucket: &StorageBucket<WorkerId<T>>,
  2403. ) -> DispatchResult {
  2404. match bucket.operator_status {
  2405. StorageBucketOperatorStatus::Missing => {
  2406. Err(Error::<T>::NoStorageBucketInvitation.into())
  2407. }
  2408. StorageBucketOperatorStatus::StorageWorker(_) => {
  2409. Err(Error::<T>::StorageProviderAlreadySet.into())
  2410. }
  2411. StorageBucketOperatorStatus::InvitedStorageWorker(_) => Ok(()),
  2412. }
  2413. }
  2414. // Ensures the missing invitation for the storage bucket and storage provider.
  2415. fn ensure_bucket_missing_invitation_status(
  2416. bucket: &StorageBucket<WorkerId<T>>,
  2417. ) -> DispatchResult {
  2418. match bucket.operator_status {
  2419. StorageBucketOperatorStatus::Missing => Ok(()),
  2420. StorageBucketOperatorStatus::StorageWorker(_) => {
  2421. Err(Error::<T>::StorageProviderAlreadySet.into())
  2422. }
  2423. StorageBucketOperatorStatus::InvitedStorageWorker(_) => {
  2424. Err(Error::<T>::InvitedStorageProvider.into())
  2425. }
  2426. }
  2427. }
  2428. // Ensures correct storage provider for the storage bucket.
  2429. fn ensure_bucket_invitation_accepted(
  2430. bucket: &StorageBucket<WorkerId<T>>,
  2431. worker_id: WorkerId<T>,
  2432. ) -> DispatchResult {
  2433. match bucket.operator_status {
  2434. StorageBucketOperatorStatus::Missing => {
  2435. Err(Error::<T>::StorageProviderMustBeSet.into())
  2436. }
  2437. StorageBucketOperatorStatus::InvitedStorageWorker(_) => {
  2438. Err(Error::<T>::InvalidStorageProvider.into())
  2439. }
  2440. StorageBucketOperatorStatus::StorageWorker(invited_worker_id) => {
  2441. ensure!(
  2442. worker_id == invited_worker_id,
  2443. Error::<T>::InvalidStorageProvider
  2444. );
  2445. Ok(())
  2446. }
  2447. }
  2448. }
  2449. // Create data objects from the creation data.
  2450. fn create_data_objects(
  2451. object_creation_list: Vec<DataObjectCreationParameters>,
  2452. ) -> DataObjectCandidates<T> {
  2453. let deletion_prize = T::DataObjectDeletionPrize::get();
  2454. let data_objects = object_creation_list.iter().cloned().map(|obj| DataObject {
  2455. accepted: false,
  2456. deletion_prize,
  2457. size: obj.size,
  2458. ipfs_content_id: obj.ipfs_content_id,
  2459. });
  2460. let mut next_data_object_id = Self::next_data_object_id();
  2461. let ids = iter::repeat_with(|| {
  2462. let id = next_data_object_id;
  2463. next_data_object_id += One::one();
  2464. id
  2465. })
  2466. .take(data_objects.len());
  2467. let data_objects_map = ids.zip(data_objects).collect::<BTreeMap<_, _>>();
  2468. DataObjectCandidates {
  2469. next_data_object_id,
  2470. data_objects_map,
  2471. }
  2472. }
  2473. // Ensures validity of the `accept_pending_data_objects` extrinsic parameters
  2474. fn validate_accept_pending_data_objects_params(
  2475. bag_id: &BagId<T>,
  2476. data_objects: &BTreeSet<T::DataObjectId>,
  2477. storage_bucket_id: &T::StorageBucketId,
  2478. ) -> DispatchResult {
  2479. ensure!(
  2480. !data_objects.is_empty(),
  2481. Error::<T>::DataObjectIdParamsAreEmpty
  2482. );
  2483. let bag = Self::ensure_bag_exists(bag_id)?;
  2484. Self::ensure_storage_bucket_bound(&bag, storage_bucket_id)?;
  2485. for data_object_id in data_objects.iter() {
  2486. Self::ensure_data_object_exists(bag_id, data_object_id)?;
  2487. }
  2488. Ok(())
  2489. }
  2490. // Ensures validity of the `update_storage_buckets_for_bag` extrinsic parameters
  2491. fn validate_update_storage_buckets_for_bag_params(
  2492. bag_id: &BagId<T>,
  2493. add_buckets: &BTreeSet<T::StorageBucketId>,
  2494. remove_buckets: &BTreeSet<T::StorageBucketId>,
  2495. ) -> Result<VoucherUpdate, DispatchError> {
  2496. ensure!(
  2497. !add_buckets.is_empty() || !remove_buckets.is_empty(),
  2498. Error::<T>::StorageBucketIdCollectionsAreEmpty
  2499. );
  2500. let bag = Self::ensure_bag_exists(&bag_id)?;
  2501. let new_bucket_number = bag
  2502. .stored_by
  2503. .len()
  2504. .saturating_add(add_buckets.len())
  2505. .saturating_sub(remove_buckets.len())
  2506. .saturated_into::<u64>();
  2507. ensure!(
  2508. new_bucket_number <= Self::storage_buckets_per_bag_limit(),
  2509. Error::<T>::StorageBucketPerBagLimitExceeded
  2510. );
  2511. for bucket_id in remove_buckets.iter() {
  2512. ensure!(
  2513. <StorageBucketById<T>>::contains_key(&bucket_id),
  2514. Error::<T>::StorageBucketDoesntExist
  2515. );
  2516. ensure!(
  2517. bag.stored_by.contains(&bucket_id),
  2518. Error::<T>::StorageBucketIsNotBoundToBag
  2519. );
  2520. }
  2521. for bucket_id in add_buckets.iter() {
  2522. let bucket = Self::ensure_storage_bucket_exists(bucket_id)?;
  2523. ensure!(
  2524. bucket.accepting_new_bags,
  2525. Error::<T>::StorageBucketDoesntAcceptNewBags
  2526. );
  2527. ensure!(
  2528. !bag.stored_by.contains(&bucket_id),
  2529. Error::<T>::StorageBucketIsBoundToBag
  2530. );
  2531. }
  2532. let voucher_update = VoucherUpdate {
  2533. objects_number: bag.objects_number,
  2534. objects_total_size: bag.objects_total_size,
  2535. };
  2536. Self::check_buckets_for_overflow(&add_buckets, &voucher_update)?;
  2537. Ok(voucher_update)
  2538. }
  2539. // Validate the "Move data objects between bags" operation data.
  2540. fn validate_data_objects_on_moving(
  2541. src_bag_id: &BagId<T>,
  2542. dest_bag_id: &BagId<T>,
  2543. object_ids: &BTreeSet<T::DataObjectId>,
  2544. ) -> Result<BagUpdate<BalanceOf<T>>, DispatchError> {
  2545. ensure!(
  2546. *src_bag_id != *dest_bag_id,
  2547. Error::<T>::SourceAndDestinationBagsAreEqual
  2548. );
  2549. ensure!(
  2550. !object_ids.is_empty(),
  2551. Error::<T>::DataObjectIdCollectionIsEmpty
  2552. );
  2553. Self::ensure_bag_exists(&src_bag_id)?;
  2554. let dest_bag = Self::ensure_bag_exists(&dest_bag_id)?;
  2555. let mut bag_change = BagUpdate::<BalanceOf<T>>::default();
  2556. for object_id in object_ids.iter() {
  2557. let data_object = Self::ensure_data_object_exists(&src_bag_id, object_id)?;
  2558. bag_change.add_object(data_object.size, data_object.deletion_prize);
  2559. }
  2560. Self::check_bag_for_buckets_overflow(&dest_bag, &bag_change.voucher_update)?;
  2561. Ok(bag_change)
  2562. }
  2563. // Returns only existing hashes in the blacklist from the original collection.
  2564. #[allow(clippy::redundant_closure)] // doesn't work with Substrate storage functions.
  2565. fn get_existing_hashes(hashes: &BTreeSet<Cid>) -> BTreeSet<Cid> {
  2566. Self::get_hashes_by_predicate(hashes, |cid| Blacklist::contains_key(cid))
  2567. }
  2568. // Returns only nonexisting hashes in the blacklist from the original collection.
  2569. fn get_nonexisting_hashes(hashes: &BTreeSet<Cid>) -> BTreeSet<Cid> {
  2570. Self::get_hashes_by_predicate(hashes, |cid| !Blacklist::contains_key(cid))
  2571. }
  2572. // Returns hashes from the original collection selected by predicate.
  2573. fn get_hashes_by_predicate<P: FnMut(&&Cid) -> bool>(
  2574. hashes: &BTreeSet<Cid>,
  2575. predicate: P,
  2576. ) -> BTreeSet<Cid> {
  2577. hashes
  2578. .iter()
  2579. .filter(predicate)
  2580. .cloned()
  2581. .collect::<BTreeSet<_>>()
  2582. }
  2583. // Ensure the new bucket could be created. It also validates some parameters.
  2584. fn can_create_storage_bucket(
  2585. voucher: &Voucher,
  2586. invited_worker: &Option<WorkerId<T>>,
  2587. ) -> DispatchResult {
  2588. ensure!(
  2589. voucher.size_limit <= Self::voucher_max_objects_size_limit(),
  2590. Error::<T>::VoucherMaxObjectSizeLimitExceeded
  2591. );
  2592. ensure!(
  2593. voucher.objects_limit <= Self::voucher_max_objects_number_limit(),
  2594. Error::<T>::VoucherMaxObjectNumberLimitExceeded
  2595. );
  2596. if let Some(operator_id) = invited_worker {
  2597. Self::ensure_storage_provider_operator_exists(operator_id)?;
  2598. }
  2599. Ok(())
  2600. }
  2601. // Update total objects size and number for all storage buckets assigned to a bag
  2602. // and bag counters.
  2603. fn change_storage_bucket_vouchers_for_bag(
  2604. bag_id: &BagId<T>,
  2605. bag: &Bag<T>,
  2606. voucher_update: &VoucherUpdate,
  2607. voucher_operation: OperationType,
  2608. ) {
  2609. // Change bag object and size counters.
  2610. Bags::<T>::mutate(&bag_id, |bag| {
  2611. match voucher_operation {
  2612. OperationType::Increase => {
  2613. bag.objects_total_size = bag
  2614. .objects_total_size
  2615. .saturating_add(voucher_update.objects_total_size);
  2616. bag.objects_number = bag
  2617. .objects_number
  2618. .saturating_add(voucher_update.objects_number);
  2619. }
  2620. OperationType::Decrease => {
  2621. bag.objects_total_size = bag
  2622. .objects_total_size
  2623. .saturating_sub(voucher_update.objects_total_size);
  2624. bag.objects_number = bag
  2625. .objects_number
  2626. .saturating_sub(voucher_update.objects_number);
  2627. }
  2628. }
  2629. Self::deposit_event(RawEvent::BagObjectsChanged(
  2630. bag_id.clone(),
  2631. bag.objects_total_size,
  2632. bag.objects_number,
  2633. ));
  2634. });
  2635. // Change related buckets' vouchers.
  2636. Self::change_storage_buckets_vouchers(&bag.stored_by, voucher_update, voucher_operation);
  2637. }
  2638. // Update total objects size and number for provided storage buckets.
  2639. fn change_storage_buckets_vouchers(
  2640. bucket_ids: &BTreeSet<T::StorageBucketId>,
  2641. voucher_update: &VoucherUpdate,
  2642. voucher_operation: OperationType,
  2643. ) {
  2644. for bucket_id in bucket_ids.iter() {
  2645. <StorageBucketById<T>>::mutate(bucket_id, |bucket| {
  2646. bucket.voucher =
  2647. voucher_update.get_updated_voucher(&bucket.voucher, voucher_operation);
  2648. Self::deposit_event(RawEvent::VoucherChanged(*bucket_id, bucket.voucher.clone()));
  2649. });
  2650. }
  2651. }
  2652. // Validates upload parameters and conditions (like global uploading block).
  2653. // Returns voucher update parameters for the storage buckets.
  2654. fn validate_upload_data_objects_parameters(
  2655. params: &UploadParameters<T>,
  2656. ) -> Result<BagUpdate<BalanceOf<T>>, DispatchError> {
  2657. let bag_change = Self::validate_bag_change(params)?;
  2658. Self::ensure_sufficient_balance_for_upload(
  2659. Some(params.deletion_prize_source_account_id.clone()),
  2660. Self::compute_upload_fees(&bag_change),
  2661. )?;
  2662. Self::ensure_upload_bag_validity(&params.bag_id, &bag_change.voucher_update)?;
  2663. Ok(bag_change)
  2664. }
  2665. // construct bag change after validating the inputs
  2666. fn validate_bag_change(
  2667. params: &UploadParameters<T>,
  2668. ) -> Result<BagUpdate<BalanceOf<T>>, DispatchError> {
  2669. Self::check_global_uploading_block()?;
  2670. Self::ensure_objects_creation_list_validity(&params.object_creation_list)?;
  2671. let bag_change = Self::construct_bag_change(&params.object_creation_list)?;
  2672. ensure!(
  2673. params.expected_data_size_fee == Self::data_object_per_mega_byte_fee(),
  2674. Error::<T>::DataSizeFeeChanged
  2675. );
  2676. Ok(bag_change)
  2677. }
  2678. // Validates `delete_data_objects` parameters.
  2679. // Returns voucher update for an affected bag.
  2680. fn validate_delete_data_objects_params(
  2681. bag_id: &BagId<T>,
  2682. data_object_ids: &BTreeSet<T::DataObjectId>,
  2683. ) -> Result<BagUpdate<BalanceOf<T>>, DispatchError> {
  2684. ensure!(
  2685. !data_object_ids.is_empty(),
  2686. Error::<T>::DataObjectIdParamsAreEmpty
  2687. );
  2688. Self::ensure_bag_exists(bag_id)?;
  2689. let bag_change = data_object_ids
  2690. .iter()
  2691. .try_fold::<_, _, Result<_, DispatchError>>(
  2692. BagUpdate::default(),
  2693. |acc, data_object_id| {
  2694. let data_object = Self::ensure_data_object_exists(bag_id, data_object_id)?;
  2695. let bag_change = acc
  2696. .clone()
  2697. .add_object(data_object.size, data_object.deletion_prize);
  2698. Ok(bag_change)
  2699. },
  2700. )?;
  2701. ensure!(
  2702. <StorageTreasury<T>>::usable_balance() >= bag_change.total_deletion_prize,
  2703. Error::<T>::InsufficientTreasuryBalance
  2704. );
  2705. Ok(bag_change)
  2706. }
  2707. fn ensure_upload_bag_validity(
  2708. bag_id: &BagId<T>,
  2709. voucher_update: &VoucherUpdate,
  2710. ) -> DispatchResult {
  2711. let bag = Self::ensure_bag_exists(bag_id)?;
  2712. // Check buckets.
  2713. Self::check_bag_for_buckets_overflow(&bag, voucher_update)?;
  2714. Ok(())
  2715. }
  2716. fn compute_upload_fees(bag_change: &BagUpdate<BalanceOf<T>>) -> BalanceOf<T> {
  2717. let size_fee =
  2718. Self::calculate_data_storage_fee(bag_change.voucher_update.objects_total_size);
  2719. bag_change.total_deletion_prize.saturating_add(size_fee)
  2720. }
  2721. // Check global uploading block.
  2722. fn check_global_uploading_block() -> DispatchResult {
  2723. ensure!(!Self::uploading_blocked(), Error::<T>::UploadingBlocked);
  2724. Ok(())
  2725. }
  2726. fn construct_bag_change(
  2727. object_creation_list: &[DataObjectCreationParameters],
  2728. ) -> Result<BagUpdate<BalanceOf<T>>, DispatchError> {
  2729. let bag_change = object_creation_list
  2730. .iter()
  2731. .try_fold::<_, _, Result<_, DispatchError>>(
  2732. BagUpdate::default(),
  2733. |acc, object_params| {
  2734. // Should be non-empty hash.
  2735. ensure!(
  2736. !object_params.ipfs_content_id.is_empty(),
  2737. Error::<T>::EmptyContentId
  2738. );
  2739. // Should be non-zero size.
  2740. ensure!(object_params.size != 0, Error::<T>::ZeroObjectSize);
  2741. // Should not be blacklisted.
  2742. ensure!(
  2743. !Blacklist::contains_key(&object_params.ipfs_content_id),
  2744. Error::<T>::DataObjectBlacklisted,
  2745. );
  2746. let bag_change = acc
  2747. .clone()
  2748. .add_object(object_params.size, T::DataObjectDeletionPrize::get());
  2749. Ok(bag_change)
  2750. },
  2751. )?;
  2752. Ok(bag_change)
  2753. }
  2754. // objects creation list validity
  2755. fn ensure_objects_creation_list_validity(
  2756. object_creation_list: &[DataObjectCreationParameters],
  2757. ) -> DispatchResult {
  2758. // Check object creation list is not empty
  2759. ensure!(
  2760. !object_creation_list.is_empty(),
  2761. Error::<T>::NoObjectsOnUpload
  2762. );
  2763. // Check data objects' max size.
  2764. ensure!(
  2765. object_creation_list
  2766. .iter()
  2767. .all(|obj| obj.size <= T::MaxDataObjectSize::get()),
  2768. Error::<T>::MaxDataObjectSizeExceeded
  2769. );
  2770. Ok(())
  2771. }
  2772. // Iterates through buckets in the bag. Verifies voucher parameters to fit the new limits:
  2773. // objects number and total objects size.
  2774. fn check_bag_for_buckets_overflow(
  2775. bag: &Bag<T>,
  2776. voucher_update: &VoucherUpdate,
  2777. ) -> DispatchResult {
  2778. Self::check_buckets_for_overflow(&bag.stored_by, voucher_update)
  2779. }
  2780. // Iterates through buckets. Verifies voucher parameters to fit the new limits:
  2781. // objects number and total objects size.
  2782. fn check_buckets_for_overflow(
  2783. bucket_ids: &BTreeSet<T::StorageBucketId>,
  2784. voucher_update: &VoucherUpdate,
  2785. ) -> DispatchResult {
  2786. for bucket_id in bucket_ids.iter() {
  2787. let bucket = Self::storage_bucket_by_id(bucket_id);
  2788. // Total object number limit is not exceeded.
  2789. ensure!(
  2790. voucher_update.objects_number + bucket.voucher.objects_used
  2791. <= bucket.voucher.objects_limit,
  2792. Error::<T>::StorageBucketObjectNumberLimitReached
  2793. );
  2794. // Total object size limit is not exceeded.
  2795. ensure!(
  2796. voucher_update.objects_total_size + bucket.voucher.size_used
  2797. <= bucket.voucher.size_limit,
  2798. Error::<T>::StorageBucketObjectSizeLimitReached
  2799. );
  2800. }
  2801. Ok(())
  2802. }
  2803. // Calculate data storage fee based on size. Fee-value uses megabytes as measure value.
  2804. // Data size will be rounded to nearest greater MB integer.
  2805. pub(crate) fn calculate_data_storage_fee(bytes: u64) -> BalanceOf<T> {
  2806. let mb_fee = Self::data_object_per_mega_byte_fee();
  2807. const ONE_MB: u64 = 1_048_576;
  2808. let mut megabytes = bytes / ONE_MB;
  2809. if bytes % ONE_MB > 0 {
  2810. megabytes += 1; // rounding to the nearest greater integer
  2811. }
  2812. mb_fee.saturating_mul(megabytes.saturated_into())
  2813. }
  2814. // Slash data size fee if fee value is set to non-zero.
  2815. fn slash_data_size_fee(account_id: &T::AccountId, bytes: u64) {
  2816. let fee = Self::calculate_data_storage_fee(bytes);
  2817. if fee != Zero::zero() {
  2818. let _ = Balances::<T>::slash(account_id, fee);
  2819. }
  2820. }
  2821. // helper pick buckets for bag
  2822. fn pick_buckets_for_bag(
  2823. dynamic_bag_id: DynamicBagId<T>,
  2824. bag_change: &Option<BagUpdate<BalanceOf<T>>>,
  2825. ) -> Result<BucketPair<T>, DispatchError> {
  2826. let bag_type: DynamicBagType = dynamic_bag_id.into();
  2827. let storage_bucket_ids = Self::pick_storage_buckets_for_dynamic_bag(
  2828. bag_type,
  2829. bag_change.map(|bag_change| bag_change.voucher_update),
  2830. );
  2831. let distribution_bucket_ids = Self::pick_distribution_buckets_for_dynamic_bag(bag_type);
  2832. if bag_change.is_some() {
  2833. ensure!(
  2834. !storage_bucket_ids.is_empty(),
  2835. Error::<T>::StorageBucketIdCollectionsAreEmpty
  2836. );
  2837. }
  2838. Ok((storage_bucket_ids, distribution_bucket_ids))
  2839. }
  2840. // Selects storage bucket ID sets to assign to the dynamic bag.
  2841. pub(crate) fn pick_storage_buckets_for_dynamic_bag(
  2842. bag_type: DynamicBagType,
  2843. voucher_update: Option<VoucherUpdate>,
  2844. ) -> BTreeSet<T::StorageBucketId> {
  2845. StorageBucketPicker::<T>::pick_storage_buckets(bag_type, voucher_update)
  2846. }
  2847. // Selects distributed bucket ID sets to assign to the dynamic bag.
  2848. pub(crate) fn pick_distribution_buckets_for_dynamic_bag(
  2849. bag_type: DynamicBagType,
  2850. ) -> BTreeSet<DistributionBucketId<T>> {
  2851. DistributionBucketPicker::<T>::pick_distribution_buckets(bag_type)
  2852. }
  2853. // Get default dynamic bag policy by bag type.
  2854. fn get_default_dynamic_bag_creation_policy(
  2855. bag_type: DynamicBagType,
  2856. ) -> DynamicBagCreationPolicy<T::DistributionBucketFamilyId> {
  2857. let number_of_storage_buckets = match bag_type {
  2858. DynamicBagType::Member => T::DefaultMemberDynamicBagNumberOfStorageBuckets::get(),
  2859. DynamicBagType::Channel => T::DefaultChannelDynamicBagNumberOfStorageBuckets::get(),
  2860. };
  2861. DynamicBagCreationPolicy::<T::DistributionBucketFamilyId> {
  2862. number_of_storage_buckets,
  2863. ..Default::default()
  2864. }
  2865. }
  2866. // Loads dynamic bag creation policy or use default values.
  2867. pub(crate) fn get_dynamic_bag_creation_policy(
  2868. bag_type: DynamicBagType,
  2869. ) -> DynamicBagCreationPolicy<T::DistributionBucketFamilyId> {
  2870. if DynamicBagCreationPolicies::<T>::contains_key(bag_type) {
  2871. return Self::dynamic_bag_creation_policy(bag_type);
  2872. }
  2873. Self::get_default_dynamic_bag_creation_policy(bag_type)
  2874. }
  2875. // Verifies storage operator existence.
  2876. fn ensure_storage_provider_operator_exists(operator_id: &WorkerId<T>) -> DispatchResult {
  2877. ensure!(
  2878. T::ensure_storage_worker_exists(operator_id).is_ok(),
  2879. Error::<T>::StorageProviderOperatorDoesntExist
  2880. );
  2881. Ok(())
  2882. }
  2883. // Returns the bag by the static bag id.
  2884. #[cfg(test)]
  2885. pub(crate) fn static_bag(static_bag_id: &StaticBagId) -> Bag<T> {
  2886. let bag_id: BagId<T> = static_bag_id.clone().into();
  2887. Self::bag(&bag_id)
  2888. }
  2889. // Returns the bag by the dynamic bag id.
  2890. pub(crate) fn dynamic_bag(dynamic_bag_id: &DynamicBagId<T>) -> Bag<T> {
  2891. let bag_id: BagId<T> = dynamic_bag_id.clone().into();
  2892. Self::bag(&bag_id)
  2893. }
  2894. // Check the dynamic bag existence.
  2895. fn ensure_dynamic_bag_exists(
  2896. dynamic_bag_id: &DynamicBagId<T>,
  2897. ) -> Result<Bag<T>, DispatchError> {
  2898. let bag_id: BagId<T> = dynamic_bag_id.clone().into();
  2899. Self::ensure_bag_exists(&bag_id)
  2900. }
  2901. // Check the dynamic bag existence. Static bags always exist.
  2902. fn ensure_bag_exists(bag_id: &BagId<T>) -> Result<Bag<T>, DispatchError> {
  2903. if let BagId::<T>::Dynamic(_) = &bag_id {
  2904. ensure!(
  2905. <Bags<T>>::contains_key(&bag_id),
  2906. Error::<T>::DynamicBagDoesntExist
  2907. );
  2908. }
  2909. Ok(Self::bag(&bag_id))
  2910. }
  2911. // Check the storage bucket binding for a bag.
  2912. fn ensure_storage_bucket_bound(
  2913. bag: &Bag<T>,
  2914. storage_bucket_id: &T::StorageBucketId,
  2915. ) -> DispatchResult {
  2916. ensure!(
  2917. bag.stored_by.contains(storage_bucket_id),
  2918. Error::<T>::StorageBucketIsNotBoundToBag
  2919. );
  2920. Ok(())
  2921. }
  2922. // Check the data object existence inside a bag.
  2923. pub(crate) fn ensure_data_object_exists(
  2924. bag_id: &BagId<T>,
  2925. data_object_id: &T::DataObjectId,
  2926. ) -> Result<DataObject<BalanceOf<T>>, DispatchError> {
  2927. ensure!(
  2928. <DataObjectsById<T>>::contains_key(bag_id, data_object_id),
  2929. Error::<T>::DataObjectDoesntExist
  2930. );
  2931. Ok(Self::data_object_by_id(bag_id, data_object_id))
  2932. }
  2933. // Ensures the existence of the distribution bucket family.
  2934. // Returns the DistributionBucketFamily object or error.
  2935. fn ensure_distribution_bucket_family_exists(
  2936. family_id: &T::DistributionBucketFamilyId,
  2937. ) -> Result<DistributionBucketFamily<T>, Error<T>> {
  2938. ensure!(
  2939. <DistributionBucketFamilyById<T>>::contains_key(family_id),
  2940. Error::<T>::DistributionBucketFamilyDoesntExist
  2941. );
  2942. Ok(Self::distribution_bucket_family_by_id(family_id))
  2943. }
  2944. // Ensures the existence of the distribution bucket.
  2945. // Returns the DistributionBucket object or error.
  2946. fn ensure_distribution_bucket_exists(
  2947. bucket_id: &DistributionBucketId<T>,
  2948. ) -> Result<DistributionBucket<T>, Error<T>> {
  2949. ensure!(
  2950. <DistributionBucketByFamilyIdById<T>>::contains_key(
  2951. bucket_id.distribution_bucket_family_id,
  2952. bucket_id.distribution_bucket_index
  2953. ),
  2954. Error::<T>::DistributionBucketDoesntExist
  2955. );
  2956. Ok(Self::distribution_bucket_by_family_id_by_index(
  2957. bucket_id.distribution_bucket_family_id,
  2958. bucket_id.distribution_bucket_index,
  2959. ))
  2960. }
  2961. // Ensures validity of the `update_distribution_buckets_for_bag` extrinsic parameters
  2962. fn validate_update_distribution_buckets_for_bag_params(
  2963. bag_id: &BagId<T>,
  2964. family_id: &T::DistributionBucketFamilyId,
  2965. add_buckets: &BTreeSet<T::DistributionBucketIndex>,
  2966. remove_buckets: &BTreeSet<T::DistributionBucketIndex>,
  2967. ) -> DispatchResult {
  2968. ensure!(
  2969. !add_buckets.is_empty() || !remove_buckets.is_empty(),
  2970. Error::<T>::DistributionBucketIdCollectionsAreEmpty
  2971. );
  2972. let bag = Self::ensure_bag_exists(bag_id)?;
  2973. Self::ensure_distribution_bucket_family_exists(family_id)?;
  2974. let new_bucket_number = bag
  2975. .distributed_by
  2976. .len()
  2977. .saturating_add(add_buckets.len())
  2978. .saturating_sub(remove_buckets.len())
  2979. .saturated_into::<u64>();
  2980. ensure!(
  2981. new_bucket_number <= Self::distribution_buckets_per_bag_limit(),
  2982. Error::<T>::MaxDistributionBucketNumberPerBagLimitExceeded
  2983. );
  2984. for bucket_index in remove_buckets.iter() {
  2985. let bucket_id = Self::create_distribution_bucket_id(*family_id, *bucket_index);
  2986. Self::ensure_distribution_bucket_exists(&bucket_id)?;
  2987. ensure!(
  2988. bag.distributed_by.contains(&bucket_id),
  2989. Error::<T>::DistributionBucketIsNotBoundToBag
  2990. );
  2991. }
  2992. for bucket_index in add_buckets.iter() {
  2993. let bucket_id = Self::create_distribution_bucket_id(*family_id, *bucket_index);
  2994. let bucket = Self::ensure_distribution_bucket_exists(&bucket_id)?;
  2995. ensure!(
  2996. bucket.accepting_new_bags,
  2997. Error::<T>::DistributionBucketDoesntAcceptNewBags
  2998. );
  2999. ensure!(
  3000. !bag.distributed_by.contains(&bucket_id),
  3001. Error::<T>::DistributionBucketIsBoundToBag
  3002. );
  3003. }
  3004. Ok(())
  3005. }
  3006. // Ensures validity of the `update_families_in_dynamic_bag_creation_policy` extrinsic parameters
  3007. fn validate_update_families_in_dynamic_bag_creation_policy_params(
  3008. families: &BTreeMap<T::DistributionBucketFamilyId, u32>,
  3009. ) -> DispatchResult {
  3010. for (family_id, _) in families.iter() {
  3011. Self::ensure_distribution_bucket_family_exists(family_id)?;
  3012. }
  3013. Ok(())
  3014. }
  3015. // Generate random number from zero to upper_bound (excluding).
  3016. pub(crate) fn random_index(seed: &[u8], upper_bound: u64) -> u64 {
  3017. if upper_bound == 0 {
  3018. return upper_bound;
  3019. }
  3020. let mut rand: u64 = 0;
  3021. for (offset, byte) in seed.iter().enumerate().take(8) {
  3022. rand += (*byte as u64) << offset;
  3023. }
  3024. rand % upper_bound
  3025. }
  3026. // Get initial random seed. It handles the error on the initial block.
  3027. pub(crate) fn get_initial_random_seed() -> T::Hash {
  3028. // Cannot create randomness in the initial block (Substrate error).
  3029. if <frame_system::Module<T>>::block_number() == Zero::zero() {
  3030. Default::default()
  3031. } else {
  3032. T::Randomness::random_seed()
  3033. }
  3034. }
  3035. // Verify parameters for the `invite_distribution_bucket_operator` extrinsic.
  3036. fn ensure_distribution_provider_can_be_invited(
  3037. bucket: &DistributionBucket<T>,
  3038. worker_id: &WorkerId<T>,
  3039. ) -> DispatchResult {
  3040. ensure!(
  3041. T::ensure_distribution_worker_exists(worker_id).is_ok(),
  3042. Error::<T>::DistributionProviderOperatorDoesntExist
  3043. );
  3044. ensure!(
  3045. !bucket.pending_invitations.contains(worker_id),
  3046. Error::<T>::DistributionProviderOperatorAlreadyInvited
  3047. );
  3048. ensure!(
  3049. !bucket.operators.contains(worker_id),
  3050. Error::<T>::DistributionProviderOperatorSet
  3051. );
  3052. ensure!(
  3053. bucket.pending_invitations.len().saturated_into::<u64>()
  3054. < T::MaxNumberOfPendingInvitationsPerDistributionBucket::get(),
  3055. Error::<T>::MaxNumberOfPendingInvitationsLimitForDistributionBucketReached
  3056. );
  3057. Ok(())
  3058. }
  3059. // Verify that dynamic bag creation policies has no dependencies on given distribution bucket
  3060. // family for all bag types.
  3061. fn check_dynamic_bag_creation_policy_for_dependencies(
  3062. family_id: &T::DistributionBucketFamilyId,
  3063. dynamic_bag_type: DynamicBagType,
  3064. ) -> DispatchResult {
  3065. let creation_policy = Self::get_dynamic_bag_creation_policy(dynamic_bag_type);
  3066. ensure!(
  3067. !creation_policy.families.contains_key(family_id),
  3068. Error::<T>::DistributionFamilyBoundToBagCreationPolicy
  3069. );
  3070. Ok(())
  3071. }
  3072. // Add and/or remove distribution buckets assignments to bags.
  3073. fn change_bag_assignments(
  3074. add_buckets: &BTreeSet<DistributionBucketId<T>>,
  3075. remove_buckets: &BTreeSet<DistributionBucketId<T>>,
  3076. ) {
  3077. for bucket_id in add_buckets.iter() {
  3078. if DistributionBucketByFamilyIdById::<T>::contains_key(
  3079. bucket_id.distribution_bucket_family_id,
  3080. bucket_id.distribution_bucket_index,
  3081. ) {
  3082. DistributionBucketByFamilyIdById::<T>::mutate(
  3083. bucket_id.distribution_bucket_family_id,
  3084. bucket_id.distribution_bucket_index,
  3085. |bucket| {
  3086. bucket.register_bag_assignment();
  3087. },
  3088. )
  3089. }
  3090. }
  3091. for bucket_id in remove_buckets.iter() {
  3092. if DistributionBucketByFamilyIdById::<T>::contains_key(
  3093. bucket_id.distribution_bucket_family_id,
  3094. bucket_id.distribution_bucket_index,
  3095. ) {
  3096. DistributionBucketByFamilyIdById::<T>::mutate(
  3097. bucket_id.distribution_bucket_family_id,
  3098. bucket_id.distribution_bucket_index,
  3099. |bucket| {
  3100. bucket.unregister_bag_assignment();
  3101. },
  3102. )
  3103. }
  3104. }
  3105. }
  3106. // Checks distribution buckets for bag assignment number. Returns true only if all 'assigned_bags' are
  3107. // zero.
  3108. fn no_bags_assigned(family_id: &T::DistributionBucketFamilyId) -> bool {
  3109. DistributionBucketByFamilyIdById::<T>::iter_prefix_values(family_id)
  3110. .all(|b| b.no_bags_assigned())
  3111. }
  3112. // Creates distribution bucket ID from family ID and bucket index.
  3113. pub(crate) fn create_distribution_bucket_id(
  3114. distribution_bucket_family_id: T::DistributionBucketFamilyId,
  3115. distribution_bucket_index: T::DistributionBucketIndex,
  3116. ) -> DistributionBucketId<T> {
  3117. DistributionBucketId::<T> {
  3118. distribution_bucket_family_id,
  3119. distribution_bucket_index,
  3120. }
  3121. }
  3122. }