lib.rs 120 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841
  1. //! # Content Directory Module
  2. //!
  3. //! The content directory is an on-chain index of all content and metadata,
  4. //! and related concepts - such as channels and playlists.
  5. //!
  6. //! - [`substrate_content_directory_module::Trait`](./trait.Trait.html)
  7. //! - [`Call`](./enum.Call.html)
  8. //! - [`Module`](./struct.Module.html)
  9. //!
  10. //! ## Overview
  11. //!
  12. //! The content directory provides functions for:
  13. //!
  14. //! - Creating/removal and managing curator groups
  15. //! - Creating classes and managing their permissions
  16. //! - Adding schemas to the class
  17. //! - Creating and removal of entities and managing their permissions
  18. //! - Adding schemas support to the respective class entities
  19. //! - Transfering entities ownership
  20. //! - Updating entity property values
  21. //!
  22. //! ## Terminology
  23. //!
  24. //! ### Class
  25. //!
  26. //! - **Class Properties:** All properties that have been used on this class across different class schemas.
  27. //! Unlikely to be more than roughly 20 properties per class, often less.
  28. //! For Person, think "height", "weight", etc.
  29. //!
  30. //! - **Schemas:** All schemas, that are available for this class, think v0.0 Person, v.1.0 Person, etc.
  31. //!
  32. //! ### Entity
  33. //!
  34. //! - **Supported Schemas:** What schemas under which entity of the respective class is available, think
  35. //! v.2.0 Person schema for John, v3.0 Person schema for John
  36. //! Unlikely to be more than roughly 20ish, assuming schemas for a given class eventually stableize,
  37. //! or that very old schema are eventually removed.
  38. //!
  39. //! - **Property Values:** Values for properties, declared on class level,
  40. //! that are used in respective Class Entity after adding Schema support.
  41. //!
  42. //! ## Interface
  43. //!
  44. //! ### Dispatchable Functions
  45. //!
  46. //! #### Curator groups
  47. //!
  48. //! - `add_curator_group` - Add new curator group to the runtime storage
  49. //! - `remove_curator_group` - Remove curator group under given `curator_group_id` from runtime storage.
  50. //! The origin of this call must be a blog owner.
  51. //! - `set_curator_group_status` - Set activity status for curator group under given `curator_group_id`
  52. //! - `add_curator_to_group` - Add curator to curator group under given `curator_group_id`
  53. //! - `remove_curator_from_group` - Remove curator from a given curator group.
  54. //!
  55. //! #### Classes
  56. //!
  57. //! - `create_class` - Create new class with provided parameters
  58. //! - `add_maintainer_to_class` - Add curator group under given curator_group_id as class maintainer
  59. //! - `remove_maintainer_from_class` - Remove curator group under given curator_group_id from class maintainers set
  60. //! - `update_class_permissions` - Update class permissions under specific class_id
  61. //! - `add_class_schema` - Create new class schema from existing property ids and new properties
  62. //! - `update_class_schema_status` - Update schema status under specific schema_id in class
  63. //!
  64. //! #### Entities
  65. //!
  66. //! - `create_entity` - Create new entity of respective class
  67. //! - `remove_entity` - Remove entity under provided entity_id
  68. //! - `update_entity_permissions` - Update entity permissions
  69. //! - `add_schema_support_to_entity` - add schema support to entity under given schema_id and provided property values
  70. //! - `update_entity_property_values` - Update entity property values with provided ones
  71. //! - `clear_entity_property_vector` - Clear property value vector under given entity_id & in class schema property id
  72. //! - `remove_at_entity_property_vector` - Remove value at given index_in_property_vector
  73. //! from property values vector under in_class schema property id
  74. //! - `insert_at_entity_property_vector` - Insert single input property values at given index in property vector
  75. //! into property values vector under in class schema property id
  76. //!
  77. //! #### Others
  78. //!
  79. //! - `update_entity_creation_voucher` - Update/create new entity creation voucher for given entity controller with individual limit
  80. //! - `transaction` - This extrinsic allows a batch operation, which is atomic, over the following operations:
  81. //! **Entity creation**
  82. //! **Adding schema support to the entity**
  83. //! **Update property values of the entity**
  84. //!
  85. //! ## Usage
  86. //!
  87. //! The following example shows how to use the content directory module in your custom module.
  88. //!
  89. //! ### Prerequisites
  90. //!
  91. //! Import the content directory module into your custom module and derive the module configuration
  92. //! trait from the content directory trait.
  93. //!
  94. //! ### Add curator group
  95. //!
  96. //! ```
  97. //! use frame_support::{decl_module, assert_ok};
  98. //! use system::{self as system, ensure_signed};
  99. //!
  100. //! pub trait Trait: pallet_content_directory::Trait {}
  101. //!
  102. //! decl_module! {
  103. //! pub struct Module<T: Trait> for enum Call where origin: T::Origin {
  104. //! #[weight = 10_000_000]
  105. //! pub fn add_curator_group(origin) -> Result<(), &'static str> {
  106. //! <pallet_content_directory::Module<T>>::add_curator_group(origin)?;
  107. //! Ok(())
  108. //! }
  109. //! }
  110. //! }
  111. //! # fn main() {}
  112. //! ```
  113. // Ensure we're `no_std` when compiling for Wasm.
  114. #![cfg_attr(not(feature = "std"), no_std)]
  115. #![recursion_limit = "256"]
  116. #[cfg(test)]
  117. mod tests;
  118. mod class;
  119. mod entity;
  120. mod errors;
  121. mod helpers;
  122. mod mock;
  123. mod operations;
  124. mod permissions;
  125. mod schema;
  126. pub use class::*;
  127. pub use entity::*;
  128. pub use errors::*;
  129. pub use helpers::*;
  130. pub use operations::*;
  131. pub use permissions::*;
  132. pub use schema::*;
  133. use core::hash::Hash;
  134. use core::ops::AddAssign;
  135. use codec::{Codec, Decode, Encode};
  136. use frame_support::storage::IterableStorageMap;
  137. use frame_support::{
  138. decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure, traits::Get, Parameter,
  139. };
  140. #[cfg(feature = "std")]
  141. pub use serde::{Deserialize, Serialize};
  142. use sp_arithmetic::traits::{BaseArithmetic, One, Zero};
  143. use sp_runtime::traits::{MaybeSerializeDeserialize, Member};
  144. use sp_std::borrow::ToOwned;
  145. use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet};
  146. use sp_std::vec;
  147. use sp_std::vec::Vec;
  148. use system::ensure_signed;
  149. pub use errors::Error;
  150. use core::debug_assert;
  151. /// Type, used in diffrent numeric constraints representations
  152. pub type MaxNumber = u32;
  153. /// Module configuration trait for this Substrate module.
  154. pub trait Trait: system::Trait + ActorAuthenticator + Clone {
  155. /// The overarching event type.
  156. type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
  157. /// Nonce type is used to avoid data race update conditions, when performing property value vector operations
  158. type Nonce: Parameter
  159. + Member
  160. + BaseArithmetic
  161. + Codec
  162. + Default
  163. + Copy
  164. + Clone
  165. + MaybeSerializeDeserialize
  166. + Eq
  167. + PartialEq
  168. + Ord
  169. + From<u32>;
  170. /// Type of identifier for classes
  171. type ClassId: Parameter
  172. + Member
  173. + BaseArithmetic
  174. + Codec
  175. + Default
  176. + Copy
  177. + Clone
  178. + Hash
  179. + MaybeSerializeDeserialize
  180. + Eq
  181. + PartialEq
  182. + Ord;
  183. /// Type of identifier for entities
  184. type EntityId: Parameter
  185. + Member
  186. + BaseArithmetic
  187. + Codec
  188. + Default
  189. + Copy
  190. + Clone
  191. + Hash
  192. + MaybeSerializeDeserialize
  193. + Eq
  194. + PartialEq
  195. + Ord;
  196. /// Security/configuration constraints
  197. /// Type, representing min & max property name length constraints
  198. type PropertyNameLengthConstraint: Get<InputValidationLengthConstraint>;
  199. /// Type, representing min & max property description length constraints
  200. type PropertyDescriptionLengthConstraint: Get<InputValidationLengthConstraint>;
  201. /// Type, representing min & max class name length constraints
  202. type ClassNameLengthConstraint: Get<InputValidationLengthConstraint>;
  203. /// Type, representing min & max class description length constraints
  204. type ClassDescriptionLengthConstraint: Get<InputValidationLengthConstraint>;
  205. /// The maximum number of classes
  206. type MaxNumberOfClasses: Get<MaxNumber>;
  207. /// The maximum number of maintainers per class constraint
  208. type MaxNumberOfMaintainersPerClass: Get<MaxNumber>;
  209. /// The maximum number of curators per group constraint
  210. type MaxNumberOfCuratorsPerGroup: Get<MaxNumber>;
  211. /// The maximum number of schemas per class constraint
  212. type MaxNumberOfSchemasPerClass: Get<MaxNumber>;
  213. /// The maximum number of properties per class constraint
  214. type MaxNumberOfPropertiesPerSchema: Get<MaxNumber>;
  215. /// The maximum number of operations during single invocation of `transaction`
  216. type MaxNumberOfOperationsDuringAtomicBatching: Get<MaxNumber>;
  217. /// The maximum length of vector property value constarint
  218. type VecMaxLengthConstraint: Get<VecMaxLength>;
  219. /// The maximum length of text property value constarint
  220. type TextMaxLengthConstraint: Get<TextMaxLength>;
  221. /// The maximum length of text, that will be hashed property value constarint
  222. type HashedTextMaxLengthConstraint: Get<HashedTextMaxLength>;
  223. /// Entities creation constraint per class
  224. type MaxNumberOfEntitiesPerClass: Get<Self::EntityId>;
  225. /// Entities creation constraint per individual
  226. type IndividualEntitiesCreationLimit: Get<Self::EntityId>;
  227. }
  228. decl_storage! {
  229. trait Store for Module<T: Trait> as ContentDirectory {
  230. /// Map, representing ClassId -> Class relation
  231. pub ClassById get(fn class_by_id) config(): map hasher(blake2_128_concat) T::ClassId => Class<T::EntityId, T::ClassId, T::CuratorGroupId>;
  232. /// Map, representing EntityId -> Entity relation
  233. pub EntityById get(fn entity_by_id) config(): map hasher(blake2_128_concat) T::EntityId => Entity<T::ClassId, T::MemberId, T::Hash, T::EntityId, T::Nonce>;
  234. /// Map, representing CuratorGroupId -> CuratorGroup relation
  235. pub CuratorGroupById get(fn curator_group_by_id) config(): map hasher(blake2_128_concat) T::CuratorGroupId => CuratorGroup<T>;
  236. /// Mapping of class id and its property id to the respective entity id and property value hash.
  237. pub UniquePropertyValueHashes get(fn unique_property_value_hashes): double_map hasher(blake2_128_concat) (T::ClassId, PropertyId), hasher(blake2_128_concat) T::Hash => ();
  238. /// Next runtime storage values used to maintain next id value, used on creation of respective curator groups, classes and entities
  239. pub NextClassId get(fn next_class_id) config(): T::ClassId;
  240. pub NextEntityId get(fn next_entity_id) config(): T::EntityId;
  241. pub NextCuratorGroupId get(fn next_curator_group_id) config(): T::CuratorGroupId;
  242. // The voucher associated with entity creation for a given class and controller.
  243. // Is updated whenever an entity is created in a given class by a given controller.
  244. // Constraint is updated by Root, an initial value comes from `ClassPermissions::default_entity_creation_voucher_upper_bound`.
  245. pub EntityCreationVouchers get(fn entity_creation_vouchers):
  246. double_map hasher(blake2_128_concat) T::ClassId, hasher(blake2_128_concat) EntityController<T::MemberId> => EntityCreationVoucher<T>;
  247. }
  248. }
  249. decl_module! {
  250. pub struct Module<T: Trait> for enum Call where origin: T::Origin {
  251. // ======
  252. // Next set of extrinsics can only be invoked by lead.
  253. // ======
  254. /// Initializing events
  255. fn deposit_event() = default;
  256. /// Add new curator group to runtime storage
  257. #[weight = 10_000_000] // TODO: adjust weight
  258. pub fn add_curator_group(
  259. origin,
  260. ) -> DispatchResult {
  261. // Ensure given origin is lead
  262. ensure_is_lead::<T>(origin)?;
  263. //
  264. // == MUTATION SAFE ==
  265. //
  266. let curator_group_id = Self::next_curator_group_id();
  267. // Insert empty curator group with `active` parameter set to false
  268. <CuratorGroupById<T>>::insert(curator_group_id, CuratorGroup::<T>::default());
  269. // Increment the next curator curator_group_id:
  270. <NextCuratorGroupId<T>>::mutate(|n| *n += T::CuratorGroupId::one());
  271. // Trigger event
  272. Self::deposit_event(RawEvent::CuratorGroupAdded(curator_group_id));
  273. Ok(())
  274. }
  275. /// Remove curator group under given `curator_group_id` from runtime storage
  276. #[weight = 10_000_000] // TODO: adjust weight
  277. pub fn remove_curator_group(
  278. origin,
  279. curator_group_id: T::CuratorGroupId,
  280. ) -> DispatchResult {
  281. // Ensure given origin is lead
  282. ensure_is_lead::<T>(origin)?;
  283. // Ensure CuratorGroup under given curator_group_id exists
  284. let curator_group = Self::ensure_curator_group_exists(&curator_group_id)?;
  285. // We should previously ensure that curator_group maintains no classes to be able to remove it
  286. curator_group.ensure_curator_group_maintains_no_classes()?;
  287. //
  288. // == MUTATION SAFE ==
  289. //
  290. // Remove curator group under given curator group id from runtime storage
  291. <CuratorGroupById<T>>::remove(curator_group_id);
  292. // Trigger event
  293. Self::deposit_event(RawEvent::CuratorGroupRemoved(curator_group_id));
  294. Ok(())
  295. }
  296. /// Set `is_active` status for curator group under given `curator_group_id`
  297. #[weight = 10_000_000] // TODO: adjust weight
  298. pub fn set_curator_group_status(
  299. origin,
  300. curator_group_id: T::CuratorGroupId,
  301. is_active: bool,
  302. ) -> DispatchResult {
  303. // Ensure given origin is lead
  304. ensure_is_lead::<T>(origin)?;
  305. // Ensure curator group under provided curator_group_id already exist
  306. Self::ensure_curator_group_under_given_id_exists(&curator_group_id)?;
  307. //
  308. // == MUTATION SAFE ==
  309. //
  310. // Set `is_active` status for curator group under given `curator_group_id`
  311. <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
  312. curator_group.set_status(is_active)
  313. });
  314. // Trigger event
  315. Self::deposit_event(RawEvent::CuratorGroupStatusSet(curator_group_id, is_active));
  316. Ok(())
  317. }
  318. /// Add curator to curator group under given `curator_group_id`
  319. #[weight = 10_000_000] // TODO: adjust weight
  320. pub fn add_curator_to_group(
  321. origin,
  322. curator_group_id: T::CuratorGroupId,
  323. curator_id: T::CuratorId,
  324. ) -> DispatchResult {
  325. // Ensure given origin is lead
  326. ensure_is_lead::<T>(origin)?;
  327. // Ensure curator group under provided curator_group_id already exist, retrieve corresponding one
  328. let curator_group = Self::ensure_curator_group_exists(&curator_group_id)?;
  329. // Ensure max number of curators per group limit not reached yet
  330. curator_group.ensure_max_number_of_curators_limit_not_reached()?;
  331. //
  332. // == MUTATION SAFE ==
  333. //
  334. // Insert curator_id into curator_group under given curator_group_id
  335. <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
  336. curator_group.get_curators_mut().insert(curator_id);
  337. });
  338. // Trigger event
  339. Self::deposit_event(RawEvent::CuratorAdded(curator_group_id, curator_id));
  340. Ok(())
  341. }
  342. /// Remove curator from a given curator group
  343. #[weight = 10_000_000] // TODO: adjust weight
  344. pub fn remove_curator_from_group(
  345. origin,
  346. curator_group_id: T::CuratorGroupId,
  347. curator_id: T::CuratorId,
  348. ) -> DispatchResult {
  349. // Ensure given origin is lead
  350. ensure_is_lead::<T>(origin)?;
  351. // Ensure curator group under provided curator_group_id already exist, retrieve corresponding one
  352. let curator_group = Self::ensure_curator_group_exists(&curator_group_id)?;
  353. // Ensure curator under provided curator_id is CuratorGroup member
  354. curator_group.ensure_curator_in_group_exists(&curator_id)?;
  355. //
  356. // == MUTATION SAFE ==
  357. //
  358. // Remove curator_id from curator_group under given curator_group_id
  359. <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
  360. curator_group.get_curators_mut().remove(&curator_id);
  361. });
  362. // Trigger event
  363. Self::deposit_event(RawEvent::CuratorRemoved(curator_group_id, curator_id));
  364. Ok(())
  365. }
  366. /// Updates or creates new `EntityCreationVoucher` for given `EntityController` with individual limit
  367. #[weight = 10_000_000] // TODO: adjust weight
  368. pub fn update_entity_creation_voucher(
  369. origin,
  370. class_id: T::ClassId,
  371. controller: EntityController<T::MemberId>,
  372. maximum_entities_count: T::EntityId
  373. ) -> DispatchResult {
  374. // Ensure given origin is lead
  375. ensure_is_lead::<T>(origin)?;
  376. // Ensure Class under given id exists, return corresponding one
  377. Self::ensure_known_class_id(class_id)?;
  378. // Ensure maximum_entities_count does not exceed individual entities creation limit
  379. Self::ensure_valid_number_of_class_entities_per_actor_constraint(maximum_entities_count)?;
  380. // Check voucher existance
  381. let voucher_exists = <EntityCreationVouchers<T>>::contains_key(class_id, &controller);
  382. //
  383. // == MUTATION SAFE ==
  384. //
  385. if voucher_exists {
  386. // Set new maximum_entities_count limit for selected voucher
  387. let mut entity_creation_voucher = Self::entity_creation_vouchers(class_id, &controller);
  388. entity_creation_voucher.set_maximum_entities_count(maximum_entities_count);
  389. <EntityCreationVouchers<T>>::insert(class_id, controller.clone(), entity_creation_voucher.clone());
  390. // Trigger event
  391. Self::deposit_event(RawEvent::EntityCreationVoucherUpdated(controller, entity_creation_voucher))
  392. } else {
  393. // Create new EntityCreationVoucher instance with provided maximum_entities_count
  394. let entity_creation_voucher = EntityCreationVoucher::new(maximum_entities_count);
  395. // Add newly created `EntityCreationVoucher` into `EntityCreationVouchers`
  396. // runtime storage under given `class_id`, `controller` key
  397. <EntityCreationVouchers<T>>::insert(class_id, controller.clone(), entity_creation_voucher.clone());
  398. // Trigger event
  399. Self::deposit_event(RawEvent::EntityCreationVoucherCreated(controller, entity_creation_voucher));
  400. }
  401. Ok(())
  402. }
  403. /// Create new `Class` with provided parameters
  404. #[weight = 10_000_000] // TODO: adjust weight
  405. pub fn create_class(
  406. origin,
  407. name: Vec<u8>,
  408. description: Vec<u8>,
  409. class_permissions: ClassPermissions<T::CuratorGroupId>,
  410. maximum_entities_count: T::EntityId,
  411. default_entity_creation_voucher_upper_bound: T::EntityId
  412. ) -> DispatchResult {
  413. // Ensure given origin is lead
  414. ensure_is_lead::<T>(origin)?;
  415. // Ensure, that all entities creation limits, defined for a given Class, are valid
  416. Self::ensure_entities_creation_limits_are_valid(maximum_entities_count, default_entity_creation_voucher_upper_bound)?;
  417. // Ensure max number of classes limit not reached
  418. Self::ensure_class_limit_not_reached()?;
  419. // Ensure ClassNameLengthConstraint conditions satisfied
  420. Self::ensure_class_name_is_valid(&name)?;
  421. // Ensure ClassDescriptionLengthConstraint conditions satisfied
  422. Self::ensure_class_description_is_valid(&description)?;
  423. // Perform required checks to ensure class_maintainers under provided class_permissions are valid
  424. let class_maintainers = class_permissions.get_maintainers();
  425. Self::ensure_class_maintainers_are_valid(class_maintainers)?;
  426. //
  427. // == MUTATION SAFE ==
  428. //
  429. // Create new Class instance from provided values
  430. let class = Class::new(
  431. class_permissions, name, description, maximum_entities_count, default_entity_creation_voucher_upper_bound
  432. );
  433. let class_id = Self::next_class_id();
  434. // Add new `Class` to runtime storage
  435. <ClassById<T>>::insert(&class_id, class);
  436. // Increment the next class id:
  437. <NextClassId<T>>::mutate(|n| *n += T::ClassId::one());
  438. // Trigger event
  439. Self::deposit_event(RawEvent::ClassCreated(class_id));
  440. Ok(())
  441. }
  442. /// Add curator group under given `curator_group_id` as `Class` maintainer
  443. #[weight = 10_000_000] // TODO: adjust weight
  444. pub fn add_maintainer_to_class(
  445. origin,
  446. class_id: T::ClassId,
  447. curator_group_id: T::CuratorGroupId,
  448. ) -> DispatchResult {
  449. // Ensure given origin is lead
  450. ensure_is_lead::<T>(origin)?;
  451. // Ensure Class under provided class_id exist, retrieve corresponding one
  452. let class = Self::ensure_known_class_id(class_id)?;
  453. // Ensure CuratorGroup under provided curator_group_id exist, retrieve corresponding one
  454. Self::ensure_curator_group_under_given_id_exists(&curator_group_id)?;
  455. // Ensure the max number of maintainers per Class limit not reached
  456. let class_permissions = class.get_permissions_ref();
  457. // Ensure max number of maintainers per Class constraint satisfied
  458. Self::ensure_maintainers_limit_not_reached(class_permissions.get_maintainers())?;
  459. // Ensure maintainer under provided curator_group_id is not added to the Class maintainers set yet
  460. class_permissions.ensure_maintainer_does_not_exist::<T>(&curator_group_id)?;
  461. //
  462. // == MUTATION SAFE ==
  463. //
  464. // Insert `curator_group_id` into `maintainers` set, associated with given `Class`
  465. <ClassById<T>>::mutate(class_id, |class|
  466. class.get_permissions_mut().get_maintainers_mut().insert(curator_group_id)
  467. );
  468. // Increment the number of classes, curator group under given `curator_group_id` maintains
  469. <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
  470. curator_group.increment_number_of_classes_maintained_count();
  471. });
  472. // Trigger event
  473. Self::deposit_event(RawEvent::MaintainerAdded(class_id, curator_group_id));
  474. Ok(())
  475. }
  476. /// Remove curator group under given `curator_group_id` from `Class` maintainers set
  477. #[weight = 10_000_000] // TODO: adjust weight
  478. pub fn remove_maintainer_from_class(
  479. origin,
  480. class_id: T::ClassId,
  481. curator_group_id: T::CuratorGroupId,
  482. ) -> DispatchResult {
  483. // Ensure given origin is lead
  484. ensure_is_lead::<T>(origin)?;
  485. // Ensure Class under given id exists, return corresponding one
  486. let class = Self::ensure_known_class_id(class_id)?;
  487. // Ensure maintainer under provided curator_group_id was previously added
  488. // to the maintainers set, associated with corresponding Class
  489. class.get_permissions_ref().ensure_maintainer_exists::<T>(&curator_group_id)?;
  490. //
  491. // == MUTATION SAFE ==
  492. //
  493. // Remove `curator_group_id` from `maintainers` set, associated with given `Class`
  494. <ClassById<T>>::mutate(class_id, |class|
  495. class.get_permissions_mut().get_maintainers_mut().remove(&curator_group_id)
  496. );
  497. // Decrement the number of classes, curator group under given `curator_group_id` maintains
  498. <CuratorGroupById<T>>::mutate(curator_group_id, |curator_group| {
  499. curator_group.decrement_number_of_classes_maintained_count();
  500. });
  501. // Trigger event
  502. Self::deposit_event(RawEvent::MaintainerRemoved(class_id, curator_group_id));
  503. Ok(())
  504. }
  505. /// Update `ClassPermissions` under specific `class_id`
  506. #[weight = 10_000_000] // TODO: adjust weight
  507. pub fn update_class_permissions(
  508. origin,
  509. class_id: T::ClassId,
  510. updated_any_member: Option<bool>,
  511. updated_entity_creation_blocked: Option<bool>,
  512. updated_all_entity_property_values_locked: Option<bool>,
  513. updated_maintainers: Option<BTreeSet<T::CuratorGroupId>>,
  514. ) -> DispatchResult {
  515. // Ensure given origin is lead
  516. ensure_is_lead::<T>(origin)?;
  517. // Ensure Class under given id exists, return corresponding one
  518. let class = Self::ensure_known_class_id(class_id)?;
  519. // Perform required checks to ensure class_maintainers are valid
  520. if let Some(ref updated_maintainers) = updated_maintainers {
  521. Self::ensure_class_maintainers_are_valid(updated_maintainers)?;
  522. }
  523. //
  524. // == MUTATION SAFE ==
  525. //
  526. let class_permissions = class.get_permissions();
  527. // Make updated class_permissions from parameters provided
  528. let updated_class_permissions = Self::make_updated_class_permissions(
  529. class_permissions, updated_any_member, updated_entity_creation_blocked,
  530. updated_all_entity_property_values_locked, updated_maintainers
  531. );
  532. // If class_permissions update has been performed
  533. if let Some(updated_class_permissions) = updated_class_permissions {
  534. // Update `class_permissions` under given class id
  535. <ClassById<T>>::mutate(class_id, |class| {
  536. class.update_permissions(updated_class_permissions)
  537. });
  538. // Trigger event
  539. Self::deposit_event(RawEvent::ClassPermissionsUpdated(class_id));
  540. }
  541. Ok(())
  542. }
  543. /// Create new class schema from existing property ids and new properties
  544. #[weight = 10_000_000] // TODO: adjust weight
  545. pub fn add_class_schema(
  546. origin,
  547. class_id: T::ClassId,
  548. existing_properties: BTreeSet<PropertyId>,
  549. new_properties: Vec<Property<T::ClassId>>
  550. ) -> DispatchResult {
  551. // Ensure given origin is lead
  552. ensure_is_lead::<T>(origin)?;
  553. // Ensure Class under given id exists, return corresponding one
  554. let class = Self::ensure_known_class_id(class_id)?;
  555. // Ensure Schemas limit per Class not reached
  556. class.ensure_schemas_limit_not_reached::<T>()?;
  557. // Ensure both existing and new properties for future Schema are not empty
  558. Self::ensure_non_empty_schema(&existing_properties, &new_properties)?;
  559. // Ensure max number of properties per Schema limit not reached
  560. class.ensure_properties_limit_not_reached::<T>(&new_properties)?;
  561. // Complete all checks to ensure all provided new_properties are valid
  562. Self::ensure_all_properties_are_valid(&new_properties)?;
  563. // Id of next Class Schema being added
  564. let schema_id = class.get_schemas().len() as SchemaId;
  565. let class_properties = class.get_properties();
  566. // Ensure all Property names are unique within Class
  567. Self::ensure_all_property_names_are_unique(&class_properties, &new_properties)?;
  568. // Ensure existing_properties are valid indices of properties, corresponding to chosen Class
  569. Self::ensure_schema_properties_are_valid_indices(&existing_properties, &class_properties)?;
  570. //
  571. // == MUTATION SAFE ==
  572. //
  573. // Create `Schema` instance from existing and new property ids
  574. let schema = Self::create_class_schema(existing_properties, &class_properties, &new_properties);
  575. // Update class properties after new `Schema` added
  576. let updated_class_properties = Self::make_updated_class_properties(class_properties, new_properties);
  577. // Update Class properties and schemas
  578. <ClassById<T>>::mutate(class_id, |class| {
  579. class.set_properties(updated_class_properties);
  580. class.get_schemas_mut().push(schema);
  581. });
  582. // Trigger event
  583. Self::deposit_event(RawEvent::ClassSchemaAdded(class_id, schema_id));
  584. Ok(())
  585. }
  586. /// Update `schema_status` under specific `schema_id` in `Class`
  587. #[weight = 10_000_000] // TODO: adjust weight
  588. pub fn update_class_schema_status(
  589. origin,
  590. class_id: T::ClassId,
  591. schema_id: SchemaId,
  592. schema_status: bool
  593. ) -> DispatchResult {
  594. // Ensure given origin is lead
  595. ensure_is_lead::<T>(origin)?;
  596. // Ensure Class under given id exists, return corresponding one
  597. let class = Self::ensure_known_class_id(class_id)?;
  598. // Ensure Class already contains schema under provided schema_id
  599. class.ensure_schema_id_exists::<T>(schema_id)?;
  600. //
  601. // == MUTATION SAFE ==
  602. //
  603. // Update class schema status
  604. <ClassById<T>>::mutate(class_id, |class| {
  605. class.update_schema_status(schema_id, schema_status)
  606. });
  607. // Trigger event
  608. Self::deposit_event(RawEvent::ClassSchemaStatusUpdated(class_id, schema_id, schema_status));
  609. Ok(())
  610. }
  611. /// Update entity permissions
  612. #[weight = 10_000_000] // TODO: adjust weight
  613. pub fn update_entity_permissions(
  614. origin,
  615. entity_id: T::EntityId,
  616. updated_frozen: Option<bool>,
  617. updated_referenceable: Option<bool>
  618. ) -> DispatchResult {
  619. // Ensure given origin is lead
  620. ensure_is_lead::<T>(origin)?;
  621. // Ensure Entity under given id exists, return corresponding one
  622. let entity = Self::ensure_known_entity_id(entity_id)?;
  623. //
  624. // == MUTATION SAFE ==
  625. //
  626. // Make updated entity_permissions from parameters provided
  627. let entity_permissions = entity.get_permissions();
  628. let updated_entity_permissions =
  629. Self::make_updated_entity_permissions(entity_permissions, updated_frozen, updated_referenceable);
  630. // Update entity permissions under given entity id
  631. if let Some(updated_entity_permissions) = updated_entity_permissions {
  632. <EntityById<T>>::mutate(entity_id, |entity| {
  633. entity.update_permissions(updated_entity_permissions)
  634. });
  635. // Trigger event
  636. Self::deposit_event(RawEvent::EntityPermissionsUpdated(entity_id));
  637. }
  638. Ok(())
  639. }
  640. /// Transfer ownership to new `EntityController` for `Entity` under given `entity_id`
  641. /// `new_property_value_references_with_same_owner_flag_set` should be provided manually
  642. #[weight = 10_000_000] // TODO: adjust weight
  643. pub fn transfer_entity_ownership(
  644. origin,
  645. entity_id: T::EntityId,
  646. new_controller: EntityController<T::MemberId>,
  647. new_property_value_references_with_same_owner_flag_set: BTreeMap<PropertyId, InputPropertyValue<T>>
  648. ) -> DispatchResult {
  649. // Ensure given origin is lead
  650. ensure_is_lead::<T>(origin)?;
  651. // Ensure Entity under given entity_id exists, retrieve corresponding Entity & Class
  652. let (entity, class) = Self::ensure_known_entity_and_class(entity_id)?;
  653. // Ensure provided new_entity_controller is not equal to current one
  654. entity.get_permissions_ref().ensure_controllers_are_not_equal::<T>(&new_controller)?;
  655. // Ensure any inbound InputPropertyValue::Reference with same_owner flag set points to the given Entity
  656. entity.ensure_inbound_same_owner_rc_is_zero::<T>()?;
  657. let class_properties = class.get_properties();
  658. let class_id = entity.get_class_id();
  659. let entity_property_values = entity.get_values();
  660. // Create wrapper structure from provided entity_property_values and their corresponding Class properties
  661. let values_for_existing_properties = match StoredValuesForExistingProperties::from(&class_properties, &entity_property_values) {
  662. Ok(values_for_existing_properties) => values_for_existing_properties,
  663. Err(e) => {
  664. debug_assert!(false, "Should not fail! {:?}", e);
  665. return Err(e.into())
  666. }
  667. };
  668. // Filter provided values_for_existing_properties, leaving only `Reference`'s with `SameOwner` flag set
  669. // Retrieve the set of corresponding property ids
  670. let entity_property_id_references_with_same_owner_flag_set =
  671. Self::get_property_id_references_with_same_owner_flag_set(values_for_existing_properties);
  672. // Ensure all ids of provided `new_property_value_references_with_same_owner_flag_set`
  673. // corresponding to property ids of respective Class Property references with same owner flag set
  674. Self::ensure_only_reference_ids_with_same_owner_flag_set_provided(
  675. &entity_property_id_references_with_same_owner_flag_set,
  676. &new_property_value_references_with_same_owner_flag_set
  677. )?;
  678. // Retrieve ids of all entity property values, that are references with same owner flag set and which are not provided
  679. // in new property value references with same owner flag set
  680. let unused_property_id_references_with_same_owner_flag_set = Self::compute_unused_property_ids(
  681. &new_property_value_references_with_same_owner_flag_set, &entity_property_id_references_with_same_owner_flag_set
  682. );
  683. // Perform checks to ensure all required property_values under provided unused_schema_property_ids provided
  684. Self::ensure_all_required_properties_provided(&class_properties, &unused_property_id_references_with_same_owner_flag_set)?;
  685. // Create wrapper structure from provided new_property_value_references_with_same_owner_flag_set and their corresponding Class properties
  686. let new_values_for_existing_properties = InputValuesForExistingProperties::from(
  687. &class_properties, &new_property_value_references_with_same_owner_flag_set
  688. )?;
  689. // Ensure all provided `new_property_value_references_with_same_owner_flag_set` are valid
  690. Self::ensure_are_valid_references_with_same_owner_flag_set(
  691. new_values_for_existing_properties, &new_controller
  692. )?;
  693. let new_output_property_value_references_with_same_owner_flag_set = Self::make_output_property_values(new_property_value_references_with_same_owner_flag_set);
  694. // Compute StoredPropertyValues, which respective Properties have unique flag set
  695. // (skip PropertyIds, which respective property values under this Entity are default and non required)
  696. let new_output_values_for_existing_properties =
  697. StoredValuesForExistingProperties::from(&class_properties, &new_output_property_value_references_with_same_owner_flag_set)?;
  698. // Compute new unique property value hashes.
  699. // Ensure new property value hashes with `unique` flag set are `unique` on `Class` level
  700. let new_unique_hashes = Self::ensure_new_property_values_respect_uniquness(
  701. class_id, new_output_values_for_existing_properties,
  702. )?;
  703. //
  704. // == MUTATION SAFE ==
  705. //
  706. // Used to compute old unique hashes, that should be substituted with new ones.
  707. let old_unique_hashes =
  708. Self::compute_old_unique_hashes(&new_output_property_value_references_with_same_owner_flag_set, &entity_property_values);
  709. // Add property values, that should be unique on Class level
  710. Self::add_unique_property_value_hashes(class_id, new_unique_hashes);
  711. // Remove unique hashes, that were substituted with new ones.
  712. Self::remove_unique_property_value_hashes(class_id, old_unique_hashes);
  713. // Make updated entity_property_values from parameters provided
  714. let entity_property_values_updated =
  715. Self::make_updated_property_value_references_with_same_owner_flag_set(
  716. unused_property_id_references_with_same_owner_flag_set, &entity_property_values,
  717. &new_output_property_value_references_with_same_owner_flag_set,
  718. );
  719. // Transfer entity ownership
  720. let entities_inbound_rcs_delta = if let Some(entity_property_values_updated) = entity_property_values_updated {
  721. // Calculate entities reference counter side effects for current operation
  722. let entities_inbound_rcs_delta =
  723. Self::get_updated_inbound_rcs_delta(
  724. entity_id, class_properties, entity_property_values, new_output_property_value_references_with_same_owner_flag_set
  725. )?;
  726. // Update InboundReferenceCounter, based on previously calculated ReferenceCounterSideEffects, for each Entity involved
  727. Self::update_entities_rcs(&entities_inbound_rcs_delta);
  728. <EntityById<T>>::mutate(entity_id, |entity| {
  729. // Update current Entity property values with updated ones
  730. entity.set_values(entity_property_values_updated);
  731. // Set up new controller for the current Entity instance
  732. entity.get_permissions_mut().set_conroller(new_controller.clone());
  733. });
  734. entities_inbound_rcs_delta
  735. } else {
  736. // Set up new controller for the current Entity instance
  737. <EntityById<T>>::mutate(entity_id, |entity| {
  738. entity.get_permissions_mut().set_conroller(new_controller.clone());
  739. });
  740. None
  741. };
  742. // Trigger event
  743. Self::deposit_event(RawEvent::EntityOwnershipTransfered(entity_id, new_controller, entities_inbound_rcs_delta));
  744. Ok(())
  745. }
  746. // ======
  747. // The next set of extrinsics can be invoked by anyone who can properly sign for provided value of `Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>`.
  748. // ======
  749. /// Create entity.
  750. /// If someone is making an entity of this class for first time,
  751. /// then a voucher is also added with the class limit as the default limit value.
  752. #[weight = 10_000_000] // TODO: adjust weight
  753. pub fn create_entity(
  754. origin,
  755. class_id: T::ClassId,
  756. actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
  757. ) -> DispatchResult {
  758. let account_id = ensure_signed(origin)?;
  759. // Ensure Class under given id exists, return corresponding one
  760. let class = Self::ensure_class_exists(class_id)?;
  761. // Ensure maximum entities limit per class not reached
  762. class.ensure_maximum_entities_count_limit_not_reached::<T>()?;
  763. let class_permissions = class.get_permissions_ref();
  764. // Ensure entities creation is not blocked on Class level
  765. class_permissions.ensure_entity_creation_not_blocked::<T>()?;
  766. // Ensure actor can create entities
  767. Self::ensure_can_create_entities(&class_permissions, &account_id, &actor)?;
  768. let entity_controller = EntityController::<T::MemberId>::from_actor::<T>(&actor);
  769. // Check if entity creation voucher exists
  770. let voucher_exists = if <EntityCreationVouchers<T>>::contains_key(class_id, &entity_controller) {
  771. // Ensure voucher limit not reached
  772. Self::entity_creation_vouchers(class_id, &entity_controller).ensure_voucher_limit_not_reached()?;
  773. true
  774. } else {
  775. false
  776. };
  777. //
  778. // == MUTATION SAFE ==
  779. //
  780. // Create voucher, update if exists
  781. if voucher_exists {
  782. // Increment number of created entities count, if specified voucher already exist
  783. <EntityCreationVouchers<T>>::mutate(class_id, &entity_controller, |entity_creation_voucher| {
  784. entity_creation_voucher.increment_created_entities_count()
  785. });
  786. } else {
  787. // Create new voucher for given entity creator with default limit
  788. let mut entity_creation_voucher = EntityCreationVoucher::new(class.get_default_entity_creation_voucher_upper_bound());
  789. // Increase created entities count by 1 to maintain valid entity_creation_voucher state after following Entity added
  790. entity_creation_voucher.increment_created_entities_count();
  791. <EntityCreationVouchers<T>>::insert(class_id, entity_controller.clone(), entity_creation_voucher);
  792. }
  793. // Create new entity
  794. let entity_id = Self::next_entity_id();
  795. let new_entity = Entity::<T::ClassId, T::MemberId, T::Hash, T::EntityId, T::Nonce>::new(
  796. entity_controller,
  797. class_id,
  798. BTreeSet::new(),
  799. BTreeMap::new(),
  800. );
  801. // Save newly created entity:
  802. <EntityById<T>>::insert(entity_id, new_entity);
  803. // Increment the next entity id:
  804. <NextEntityId<T>>::mutate(|n| *n += T::EntityId::one());
  805. // Increment number of entities, associated with this class
  806. <ClassById<T>>::mutate(class_id, |class| {
  807. class.increment_entities_count();
  808. });
  809. // Trigger event
  810. Self::deposit_event(RawEvent::EntityCreated(actor, entity_id));
  811. Ok(())
  812. }
  813. /// Remove `Entity` under provided `entity_id`
  814. #[weight = 10_000_000] // TODO: adjust weight
  815. pub fn remove_entity(
  816. origin,
  817. actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
  818. entity_id: T::EntityId,
  819. ) -> DispatchResult {
  820. let account_id = ensure_signed(origin)?;
  821. // Retrieve Class, Entity and EntityAccessLevel for the actor, attemting to perform operation
  822. let (class, entity, access_level) = Self::ensure_class_entity_and_access_level(account_id, entity_id, &actor)?;
  823. // Ensure actor with given EntityAccessLevel can remove entity
  824. EntityPermissions::<T::MemberId>::ensure_group_can_remove_entity::<T>(access_level)?;
  825. // Ensure any inbound InputPropertyValue::Reference points to the given Entity
  826. entity.ensure_rc_is_zero::<T>()?;
  827. let class_properties = class.get_properties();
  828. let class_id = entity.get_class_id();
  829. let entity_values = entity.get_values();
  830. let unique_property_value_hashes = match StoredValuesForExistingProperties::<T>::from(&class_properties, &entity_values) {
  831. Ok(values_for_existing_properties) => values_for_existing_properties.compute_unique_hashes(),
  832. Err(e) => {
  833. debug_assert!(false, "Should not fail! {:?}", e);
  834. return Err(e.into())
  835. }
  836. };
  837. //
  838. // == MUTATION SAFE ==
  839. //
  840. // Remove property value entries, that should be unique on Class level
  841. Self::remove_unique_property_value_hashes(class_id, unique_property_value_hashes);
  842. // Remove entity
  843. <EntityById<T>>::remove(entity_id);
  844. // Decrement class entities counter
  845. <ClassById<T>>::mutate(class_id, |class| class.decrement_entities_count());
  846. let entity_controller = EntityController::<T::MemberId>::from_actor::<T>(&actor);
  847. // Decrement entity_creation_voucher after entity removal perfomed
  848. <EntityCreationVouchers<T>>::mutate(class_id, entity_controller, |entity_creation_voucher| {
  849. entity_creation_voucher.decrement_created_entities_count();
  850. });
  851. // Trigger event
  852. Self::deposit_event(RawEvent::EntityRemoved(actor, entity_id));
  853. Ok(())
  854. }
  855. /// Add schema support to entity under given `schema_id` and provided `property_values`
  856. #[weight = 10_000_000] // TODO: adjust weight
  857. pub fn add_schema_support_to_entity(
  858. origin,
  859. actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
  860. entity_id: T::EntityId,
  861. schema_id: SchemaId,
  862. new_property_values: BTreeMap<PropertyId, InputPropertyValue<T>>
  863. ) -> DispatchResult {
  864. let account_id = ensure_signed(origin)?;
  865. // Retrieve Class, Entity and EntityAccessLevel for the actor, attemting to perform operation
  866. let (class, entity, _) = Self::ensure_class_entity_and_access_level(account_id, entity_id, &actor)?;
  867. // Ensure Class Schema under given index exists, return corresponding Schema
  868. let schema = class.ensure_schema_exists::<T>(schema_id)?.to_owned();
  869. let class_properties = class.get_properties();
  870. // Create wrapper structure from provided new_property_values and their corresponding Class properties
  871. let new_values_for_existing_properties = InputValuesForExistingProperties::from(&class_properties, &new_property_values)?;
  872. // Ensure Schema under given id is not added to given Entity yet
  873. entity.ensure_schema_id_is_not_added::<T>(schema_id)?;
  874. // Ensure provided new_property_values are not added to the Entity values map yet
  875. entity.ensure_property_values_are_not_added(&new_property_values)?;
  876. // Ensure provided schema can be added to the Entity
  877. schema.ensure_is_active::<T>()?;
  878. // Ensure all provided new property values are for properties in the given schema
  879. schema.ensure_has_properties(&new_property_values)?;
  880. // Retrieve Schema property ids, which are not provided in new_property_values
  881. let unused_schema_property_ids = Self::compute_unused_property_ids(&new_property_values, schema.get_properties());
  882. // Perform checks to ensure all required property_values under provided unused_schema_property_ids provided
  883. Self::ensure_all_required_properties_provided(&class_properties, &unused_schema_property_ids)?;
  884. // Ensure all property_values under given Schema property ids are valid
  885. let entity_controller = entity.get_permissions_ref().get_controller();
  886. // Validate all values, provided in new_values_for_existing_properties,
  887. // against the type of its Property and check any additional constraints
  888. Self::ensure_property_values_are_valid(&entity_controller, &new_values_for_existing_properties)?;
  889. let class_id = entity.get_class_id();
  890. let entity_property_values = entity.get_values();
  891. let new_output_property_values = Self::make_output_property_values(new_property_values);
  892. // Compute updated entity values, after new schema support added
  893. let entity_values_updated = Self::make_updated_entity_property_values(
  894. schema, entity_property_values, &new_output_property_values
  895. );
  896. let new_output_values_for_existing_properties = StoredValuesForExistingProperties::from(&class_properties, &new_output_property_values)?;
  897. // Retrieve StoredPropertyValues, which respective Properties have unique flag set
  898. // (skip PropertyIds, which respective property values under this Entity are default and non required)
  899. let new_unique_property_value_hashes = new_output_values_for_existing_properties.compute_unique_hashes();
  900. // Ensure all provided Properties with unique flag set are unique on Class level
  901. Self::ensure_property_value_hashes_unique_option_satisfied(class_id, &new_unique_property_value_hashes)?;
  902. //
  903. // == MUTATION SAFE ==
  904. //
  905. // Add property value hashes, that should be unique on Class level
  906. Self::add_unique_property_value_hashes(class_id, new_unique_property_value_hashes);
  907. // Calculate entities reference counter side effects for current operation
  908. let entities_inbound_rcs_delta = Self::calculate_entities_inbound_rcs_delta(
  909. entity_id, new_output_values_for_existing_properties, DeltaMode::Increment
  910. );
  911. // Update InboundReferenceCounter, based on previously calculated entities_inbound_rcs_delta, for each Entity involved
  912. Self::update_entities_rcs(&entities_inbound_rcs_delta);
  913. // Add schema support to `Entity` under given `entity_id`
  914. <EntityById<T>>::mutate(entity_id, |entity| {
  915. // Add a new schema to the list of schemas supported by this entity.
  916. entity.get_supported_schemas_mut().insert(schema_id);
  917. // Update entity values only if new properties have been added.
  918. if entity_values_updated.len() > entity.get_values_ref().len() {
  919. entity.set_values(entity_values_updated);
  920. }
  921. });
  922. // Trigger event
  923. Self::deposit_event(RawEvent::EntitySchemaSupportAdded(actor, entity_id, schema_id, entities_inbound_rcs_delta));
  924. Ok(())
  925. }
  926. /// Update `Entity` `InputPropertyValue`'s with provided ones
  927. #[weight = 10_000_000] // TODO: adjust weight
  928. pub fn update_entity_property_values(
  929. origin,
  930. actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
  931. entity_id: T::EntityId,
  932. new_property_values: BTreeMap<PropertyId, InputPropertyValue<T>>
  933. ) -> DispatchResult {
  934. let account_id = ensure_signed(origin)?;
  935. // Retrieve Class, Entity and EntityAccessLevel for the actor, attemting to perform operation
  936. let (class, entity, access_level) = Self::ensure_class_entity_and_access_level(account_id, entity_id, &actor)?;
  937. // Ensure property values were not locked on Class level
  938. class.ensure_property_values_unlocked::<T>()?;
  939. let entity_values_ref = entity.get_values_ref();
  940. // Filter new_property_values, that are identical to entity_property_values.
  941. // Get `new_property_values`, that are not in `entity_property_values`
  942. let new_property_values = Self::try_filter_identical_property_values(entity_values_ref, new_property_values);
  943. // Ensure all provided new_property_values are already added to the current Entity instance
  944. Self::ensure_all_property_values_are_already_added(entity_values_ref, &new_property_values)?;
  945. let class_properties = class.get_properties();
  946. // Create wrapper structure from new_property_values and their corresponding Class properties
  947. let new_values_for_existing_properties = InputValuesForExistingProperties::from(&class_properties, &new_property_values)?;
  948. // Ensure all provided property values are unlocked for the actor with given access_level
  949. Self::ensure_all_property_values_are_unlocked_from(&new_values_for_existing_properties, access_level)?;
  950. let entity_controller = entity.get_permissions_ref().get_controller();
  951. // Validate all values, provided in values_for_existing_properties,
  952. // against the type of its Property and check any additional constraints
  953. Self::ensure_property_values_are_valid(&entity_controller, &new_values_for_existing_properties)?;
  954. let class_id = entity.get_class_id();
  955. // Get current property values of an Entity
  956. let entity_property_values = entity.get_values();
  957. let new_output_property_values = Self::make_output_property_values(new_property_values);
  958. // Compute StoredPropertyValues, which respective Properties have unique flag set
  959. // (skip PropertyIds, which respective property values under this Entity are default and non required)
  960. let new_output_values_for_existing_properties =
  961. StoredValuesForExistingProperties::from(&class_properties, &new_output_property_values)?;
  962. // Compute new unique property value hashes.
  963. // Ensure new property value hashes with `unique` flag set are `unique` on `Class` level
  964. let new_unique_hashes = Self::ensure_new_property_values_respect_uniquness(
  965. class_id, new_output_values_for_existing_properties,
  966. )?;
  967. //
  968. // == MUTATION SAFE ==
  969. //
  970. // Used to compute old unique hashes, that should be substituted with new ones.
  971. let old_unique_hashes =
  972. Self::compute_old_unique_hashes(&new_output_property_values, &entity_property_values);
  973. // Add property value hashes, that should be unique on Class level
  974. Self::add_unique_property_value_hashes(class_id, new_unique_hashes);
  975. // Remove unique hashes, that were substituted with new ones. (if some).
  976. Self::remove_unique_property_value_hashes(class_id, old_unique_hashes);
  977. // Make updated entity_property_values from current entity_property_values and new_output_property_values provided
  978. let entity_property_values_updated =
  979. Self::make_updated_property_values(&entity_property_values, &new_output_property_values);
  980. // If property values should be updated
  981. if let Some(entity_property_values_updated) = entity_property_values_updated {
  982. // Calculate entities reference counter side effects for current operation (should always be safe)
  983. let entities_inbound_rcs_delta =
  984. Self::get_updated_inbound_rcs_delta(entity_id, class_properties, entity_property_values, new_output_property_values)?;
  985. // Update InboundReferenceCounter, based on previously calculated entities_inbound_rcs_delta, for each Entity involved
  986. Self::update_entities_rcs(&entities_inbound_rcs_delta);
  987. // Update entity property values
  988. <EntityById<T>>::mutate(entity_id, |entity| {
  989. entity.set_values(entity_property_values_updated);
  990. });
  991. // Trigger event
  992. Self::deposit_event(RawEvent::EntityPropertyValuesUpdated(actor, entity_id, entities_inbound_rcs_delta));
  993. }
  994. Ok(())
  995. }
  996. /// Clear `PropertyValueVec` under given `entity_id` & `in_class_schema_property_id`
  997. #[weight = 10_000_000] // TODO: adjust weight
  998. pub fn clear_entity_property_vector(
  999. origin,
  1000. actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
  1001. entity_id: T::EntityId,
  1002. in_class_schema_property_id: PropertyId
  1003. ) -> DispatchResult {
  1004. let account_id = ensure_signed(origin)?;
  1005. // Retrieve Class, Entity and EntityAccessLevel for the actor, attemting to perform operation
  1006. let (class, entity, access_level) = Self::ensure_class_entity_and_access_level(account_id, entity_id, &actor)?;
  1007. // Ensure Property under given PropertyId is unlocked from actor with given EntityAccessLevel
  1008. // Retrieve corresponding Property by value
  1009. let property = class.ensure_class_property_type_unlocked_from::<T>(
  1010. in_class_schema_property_id,
  1011. access_level,
  1012. )?;
  1013. // Ensure InputPropertyValue under given in_class_schema_property_id is Vector
  1014. let property_value_vector =
  1015. entity.ensure_property_value_is_vec::<T>(in_class_schema_property_id)?;
  1016. // Calculate side effects for clear_property_vector operation, based on property_value_vector provided and its respective property.
  1017. let entities_inbound_rcs_delta = Self::make_side_effects_for_clear_property_vector_operation(&property_value_vector, &property);
  1018. // Clear property_value_vector.
  1019. let empty_property_value_vector = Self::clear_property_vector(property_value_vector.clone());
  1020. let class_id = entity.get_class_id();
  1021. // Compute old and new vec unique property value hash.
  1022. // Ensure new property value hash with `unique` flag set is `unique` on `Class` level
  1023. let vec_property_value_hashes = if property.unique {
  1024. Some(
  1025. Self::ensure_vec_property_value_hashes(class_id, in_class_schema_property_id, &empty_property_value_vector, property_value_vector)?
  1026. )
  1027. } else {
  1028. None
  1029. };
  1030. //
  1031. // == MUTATION SAFE ==
  1032. //
  1033. if let Some((new_property_value_hash, old_property_value_hash)) = vec_property_value_hashes {
  1034. // Add property value hash, that should be unique on `Class` level
  1035. Self::add_unique_property_value_hash(class_id, in_class_schema_property_id, new_property_value_hash);
  1036. // Remove property value hash, that should be unique on `Class` level
  1037. Self::remove_unique_property_value_hash(class_id, in_class_schema_property_id, old_property_value_hash);
  1038. }
  1039. // Decrease reference counters of involved entities (if some)
  1040. Self::update_entities_rcs(&entities_inbound_rcs_delta);
  1041. // Insert empty_property_value_vector into entity_property_values mapping at in_class_schema_property_id.
  1042. // Retrieve updated entity_property_values
  1043. let entity_values_updated = Self::insert_at_in_class_schema_property_id(
  1044. entity.get_values(), in_class_schema_property_id, empty_property_value_vector
  1045. );
  1046. // Update entity property values
  1047. <EntityById<T>>::mutate(entity_id, |entity| {
  1048. entity.set_values(entity_values_updated);
  1049. });
  1050. // Trigger event
  1051. Self::deposit_event(
  1052. RawEvent::VectorCleared(
  1053. actor, entity_id, in_class_schema_property_id, entities_inbound_rcs_delta
  1054. )
  1055. );
  1056. Ok(())
  1057. }
  1058. /// Remove value at given `index_in_property_vector`
  1059. /// from `PropertyValueVec` under `in_class_schema_property_id`
  1060. #[weight = 10_000_000] // TODO: adjust weight
  1061. pub fn remove_at_entity_property_vector(
  1062. origin,
  1063. actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
  1064. entity_id: T::EntityId,
  1065. in_class_schema_property_id: PropertyId,
  1066. index_in_property_vector: VecMaxLength,
  1067. nonce: T::Nonce
  1068. ) -> DispatchResult {
  1069. let account_id = ensure_signed(origin)?;
  1070. // Retrieve Class, Entity and EntityAccessLevel for the actor, attemting to perform operation
  1071. let (class, entity, access_level) = Self::ensure_class_entity_and_access_level(account_id, entity_id, &actor)?;
  1072. // Ensure Property under given PropertyId is unlocked from actor with given EntityAccessLevel
  1073. // Retrieve corresponding Property by value
  1074. let property = class.ensure_class_property_type_unlocked_from::<T>(
  1075. in_class_schema_property_id,
  1076. access_level,
  1077. )?;
  1078. // Ensure InputPropertyValue under given in_class_schema_property_id is Vector
  1079. let property_value_vector =
  1080. entity.ensure_property_value_is_vec::<T>(in_class_schema_property_id)?;
  1081. // Ensure `VecInputPropertyValue` nonce is equal to the provided one.
  1082. // Used to to avoid possible data races, when performing vector specific operations
  1083. property_value_vector.ensure_nonce_equality::<T>(nonce)?;
  1084. // Ensure, provided index_in_property_vec is valid index of VecInputValue
  1085. property_value_vector
  1086. .ensure_index_in_property_vector_is_valid::<T>(index_in_property_vector)?;
  1087. let involved_entity_id = property_value_vector
  1088. .get_vec_value_ref()
  1089. .get_involved_entities()
  1090. .and_then(|involved_entities| involved_entities.get(index_in_property_vector as usize).copied());
  1091. // Remove value at in_class_schema_property_id in property value vector
  1092. // Get VecInputPropertyValue wrapped in InputPropertyValue
  1093. let property_value_vector_updated = Self::remove_at_index_in_property_vector(
  1094. property_value_vector.clone(), index_in_property_vector
  1095. );
  1096. let class_id = entity.get_class_id();
  1097. // Compute old and new vec unique property value hash.
  1098. // Ensure new property value hash with `unique` flag set is `unique` on `Class` level
  1099. let vec_property_value_hashes = if property.unique {
  1100. Some(
  1101. Self::ensure_vec_property_value_hashes(class_id, in_class_schema_property_id, &property_value_vector_updated, property_value_vector)?
  1102. )
  1103. } else {
  1104. None
  1105. };
  1106. //
  1107. // == MUTATION SAFE ==
  1108. //
  1109. if let Some((new_property_value_hash, old_property_value_hash)) = vec_property_value_hashes {
  1110. // Add property value hash, that should be unique on `Class` level
  1111. Self::add_unique_property_value_hash(class_id, in_class_schema_property_id, new_property_value_hash);
  1112. // Remove property value hash, that should be unique on `Class` level
  1113. Self::remove_unique_property_value_hash(class_id, in_class_schema_property_id, old_property_value_hash);
  1114. }
  1115. // Insert updated propery value into entity_property_values mapping at in_class_schema_property_id.
  1116. let entity_values_updated = Self::insert_at_in_class_schema_property_id(
  1117. entity.get_values(), in_class_schema_property_id, property_value_vector_updated
  1118. );
  1119. let involved_entity_and_side_effect = if let Some(involved_entity_id) = involved_entity_id {
  1120. // Decrease reference counter of involved entity (if some)
  1121. let same_controller_status = property.property_type.same_controller_status();
  1122. let rc_delta = EntityReferenceCounterSideEffect::atomic(same_controller_status, DeltaMode::Decrement);
  1123. // Update InboundReferenceCounter of involved entity, based on previously calculated rc_delta
  1124. Self::update_entity_rc(involved_entity_id, rc_delta);
  1125. Some((involved_entity_id, rc_delta))
  1126. } else {
  1127. None
  1128. };
  1129. // Update entity property values
  1130. <EntityById<T>>::mutate(entity_id, |entity| {
  1131. entity.set_values(entity_values_updated);
  1132. });
  1133. // Trigger event
  1134. Self::deposit_event(
  1135. RawEvent::RemovedAtVectorIndex(
  1136. actor, entity_id, in_class_schema_property_id, index_in_property_vector,
  1137. nonce + T::Nonce::one(), involved_entity_and_side_effect
  1138. )
  1139. );
  1140. Ok(())
  1141. }
  1142. /// Insert `SingleInputPropertyValue` at given `index_in_property_vector`
  1143. /// into `PropertyValueVec` under `in_class_schema_property_id`
  1144. #[weight = 10_000_000] // TODO: adjust weight
  1145. pub fn insert_at_entity_property_vector(
  1146. origin,
  1147. actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
  1148. entity_id: T::EntityId,
  1149. in_class_schema_property_id: PropertyId,
  1150. index_in_property_vector: VecMaxLength,
  1151. value: InputValue<T>,
  1152. nonce: T::Nonce
  1153. ) -> DispatchResult {
  1154. let account_id = ensure_signed(origin)?;
  1155. // Retrieve Class, Entity and EntityAccessLevel for the actor, attemting to perform operation
  1156. let (class, entity, access_level) = Self::ensure_class_entity_and_access_level(account_id, entity_id, &actor)?;
  1157. // Ensure Property under given PropertyId is unlocked from actor with given EntityAccessLevel
  1158. // Retrieve corresponding Property by value
  1159. let property = class.ensure_class_property_type_unlocked_from::<T>(
  1160. in_class_schema_property_id,
  1161. access_level,
  1162. )?;
  1163. // Ensure InputPropertyValue under given in_class_schema_property_id is Vector
  1164. let property_value_vector =
  1165. entity.ensure_property_value_is_vec::<T>(in_class_schema_property_id)?;
  1166. // Ensure `VecInputPropertyValue` nonce is equal to the provided one.
  1167. // Used to to avoid possible data races, when performing vector specific operations
  1168. property_value_vector.ensure_nonce_equality::<T>(nonce)?;
  1169. let entity_controller = entity.get_permissions_ref().get_controller();
  1170. // Ensure property_value type is equal to the property_value_vector type and check all constraints
  1171. Property::<T::ClassId>::ensure_property_value_can_be_inserted_at_property_vector(
  1172. &property,
  1173. &value,
  1174. &property_value_vector,
  1175. index_in_property_vector,
  1176. entity_controller,
  1177. )?;
  1178. let involved_entity = value.get_involved_entity();
  1179. // Insert SingleInputPropertyValue at in_class_schema_property_id into property value vector
  1180. // Get VecInputPropertyValue wrapped in InputPropertyValue
  1181. let property_value_vector_updated = Self::insert_at_index_in_property_vector(
  1182. property_value_vector.clone(), index_in_property_vector, value
  1183. );
  1184. let class_id = entity.get_class_id();
  1185. // Compute old and new vec unique property value hash.
  1186. // Ensure new property value hash with `unique` flag set is `unique` on `Class` level
  1187. let vec_property_value_hashes = if property.unique {
  1188. Some(
  1189. Self::ensure_vec_property_value_hashes(class_id, in_class_schema_property_id, &property_value_vector_updated, property_value_vector)?
  1190. )
  1191. } else {
  1192. None
  1193. };
  1194. //
  1195. // == MUTATION SAFE ==
  1196. //
  1197. if let Some((new_property_value_hash, old_property_value_hash)) = vec_property_value_hashes {
  1198. // Add property value hash, that should be unique on `Class` level
  1199. Self::add_unique_property_value_hash(class_id, in_class_schema_property_id, new_property_value_hash);
  1200. // Remove property value hash, that should be unique on `Class` level
  1201. Self::remove_unique_property_value_hash(class_id, in_class_schema_property_id, old_property_value_hash);
  1202. }
  1203. // Insert updated property value into entity_property_values mapping at in_class_schema_property_id.
  1204. // Retrieve updated entity_property_values
  1205. let entity_values_updated = Self::insert_at_in_class_schema_property_id(
  1206. entity.get_values(), in_class_schema_property_id, property_value_vector_updated
  1207. );
  1208. // Increase reference counter of involved entity (if some)
  1209. let involved_entity_and_side_effect = if let Some(entity_rc_to_increment) = involved_entity {
  1210. let same_controller_status = property.property_type.same_controller_status();
  1211. let rc_delta = EntityReferenceCounterSideEffect::atomic(same_controller_status, DeltaMode::Increment);
  1212. // Update InboundReferenceCounter of involved entity, based on previously calculated ReferenceCounterSideEffect
  1213. Self::update_entity_rc(entity_rc_to_increment, rc_delta);
  1214. Some((entity_rc_to_increment, rc_delta))
  1215. } else {
  1216. None
  1217. };
  1218. // Update entity property values
  1219. <EntityById<T>>::mutate(entity_id, |entity| {
  1220. entity.set_values(entity_values_updated);
  1221. });
  1222. // Trigger event
  1223. Self::deposit_event(
  1224. RawEvent::InsertedAtVectorIndex(
  1225. actor, entity_id, in_class_schema_property_id, index_in_property_vector,
  1226. nonce + T::Nonce::one(), involved_entity_and_side_effect
  1227. )
  1228. );
  1229. Ok(())
  1230. }
  1231. /// Batch transaction
  1232. #[weight = 10_000_000] // TODO: adjust weight
  1233. pub fn transaction(origin, actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>, operations: Vec<OperationType<T>>) -> DispatchResult {
  1234. // Ensure maximum number of operations during atomic batching limit not reached
  1235. Self::ensure_number_of_operations_during_atomic_batching_limit_not_reached(&operations)?;
  1236. //
  1237. // == MUTATION SAFE ==
  1238. //
  1239. // This BTreeMap holds the T::EntityId of the entity created as a result of executing a `CreateEntity` `Operation`
  1240. let mut entity_created_in_operation = BTreeMap::new();
  1241. // Create raw origin
  1242. let raw_origin = origin.into().map_err(|_| Error::<T>::OriginCanNotBeMadeIntoRawOrigin)?;
  1243. for (index, operation_type) in operations.into_iter().enumerate() {
  1244. let origin = T::Origin::from(raw_origin.clone());
  1245. let actor = actor.clone();
  1246. match operation_type {
  1247. OperationType::CreateEntity(create_entity_operation) => {
  1248. Self::create_entity(origin, create_entity_operation.class_id, actor)?;
  1249. // entity id of newly created entity
  1250. let entity_id = Self::next_entity_id() - T::EntityId::one();
  1251. entity_created_in_operation.insert(index, entity_id);
  1252. },
  1253. OperationType::AddSchemaSupportToEntity(add_schema_support_to_entity_operation) => {
  1254. let entity_id = operations::parametrized_entity_to_entity_id(
  1255. &entity_created_in_operation, add_schema_support_to_entity_operation.entity_id
  1256. )?;
  1257. let schema_id = add_schema_support_to_entity_operation.schema_id;
  1258. let property_values = operations::parametrized_property_values_to_property_values(
  1259. &entity_created_in_operation, add_schema_support_to_entity_operation.parametrized_property_values
  1260. )?;
  1261. Self::add_schema_support_to_entity(origin, actor, entity_id, schema_id, property_values)?;
  1262. },
  1263. OperationType::UpdatePropertyValues(update_property_values_operation) => {
  1264. let entity_id = operations::parametrized_entity_to_entity_id(
  1265. &entity_created_in_operation, update_property_values_operation.entity_id
  1266. )?;
  1267. let property_values = operations::parametrized_property_values_to_property_values(
  1268. &entity_created_in_operation, update_property_values_operation.new_parametrized_property_values
  1269. )?;
  1270. Self::update_entity_property_values(origin, actor, entity_id, property_values)?;
  1271. },
  1272. }
  1273. }
  1274. // Trigger event
  1275. Self::deposit_event(RawEvent::TransactionCompleted(actor));
  1276. Ok(())
  1277. }
  1278. }
  1279. }
  1280. impl<T: Trait> Module<T> {
  1281. /// Updates corresponding `Entity` `reference_counter` by `reference_counter_delta`.
  1282. fn update_entity_rc(
  1283. entity_id: T::EntityId,
  1284. reference_counter_delta: EntityReferenceCounterSideEffect,
  1285. ) {
  1286. // Update both `total` and `same owner` number of inbound references for the Entity instance under given `entity_id`
  1287. <EntityById<T>>::mutate(entity_id, |entity| {
  1288. let entity_inbound_rc = entity.get_reference_counter_mut();
  1289. entity_inbound_rc.total =
  1290. (entity_inbound_rc.total as i32 + reference_counter_delta.total) as u32;
  1291. entity_inbound_rc.same_owner =
  1292. (entity_inbound_rc.same_owner as i32 + reference_counter_delta.same_owner) as u32;
  1293. })
  1294. }
  1295. /// Add property value hash, that should be unique on `Class` level
  1296. pub fn add_unique_property_value_hash(
  1297. class_id: T::ClassId,
  1298. property_id: PropertyId,
  1299. hash: T::Hash,
  1300. ) {
  1301. <UniquePropertyValueHashes<T>>::insert((class_id, property_id), hash, ());
  1302. }
  1303. /// Remove property value hash, that should be unique on `Class` level
  1304. pub fn remove_unique_property_value_hash(
  1305. class_id: T::ClassId,
  1306. property_id: PropertyId,
  1307. hash: T::Hash,
  1308. ) {
  1309. <UniquePropertyValueHashes<T>>::remove((class_id, property_id), hash);
  1310. }
  1311. /// Add property value hashes, that should be unique on `Class` level
  1312. pub fn add_unique_property_value_hashes(
  1313. class_id: T::ClassId,
  1314. unique_property_value_hashes: BTreeMap<PropertyId, T::Hash>,
  1315. ) {
  1316. unique_property_value_hashes
  1317. .into_iter()
  1318. .for_each(|(property_id, hash)| {
  1319. Self::add_unique_property_value_hash(class_id, property_id, hash);
  1320. });
  1321. }
  1322. /// Remove property value hashes, that should be unique on `Class` level
  1323. pub fn remove_unique_property_value_hashes(
  1324. class_id: T::ClassId,
  1325. unique_property_value_hashes: BTreeMap<PropertyId, T::Hash>,
  1326. ) {
  1327. unique_property_value_hashes
  1328. .into_iter()
  1329. .for_each(|(property_id, hash)| {
  1330. Self::remove_unique_property_value_hash(class_id, property_id, hash);
  1331. });
  1332. }
  1333. /// Convert all provided `InputPropertyValue`'s into `StoredPropertyValue`'s
  1334. pub fn make_output_property_values(
  1335. input_property_values: BTreeMap<PropertyId, InputPropertyValue<T>>,
  1336. ) -> BTreeMap<PropertyId, StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>> {
  1337. input_property_values
  1338. .into_iter()
  1339. .map(|(property_id, property_value)| (property_id, property_value.into()))
  1340. .collect()
  1341. }
  1342. /// Update `entity_property_values` with `property_values`
  1343. /// Returns updated `entity_property_values`
  1344. fn make_updated_entity_property_values(
  1345. schema: Schema,
  1346. entity_property_values: BTreeMap<
  1347. PropertyId,
  1348. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1349. >,
  1350. output_property_values: &BTreeMap<
  1351. PropertyId,
  1352. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1353. >,
  1354. ) -> BTreeMap<PropertyId, StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>> {
  1355. // Concatenate existing `entity_property_values` with `property_values`, provided, when adding `Schema` support.
  1356. let updated_entity_property_values: BTreeMap<
  1357. PropertyId,
  1358. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1359. > = entity_property_values
  1360. .into_iter()
  1361. .chain(output_property_values.to_owned().into_iter())
  1362. .collect();
  1363. // Write all missing non required `Schema` `property_values` as `InputPropertyValue::default()`
  1364. let non_required_property_values: BTreeMap<
  1365. PropertyId,
  1366. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1367. > = schema
  1368. .get_properties()
  1369. .iter()
  1370. .filter_map(|property_id| {
  1371. if !updated_entity_property_values.contains_key(property_id) {
  1372. Some((*property_id, StoredPropertyValue::default()))
  1373. } else {
  1374. None
  1375. }
  1376. })
  1377. .collect();
  1378. // Extend updated_entity_property_values with given Schema non_required_property_values
  1379. updated_entity_property_values
  1380. .into_iter()
  1381. .chain(non_required_property_values.into_iter())
  1382. .collect()
  1383. }
  1384. /// Calculate side effects for clear_property_vector operation, based on `property_value_vector` provided and its respective `property`.
  1385. /// Returns calculated `ReferenceCounterSideEffects`
  1386. pub fn make_side_effects_for_clear_property_vector_operation(
  1387. property_value_vector: &VecStoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1388. property: &Property<T::ClassId>,
  1389. ) -> Option<ReferenceCounterSideEffects<T>> {
  1390. let entity_ids_to_decrease_rc = property_value_vector
  1391. .get_vec_value_ref()
  1392. .get_involved_entities();
  1393. if let Some(entity_ids_to_decrease_rcs) = entity_ids_to_decrease_rc {
  1394. // Calculate `ReferenceCounterSideEffects`, based on entity_ids involved, same_controller_status and chosen `DeltaMode`
  1395. let same_controller_status = property.property_type.same_controller_status();
  1396. let entities_inbound_rcs_delta = Self::perform_entities_inbound_rcs_delta_calculation(
  1397. ReferenceCounterSideEffects::<T>::default(),
  1398. entity_ids_to_decrease_rcs,
  1399. same_controller_status,
  1400. DeltaMode::Decrement,
  1401. );
  1402. if !entities_inbound_rcs_delta.is_empty() {
  1403. Some(entities_inbound_rcs_delta)
  1404. } else {
  1405. None
  1406. }
  1407. } else {
  1408. None
  1409. }
  1410. }
  1411. /// Update `inbound_rcs_delta`, based on `involved_entity_ids`, `same_controller_status` provided and chosen `DeltaMode`
  1412. /// Returns updated `inbound_rcs_delta`
  1413. fn perform_entities_inbound_rcs_delta_calculation(
  1414. mut inbound_rcs_delta: ReferenceCounterSideEffects<T>,
  1415. involved_entity_ids: Vec<T::EntityId>,
  1416. same_controller_status: bool,
  1417. delta_mode: DeltaMode,
  1418. ) -> ReferenceCounterSideEffects<T> {
  1419. for involved_entity_id in involved_entity_ids {
  1420. // If inbound_rcs_delta already contains entry for the given involved_entity_id, increment it
  1421. // with atomic EntityReferenceCounterSideEffect instance, based on same_owner flag provided and DeltaMode,
  1422. // otherwise create new atomic EntityReferenceCounterSideEffect instance
  1423. if let Some(inbound_rc_delta) = inbound_rcs_delta.get_mut(&involved_entity_id) {
  1424. *inbound_rc_delta +=
  1425. EntityReferenceCounterSideEffect::atomic(same_controller_status, delta_mode);
  1426. } else {
  1427. inbound_rcs_delta.insert(
  1428. involved_entity_id,
  1429. EntityReferenceCounterSideEffect::atomic(same_controller_status, delta_mode),
  1430. );
  1431. }
  1432. }
  1433. inbound_rcs_delta
  1434. }
  1435. /// Filter references, pointing to the same `Entity`
  1436. fn filter_references_to_the_same_entity(
  1437. current_entity_id: T::EntityId,
  1438. involved_entity_ids: Vec<T::EntityId>,
  1439. ) -> Vec<T::EntityId> {
  1440. involved_entity_ids
  1441. .into_iter()
  1442. .filter(|involved_entity_id| current_entity_id != *involved_entity_id)
  1443. .collect()
  1444. }
  1445. /// Calculate `ReferenceCounterSideEffects`, based on `values_for_existing_properties` provided and chosen `DeltaMode`
  1446. /// Returns calculated `ReferenceCounterSideEffects`
  1447. fn calculate_entities_inbound_rcs_delta(
  1448. current_entity_id: T::EntityId,
  1449. values_for_existing_properties: StoredValuesForExistingProperties<T>,
  1450. delta_mode: DeltaMode,
  1451. ) -> Option<ReferenceCounterSideEffects<T>> {
  1452. let entities_inbound_rcs_delta = values_for_existing_properties
  1453. .values()
  1454. .map(|value_for_existing_property| value_for_existing_property.unzip())
  1455. .filter_map(|(property, value)| {
  1456. let involved_entity_ids =
  1457. value.get_involved_entities().map(|involved_entity_ids| {
  1458. Self::filter_references_to_the_same_entity(
  1459. current_entity_id,
  1460. involved_entity_ids,
  1461. )
  1462. });
  1463. match involved_entity_ids {
  1464. Some(involved_entity_ids) if !involved_entity_ids.is_empty() => Some((
  1465. involved_entity_ids,
  1466. property.property_type.same_controller_status(),
  1467. )),
  1468. _ => None,
  1469. }
  1470. })
  1471. // Aggeregate all sideffects on a single entity together into one side effect map
  1472. .fold(
  1473. ReferenceCounterSideEffects::default(),
  1474. |inbound_rcs_delta, (involved_entity_ids, same_controller_status)| {
  1475. Self::perform_entities_inbound_rcs_delta_calculation(
  1476. inbound_rcs_delta,
  1477. involved_entity_ids,
  1478. same_controller_status,
  1479. delta_mode,
  1480. )
  1481. },
  1482. );
  1483. if !entities_inbound_rcs_delta.is_empty() {
  1484. Some(entities_inbound_rcs_delta)
  1485. } else {
  1486. None
  1487. }
  1488. }
  1489. /// Compute `ReferenceCounterSideEffects`, based on `InputPropertyValue` `Reference`'s involved into update process.
  1490. /// Returns updated `ReferenceCounterSideEffects`
  1491. pub fn get_updated_inbound_rcs_delta(
  1492. current_entity_id: T::EntityId,
  1493. class_properties: Vec<Property<T::ClassId>>,
  1494. entity_property_values: BTreeMap<
  1495. PropertyId,
  1496. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1497. >,
  1498. new_output_property_values: BTreeMap<
  1499. PropertyId,
  1500. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1501. >,
  1502. ) -> Result<Option<ReferenceCounterSideEffects<T>>, Error<T>> {
  1503. // Filter entity_property_values to get only those, which will be substituted with new_property_values
  1504. let entity_property_values_to_update: BTreeMap<
  1505. PropertyId,
  1506. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1507. > = entity_property_values
  1508. .into_iter()
  1509. .filter(|(entity_id, _)| new_output_property_values.contains_key(entity_id))
  1510. .collect();
  1511. // Calculate entities reference counter side effects for update operation
  1512. let stored_values_for_entity_property_values_to_update =
  1513. match StoredValuesForExistingProperties::from(
  1514. &class_properties,
  1515. &entity_property_values_to_update,
  1516. ) {
  1517. Ok(stored_values_for_entity_property_values_to_update) => {
  1518. stored_values_for_entity_property_values_to_update
  1519. }
  1520. Err(e) => {
  1521. debug_assert!(false, "Should not fail! {:?}", e);
  1522. return Err(e);
  1523. }
  1524. };
  1525. // Calculate entities inbound reference counter delta with Decrement DeltaMode for entity_property_values_to_update,
  1526. // as involved InputPropertyValue References will be substituted with new ones
  1527. let decremental_reference_counter_side_effects = Self::calculate_entities_inbound_rcs_delta(
  1528. current_entity_id,
  1529. stored_values_for_entity_property_values_to_update,
  1530. DeltaMode::Decrement,
  1531. );
  1532. // Calculate entities inbound reference counter delta with Increment DeltaMode for new_property_values,
  1533. // as involved InputPropertyValue References will substitute the old ones
  1534. let incremental_reference_counter_side_effects = Self::calculate_entities_inbound_rcs_delta(
  1535. current_entity_id,
  1536. StoredValuesForExistingProperties::from(
  1537. &class_properties,
  1538. &new_output_property_values,
  1539. )?,
  1540. DeltaMode::Increment,
  1541. );
  1542. // Add up both net decremental_reference_counter_side_effects and incremental_reference_counter_side_effects
  1543. // to get one net sideffect per entity.
  1544. Ok(Self::calculate_updated_inbound_rcs_delta(
  1545. decremental_reference_counter_side_effects,
  1546. incremental_reference_counter_side_effects,
  1547. ))
  1548. }
  1549. /// Add up both net first_reference_counter_side_effects and second_reference_counter_side_effects (if some)
  1550. /// to get one net sideffect per entity.
  1551. /// Returns updated `ReferenceCounterSideEffects`
  1552. pub fn calculate_updated_inbound_rcs_delta(
  1553. first_reference_counter_side_effects: Option<ReferenceCounterSideEffects<T>>,
  1554. second_reference_counter_side_effects: Option<ReferenceCounterSideEffects<T>>,
  1555. ) -> Option<ReferenceCounterSideEffects<T>> {
  1556. match (
  1557. first_reference_counter_side_effects,
  1558. second_reference_counter_side_effects,
  1559. ) {
  1560. (
  1561. Some(first_reference_counter_side_effects),
  1562. Some(second_reference_counter_side_effects),
  1563. ) => {
  1564. let reference_counter_side_effects = first_reference_counter_side_effects
  1565. .update(second_reference_counter_side_effects);
  1566. Some(reference_counter_side_effects)
  1567. }
  1568. (Some(first_reference_counter_side_effects), _) => {
  1569. Some(first_reference_counter_side_effects)
  1570. }
  1571. (_, Some(second_reference_counter_side_effects)) => {
  1572. Some(second_reference_counter_side_effects)
  1573. }
  1574. _ => None,
  1575. }
  1576. }
  1577. /// Used to update `class_permissions` with parameters provided.
  1578. /// Returns updated `class_permissions` if update performed
  1579. pub fn make_updated_class_permissions(
  1580. class_permissions: ClassPermissions<T::CuratorGroupId>,
  1581. updated_any_member: Option<bool>,
  1582. updated_entity_creation_blocked: Option<bool>,
  1583. updated_all_entity_property_values_locked: Option<bool>,
  1584. updated_maintainers: Option<BTreeSet<T::CuratorGroupId>>,
  1585. ) -> Option<ClassPermissions<T::CuratorGroupId>> {
  1586. // Used to check if update performed
  1587. let mut updated_class_permissions = class_permissions.clone();
  1588. if let Some(updated_any_member) = updated_any_member {
  1589. updated_class_permissions.set_any_member_status(updated_any_member);
  1590. }
  1591. if let Some(updated_entity_creation_blocked) = updated_entity_creation_blocked {
  1592. updated_class_permissions.set_entity_creation_blocked(updated_entity_creation_blocked);
  1593. }
  1594. if let Some(updated_all_entity_property_values_locked) =
  1595. updated_all_entity_property_values_locked
  1596. {
  1597. updated_class_permissions
  1598. .set_all_entity_property_values_locked(updated_all_entity_property_values_locked);
  1599. }
  1600. if let Some(updated_maintainers) = updated_maintainers {
  1601. updated_class_permissions.set_maintainers(updated_maintainers);
  1602. }
  1603. if updated_class_permissions != class_permissions {
  1604. Some(updated_class_permissions)
  1605. } else {
  1606. None
  1607. }
  1608. }
  1609. /// Used to update `entity_permissions` with parameters provided.
  1610. /// Returns updated `entity_permissions` if update performed
  1611. pub fn make_updated_entity_permissions(
  1612. entity_permissions: EntityPermissions<T::MemberId>,
  1613. updated_frozen: Option<bool>,
  1614. updated_referenceable: Option<bool>,
  1615. ) -> Option<EntityPermissions<T::MemberId>> {
  1616. // Used to check if update performed
  1617. let mut updated_entity_permissions = entity_permissions.clone();
  1618. if let Some(updated_frozen) = updated_frozen {
  1619. updated_entity_permissions.set_frozen(updated_frozen);
  1620. }
  1621. if let Some(updated_referenceable) = updated_referenceable {
  1622. updated_entity_permissions.set_referencable(updated_referenceable);
  1623. }
  1624. if updated_entity_permissions != entity_permissions {
  1625. Some(updated_entity_permissions)
  1626. } else {
  1627. None
  1628. }
  1629. }
  1630. /// Ensure property value hash with `unique` flag set is `unique` on `Class` level
  1631. pub fn ensure_property_value_hash_unique_option_satisfied(
  1632. class_id: T::ClassId,
  1633. property_id: PropertyId,
  1634. unique_property_value_hash: &T::Hash,
  1635. ) -> Result<(), Error<T>> {
  1636. ensure!(
  1637. !<UniquePropertyValueHashes<T>>::contains_key(
  1638. (class_id, property_id),
  1639. unique_property_value_hash
  1640. ),
  1641. Error::<T>::PropertyValueShouldBeUnique
  1642. );
  1643. Ok(())
  1644. }
  1645. /// Ensure all property value hashes with `unique` flag set are `unique` on `Class` level
  1646. pub fn ensure_property_value_hashes_unique_option_satisfied(
  1647. class_id: T::ClassId,
  1648. unique_property_value_hashes: &BTreeMap<PropertyId, T::Hash>,
  1649. ) -> Result<(), Error<T>> {
  1650. for (&property_id, unique_property_value_hash) in unique_property_value_hashes {
  1651. Self::ensure_property_value_hash_unique_option_satisfied(
  1652. class_id,
  1653. property_id,
  1654. unique_property_value_hash,
  1655. )?;
  1656. }
  1657. Ok(())
  1658. }
  1659. /// Compute old and new vec unique property value hash.
  1660. /// Ensure new property value hash with `unique` flag set is `unique` on `Class` level
  1661. pub fn ensure_vec_property_value_hashes(
  1662. class_id: T::ClassId,
  1663. in_class_schema_property_id: PropertyId,
  1664. property_value_vector_updated: &StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1665. property_value_vector: VecStoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1666. ) -> Result<(T::Hash, T::Hash), Error<T>> {
  1667. // Compute new hash from unique property value and its respective property id
  1668. let new_property_value_hash =
  1669. property_value_vector_updated.compute_unique_hash::<T>(in_class_schema_property_id);
  1670. // Ensure `Property` with `unique` flag set is `unique` on `Class` level
  1671. Self::ensure_property_value_hash_unique_option_satisfied(
  1672. class_id,
  1673. in_class_schema_property_id,
  1674. &new_property_value_hash,
  1675. )?;
  1676. // Compute old hash from the old unique property value and its respective property id
  1677. let old_property_value_hash =
  1678. property_value_vector.compute_unique_hash::<T>(in_class_schema_property_id);
  1679. Ok((new_property_value_hash, old_property_value_hash))
  1680. }
  1681. /// Compute new unique property value hashes.
  1682. /// Ensure new property value hashes with `unique` flag set are `unique` on `Class` level
  1683. pub fn ensure_new_property_values_respect_uniquness(
  1684. class_id: T::ClassId,
  1685. new_output_values_for_existing_properties: StoredValuesForExistingProperties<T>,
  1686. ) -> Result<BTreeMap<PropertyId, T::Hash>, Error<T>> {
  1687. let new_unique_property_value_hashes =
  1688. new_output_values_for_existing_properties.compute_unique_hashes();
  1689. // Ensure all provided Properties with unique flag set are unique on Class level
  1690. Self::ensure_property_value_hashes_unique_option_satisfied(
  1691. class_id,
  1692. &new_unique_property_value_hashes,
  1693. )?;
  1694. Ok(new_unique_property_value_hashes)
  1695. }
  1696. /// Returns the stored `Class` if exist, error otherwise.
  1697. fn ensure_class_exists(
  1698. class_id: T::ClassId,
  1699. ) -> Result<Class<T::EntityId, T::ClassId, T::CuratorGroupId>, Error<T>> {
  1700. ensure!(
  1701. <ClassById<T>>::contains_key(class_id),
  1702. Error::<T>::ClassNotFound
  1703. );
  1704. Ok(Self::class_by_id(class_id))
  1705. }
  1706. /// Returns `Class` and `Entity` under given id, if exists, and `EntityAccessLevel` corresponding to `origin`, if permitted
  1707. fn ensure_class_entity_and_access_level(
  1708. account_id: T::AccountId,
  1709. entity_id: T::EntityId,
  1710. actor: &Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
  1711. ) -> Result<
  1712. (
  1713. Class<T::EntityId, T::ClassId, T::CuratorGroupId>,
  1714. Entity<T::ClassId, T::MemberId, T::Hash, T::EntityId, T::Nonce>,
  1715. EntityAccessLevel,
  1716. ),
  1717. Error<T>,
  1718. > {
  1719. // Ensure Entity under given id exists, retrieve corresponding one
  1720. let entity = Self::ensure_known_entity_id(entity_id)?;
  1721. // Retrieve corresponding Class
  1722. let class = Self::class_by_id(entity.get_class_id());
  1723. // Derive EntityAccessLevel for the actor, attempting to act.
  1724. let access_level = EntityAccessLevel::derive(
  1725. &account_id,
  1726. entity.get_permissions_ref(),
  1727. class.get_permissions_ref(),
  1728. actor,
  1729. )?;
  1730. Ok((class, entity, access_level))
  1731. }
  1732. /// Ensure `Entity` under given `entity_id` exists, retrieve corresponding `Entity` & `Class`
  1733. pub fn ensure_known_entity_and_class(
  1734. entity_id: T::EntityId,
  1735. ) -> Result<
  1736. (
  1737. Entity<T::ClassId, T::MemberId, T::Hash, T::EntityId, T::Nonce>,
  1738. Class<T::EntityId, T::ClassId, T::CuratorGroupId>,
  1739. ),
  1740. Error<T>,
  1741. > {
  1742. // Ensure Entity under given id exists, retrieve corresponding one
  1743. let entity = Self::ensure_known_entity_id(entity_id)?;
  1744. let class = ClassById::<T>::get(entity.get_class_id());
  1745. Ok((entity, class))
  1746. }
  1747. /// Filter `provided values_for_existing_properties`, leaving only `Reference`'s with `SameOwner` flag set
  1748. /// Returns the set of corresponding property ids
  1749. pub fn get_property_id_references_with_same_owner_flag_set(
  1750. values_for_existing_properties: StoredValuesForExistingProperties<T>,
  1751. ) -> BTreeSet<PropertyId> {
  1752. values_for_existing_properties
  1753. // Iterate over the PropertyId's
  1754. .keys()
  1755. // Filter provided values_for_existing_properties, leaving only `Reference`'s with `SameOwner` flag set
  1756. .filter(|property_id| {
  1757. if let Some(value_for_existing_property) =
  1758. values_for_existing_properties.get(property_id)
  1759. {
  1760. value_for_existing_property
  1761. .get_property()
  1762. .property_type
  1763. .same_controller_status()
  1764. } else {
  1765. false
  1766. }
  1767. })
  1768. .copied()
  1769. .collect()
  1770. }
  1771. /// Ensure all ids of provided `new_property_value_references_with_same_owner_flag_set`
  1772. /// corresponding to property ids of respective Class Property references with same owner flag set
  1773. pub fn ensure_only_reference_ids_with_same_owner_flag_set_provided(
  1774. entity_property_id_references_with_same_owner_flag_set: &BTreeSet<PropertyId>,
  1775. new_property_value_references_with_same_owner_flag_set: &BTreeMap<
  1776. PropertyId,
  1777. InputPropertyValue<T>,
  1778. >,
  1779. ) -> Result<(), Error<T>> {
  1780. let new_property_value_id_references_with_same_owner_flag_set: BTreeSet<PropertyId> =
  1781. new_property_value_references_with_same_owner_flag_set
  1782. .keys()
  1783. .copied()
  1784. .collect();
  1785. ensure!(
  1786. new_property_value_id_references_with_same_owner_flag_set
  1787. .is_subset(entity_property_id_references_with_same_owner_flag_set),
  1788. Error::<T>::AllProvidedPropertyValueIdsMustBeReferencesWithSameOwnerFlagSet
  1789. );
  1790. Ok(())
  1791. }
  1792. /// Ensure provided actor can create entities of current `Class`
  1793. pub fn ensure_can_create_entities(
  1794. class_permissions: &ClassPermissions<T::CuratorGroupId>,
  1795. account_id: &T::AccountId,
  1796. actor: &Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
  1797. ) -> Result<(), Error<T>> {
  1798. let can_create = match &actor {
  1799. Actor::Lead => {
  1800. // Ensure lead authorization performed succesfully
  1801. ensure_lead_auth_success::<T>(account_id)?;
  1802. true
  1803. }
  1804. Actor::Member(member_id) if class_permissions.any_member_status() => {
  1805. // Ensure member authorization performed succesfully
  1806. ensure_member_auth_success::<T>(member_id, account_id)?;
  1807. true
  1808. }
  1809. Actor::Curator(curator_group_id, curator_id)
  1810. if class_permissions.is_maintainer(curator_group_id) =>
  1811. {
  1812. // Authorize curator, performing all checks to ensure curator can act
  1813. CuratorGroup::<T>::perform_curator_in_group_auth(
  1814. curator_id,
  1815. curator_group_id,
  1816. account_id,
  1817. )?;
  1818. true
  1819. }
  1820. _ => false,
  1821. };
  1822. ensure!(can_create, Error::<T>::ActorCanNotCreateEntities);
  1823. Ok(())
  1824. }
  1825. /// Ensure all provided `new_property_value_references_with_same_owner_flag_set` are valid
  1826. fn ensure_are_valid_references_with_same_owner_flag_set(
  1827. new_property_value_references_with_same_owner_flag_set: InputValuesForExistingProperties<T>,
  1828. new_controller: &EntityController<T::MemberId>,
  1829. ) -> Result<(), Error<T>> {
  1830. for updated_value_for_existing_property in
  1831. new_property_value_references_with_same_owner_flag_set.values()
  1832. {
  1833. let (property, value) = updated_value_for_existing_property.unzip();
  1834. // Perform all required checks to ensure provided property values are valid references
  1835. Property::<T::ClassId>::ensure_property_value_is_valid_reference(
  1836. &property,
  1837. value,
  1838. new_controller,
  1839. )?;
  1840. }
  1841. Ok(())
  1842. }
  1843. /// Used to update entity_property_values with parameters provided.
  1844. /// Returns updated `entity_property_values`, if update performed
  1845. pub fn make_updated_property_value_references_with_same_owner_flag_set(
  1846. unused_property_id_references_with_same_owner_flag_set: BTreeSet<PropertyId>,
  1847. entity_property_values: &BTreeMap<
  1848. PropertyId,
  1849. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1850. >,
  1851. new_property_value_references_with_same_owner_flag_set: &BTreeMap<
  1852. PropertyId,
  1853. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1854. >,
  1855. ) -> Option<BTreeMap<PropertyId, StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>>> {
  1856. // Used to check if update performed
  1857. let mut entity_property_values_updated = entity_property_values.clone();
  1858. for (property_id, new_property_value_reference_with_same_owner_flag_set) in
  1859. new_property_value_references_with_same_owner_flag_set
  1860. {
  1861. // Update entity_property_values map at property_id with new_property_value_reference_with_same_owner_flag_set
  1862. entity_property_values_updated.insert(
  1863. *property_id,
  1864. new_property_value_reference_with_same_owner_flag_set.to_owned(),
  1865. );
  1866. }
  1867. // Throw away old non required property value references with same owner flag set
  1868. // and replace them with Default ones
  1869. for unused_property_id_reference_with_same_owner_flag_set in
  1870. unused_property_id_references_with_same_owner_flag_set
  1871. {
  1872. entity_property_values_updated.insert(
  1873. unused_property_id_reference_with_same_owner_flag_set,
  1874. StoredPropertyValue::default(),
  1875. );
  1876. }
  1877. if *entity_property_values != entity_property_values_updated {
  1878. Some(entity_property_values_updated)
  1879. } else {
  1880. None
  1881. }
  1882. }
  1883. /// Update InboundReferenceCounter, based on previously calculated entities_inbound_rcs_delta, for each Entity involved
  1884. pub fn update_entities_rcs(
  1885. entities_inbound_rcs_delta: &Option<ReferenceCounterSideEffects<T>>,
  1886. ) {
  1887. if let Some(entities_inbound_rcs_delta) = entities_inbound_rcs_delta {
  1888. entities_inbound_rcs_delta.update_entities_rcs();
  1889. }
  1890. }
  1891. /// Retrieve `property_ids`, that are not in `property_values`
  1892. pub fn compute_unused_property_ids(
  1893. property_values: &BTreeMap<PropertyId, InputPropertyValue<T>>,
  1894. property_ids: &BTreeSet<PropertyId>,
  1895. ) -> BTreeSet<PropertyId> {
  1896. let property_value_indices: BTreeSet<PropertyId> =
  1897. property_values.keys().cloned().collect();
  1898. property_ids
  1899. .difference(&property_value_indices)
  1900. .copied()
  1901. .collect()
  1902. }
  1903. /// Used to compute old unique hashes, that should be substituted with new ones.
  1904. pub fn compute_old_unique_hashes(
  1905. new_output_property_values: &BTreeMap<
  1906. PropertyId,
  1907. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1908. >,
  1909. entity_values: &BTreeMap<PropertyId, StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>>,
  1910. ) -> BTreeMap<PropertyId, T::Hash> {
  1911. entity_values
  1912. .iter()
  1913. .filter(|(property_id, _)| new_output_property_values.contains_key(property_id))
  1914. .map(|(&property_id, property_value)| {
  1915. (
  1916. property_id,
  1917. property_value.compute_unique_hash::<T>(property_id),
  1918. )
  1919. })
  1920. .collect()
  1921. }
  1922. /// Perform checks to ensure all required `property_values` under provided `unused_schema_property_ids` provided
  1923. pub fn ensure_all_required_properties_provided(
  1924. class_properties: &[Property<T::ClassId>],
  1925. unused_schema_property_ids: &BTreeSet<PropertyId>,
  1926. ) -> Result<(), Error<T>> {
  1927. for &unused_schema_property_id in unused_schema_property_ids {
  1928. let class_property = &class_properties
  1929. .get(unused_schema_property_id as usize)
  1930. .ok_or(Error::<T>::ClassPropertyNotFound)?;
  1931. // All required property values should be provided
  1932. ensure!(
  1933. !class_property.required,
  1934. Error::<T>::MissingRequiredProperty
  1935. );
  1936. }
  1937. Ok(())
  1938. }
  1939. /// Validate all values, provided in `values_for_existing_properties`, against the type of its `Property`
  1940. /// and check any additional constraints
  1941. pub fn ensure_property_values_are_valid(
  1942. entity_controller: &EntityController<T::MemberId>,
  1943. values_for_existing_properties: &InputValuesForExistingProperties<T>,
  1944. ) -> Result<(), Error<T>> {
  1945. for value_for_existing_property in values_for_existing_properties.values() {
  1946. let (property, value) = value_for_existing_property.unzip();
  1947. // Validate new InputPropertyValue against the type of this Property and check any additional constraints
  1948. Property::<T::ClassId>::ensure_property_value_to_update_is_valid(
  1949. property,
  1950. value,
  1951. entity_controller,
  1952. )?;
  1953. }
  1954. Ok(())
  1955. }
  1956. /// Ensure all provided `new_property_values` are already exist in `entity_property_values` map
  1957. pub fn ensure_all_property_values_are_already_added(
  1958. entity_property_values: &BTreeMap<
  1959. PropertyId,
  1960. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1961. >,
  1962. new_property_values: &BTreeMap<PropertyId, InputPropertyValue<T>>,
  1963. ) -> Result<(), Error<T>> {
  1964. ensure!(
  1965. new_property_values
  1966. .keys()
  1967. .all(|key| entity_property_values.contains_key(key)),
  1968. Error::<T>::UnknownEntityPropertyId
  1969. );
  1970. Ok(())
  1971. }
  1972. /// Ensure `new_values_for_existing_properties` are accessible for actor with given `access_level`
  1973. pub fn ensure_all_property_values_are_unlocked_from(
  1974. new_values_for_existing_properties: &InputValuesForExistingProperties<T>,
  1975. access_level: EntityAccessLevel,
  1976. ) -> Result<(), Error<T>> {
  1977. for value_for_new_property in new_values_for_existing_properties.values() {
  1978. // Ensure Property is unlocked from Actor with given EntityAccessLevel
  1979. value_for_new_property
  1980. .get_property()
  1981. .ensure_unlocked_from::<T>(access_level)?;
  1982. }
  1983. Ok(())
  1984. }
  1985. /// Filter `new_property_values` identical to `entity_property_values`.
  1986. /// Return only `new_property_values`, that are not in `entity_property_values`
  1987. pub fn try_filter_identical_property_values(
  1988. entity_property_values: &BTreeMap<
  1989. PropertyId,
  1990. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  1991. >,
  1992. new_property_values: BTreeMap<PropertyId, InputPropertyValue<T>>,
  1993. ) -> BTreeMap<PropertyId, InputPropertyValue<T>> {
  1994. new_property_values
  1995. .into_iter()
  1996. .filter(|(id, new_property_value)| {
  1997. if let Some(entity_property_value) = entity_property_values.get(id) {
  1998. StoredPropertyValue::<T::Hash, T::EntityId, T::Nonce>::from(
  1999. new_property_value.to_owned(),
  2000. ) != *entity_property_value
  2001. } else {
  2002. true
  2003. }
  2004. })
  2005. .collect()
  2006. }
  2007. /// Update existing `entity_property_values` with `new_property_values`.
  2008. /// if update performed, returns updated entity property values
  2009. pub fn make_updated_property_values(
  2010. entity_property_values: &BTreeMap<
  2011. PropertyId,
  2012. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  2013. >,
  2014. new_output_property_values: &BTreeMap<
  2015. PropertyId,
  2016. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  2017. >,
  2018. ) -> Option<BTreeMap<PropertyId, StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>>> {
  2019. // Used to check if updated performed
  2020. let mut entity_property_values_updated = entity_property_values.to_owned();
  2021. new_output_property_values
  2022. .iter()
  2023. .for_each(|(id, new_property_value)| {
  2024. if let Some(entity_property_value) = entity_property_values_updated.get_mut(&id) {
  2025. entity_property_value.update(new_property_value.to_owned());
  2026. }
  2027. });
  2028. if entity_property_values_updated != *entity_property_values {
  2029. Some(entity_property_values_updated)
  2030. } else {
  2031. None
  2032. }
  2033. }
  2034. /// Insert `InputValue` into `VecStoredPropertyValue` at `index_in_property_vector`.
  2035. /// Returns `VecStoredPropertyValue` wrapped in `StoredPropertyValue`
  2036. pub fn insert_at_index_in_property_vector(
  2037. mut property_value_vector: VecStoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  2038. index_in_property_vector: VecMaxLength,
  2039. value: InputValue<T>,
  2040. ) -> StoredPropertyValue<T::Hash, T::EntityId, T::Nonce> {
  2041. property_value_vector.insert_at(index_in_property_vector, value.into());
  2042. StoredPropertyValue::Vector(property_value_vector)
  2043. }
  2044. /// Remove `InputValue` at `index_in_property_vector` in `VecInputPropertyValue`.
  2045. /// Returns `VecInputPropertyValue` wrapped in `InputPropertyValue`
  2046. pub fn remove_at_index_in_property_vector(
  2047. mut property_value_vector: VecStoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  2048. index_in_property_vector: VecMaxLength,
  2049. ) -> StoredPropertyValue<T::Hash, T::EntityId, T::Nonce> {
  2050. property_value_vector.remove_at(index_in_property_vector);
  2051. StoredPropertyValue::Vector(property_value_vector)
  2052. }
  2053. /// Clear `VecStoredPropertyValue`.
  2054. /// Returns empty `VecStoredPropertyValue` wrapped in `StoredPropertyValue`
  2055. pub fn clear_property_vector(
  2056. mut property_value_vector: VecStoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  2057. ) -> StoredPropertyValue<T::Hash, T::EntityId, T::Nonce> {
  2058. property_value_vector.clear();
  2059. StoredPropertyValue::Vector(property_value_vector)
  2060. }
  2061. /// Insert `InputPropertyValue` into `entity_property_values` mapping at `in_class_schema_property_id`.
  2062. /// Returns updated `entity_property_values`
  2063. pub fn insert_at_in_class_schema_property_id(
  2064. mut entity_property_values: BTreeMap<
  2065. PropertyId,
  2066. StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  2067. >,
  2068. in_class_schema_property_id: PropertyId,
  2069. property_value: StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>,
  2070. ) -> BTreeMap<PropertyId, StoredPropertyValue<T::Hash, T::EntityId, T::Nonce>> {
  2071. entity_property_values.insert(in_class_schema_property_id, property_value);
  2072. entity_property_values
  2073. }
  2074. /// Ensure `Class` under given id exists, return corresponding one
  2075. pub fn ensure_known_class_id(
  2076. class_id: T::ClassId,
  2077. ) -> Result<Class<T::EntityId, T::ClassId, T::CuratorGroupId>, Error<T>> {
  2078. ensure!(
  2079. <ClassById<T>>::contains_key(class_id),
  2080. Error::<T>::ClassNotFound
  2081. );
  2082. Ok(Self::class_by_id(class_id))
  2083. }
  2084. /// Ensure `Entity` under given id exists, return corresponding one
  2085. pub fn ensure_known_entity_id(
  2086. entity_id: T::EntityId,
  2087. ) -> Result<Entity<T::ClassId, T::MemberId, T::Hash, T::EntityId, T::Nonce>, Error<T>> {
  2088. ensure!(
  2089. <EntityById<T>>::contains_key(entity_id),
  2090. Error::<T>::EntityNotFound
  2091. );
  2092. Ok(Self::entity_by_id(entity_id))
  2093. }
  2094. /// Ensure `CuratorGroup` under given id exists
  2095. pub fn ensure_curator_group_under_given_id_exists(
  2096. curator_group_id: &T::CuratorGroupId,
  2097. ) -> Result<(), Error<T>> {
  2098. ensure!(
  2099. <CuratorGroupById<T>>::contains_key(curator_group_id),
  2100. Error::<T>::CuratorGroupDoesNotExist
  2101. );
  2102. Ok(())
  2103. }
  2104. /// Ensure `CuratorGroup` under given id exists, return corresponding one
  2105. pub fn ensure_curator_group_exists(
  2106. curator_group_id: &T::CuratorGroupId,
  2107. ) -> Result<CuratorGroup<T>, Error<T>> {
  2108. Self::ensure_curator_group_under_given_id_exists(curator_group_id)?;
  2109. Ok(Self::curator_group_by_id(curator_group_id))
  2110. }
  2111. /// Ensure `MaxNumberOfMaintainersPerClass` constraint satisfied
  2112. pub fn ensure_maintainers_limit_not_reached(
  2113. curator_groups: &BTreeSet<T::CuratorGroupId>,
  2114. ) -> Result<(), Error<T>> {
  2115. ensure!(
  2116. curator_groups.len() < T::MaxNumberOfMaintainersPerClass::get() as usize,
  2117. Error::<T>::ClassMaintainersLimitReached
  2118. );
  2119. Ok(())
  2120. }
  2121. /// Ensure all `CuratorGroup`'s under given ids exist
  2122. pub fn ensure_curator_groups_exist(
  2123. curator_groups: &BTreeSet<T::CuratorGroupId>,
  2124. ) -> Result<(), Error<T>> {
  2125. for curator_group in curator_groups {
  2126. // Ensure CuratorGroup under given id exists
  2127. Self::ensure_curator_group_exists(curator_group)?;
  2128. }
  2129. Ok(())
  2130. }
  2131. /// Perform security checks to ensure provided `class_maintainers` are valid
  2132. pub fn ensure_class_maintainers_are_valid(
  2133. class_maintainers: &BTreeSet<T::CuratorGroupId>,
  2134. ) -> Result<(), Error<T>> {
  2135. // Ensure max number of maintainers per Class constraint satisfied
  2136. ensure!(
  2137. class_maintainers.len() <= T::MaxNumberOfMaintainersPerClass::get() as usize,
  2138. Error::<T>::ClassMaintainersLimitReached
  2139. );
  2140. // Ensure all curator groups provided are already exist in runtime
  2141. Self::ensure_curator_groups_exist(class_maintainers)?;
  2142. Ok(())
  2143. }
  2144. /// Ensure new `Schema` is not empty
  2145. pub fn ensure_non_empty_schema(
  2146. existing_properties: &BTreeSet<PropertyId>,
  2147. new_properties: &[Property<T::ClassId>],
  2148. ) -> Result<(), Error<T>> {
  2149. // Schema is empty if both existing_properties and new_properties are empty
  2150. let non_empty_schema = !existing_properties.is_empty() || !new_properties.is_empty();
  2151. ensure!(non_empty_schema, Error::<T>::NoPropertiesInClassSchema);
  2152. Ok(())
  2153. }
  2154. /// Ensure `ClassNameLengthConstraint` conditions satisfied
  2155. pub fn ensure_class_name_is_valid(text: &[u8]) -> Result<(), Error<T>> {
  2156. T::ClassNameLengthConstraint::get().ensure_valid(
  2157. text.len(),
  2158. Error::<T>::ClassNameTooShort,
  2159. Error::<T>::ClassNameTooLong,
  2160. )
  2161. }
  2162. /// Ensure `ClassDescriptionLengthConstraint` conditions satisfied
  2163. pub fn ensure_class_description_is_valid(text: &[u8]) -> Result<(), Error<T>> {
  2164. T::ClassDescriptionLengthConstraint::get().ensure_valid(
  2165. text.len(),
  2166. Error::<T>::ClassDescriptionTooShort,
  2167. Error::<T>::ClassDescriptionTooLong,
  2168. )
  2169. }
  2170. /// Ensure `MaxNumberOfClasses` constraint satisfied
  2171. pub fn ensure_class_limit_not_reached() -> Result<(), Error<T>> {
  2172. ensure!(
  2173. (<ClassById<T>>::iter().count() as MaxNumber) < T::MaxNumberOfClasses::get(),
  2174. Error::<T>::ClassLimitReached
  2175. );
  2176. Ok(())
  2177. }
  2178. /// Ensure `MaxNumberOfEntitiesPerClass` constraint satisfied
  2179. pub fn ensure_valid_number_of_entities_per_class(
  2180. maximum_entities_count: T::EntityId,
  2181. ) -> Result<(), Error<T>> {
  2182. ensure!(
  2183. maximum_entities_count <= T::MaxNumberOfEntitiesPerClass::get(),
  2184. Error::<T>::EntitiesNumberPerClassConstraintViolated
  2185. );
  2186. Ok(())
  2187. }
  2188. /// Ensure `IndividualEntitiesCreationLimit` constraint satisfied
  2189. pub fn ensure_valid_number_of_class_entities_per_actor_constraint(
  2190. number_of_class_entities_per_actor: T::EntityId,
  2191. ) -> Result<(), Error<T>> {
  2192. ensure!(
  2193. number_of_class_entities_per_actor <= T::IndividualEntitiesCreationLimit::get(),
  2194. Error::<T>::NumberOfClassEntitiesPerActorConstraintViolated
  2195. );
  2196. Ok(())
  2197. }
  2198. /// Ensure all entities creation limits, defined for a given `Class`, are valid
  2199. pub fn ensure_entities_creation_limits_are_valid(
  2200. maximum_entities_count: T::EntityId,
  2201. default_entity_creation_voucher_upper_bound: T::EntityId,
  2202. ) -> Result<(), Error<T>> {
  2203. // Ensure default_entity_creation_voucher_upper_bound does not exceed default_entity_creation_voucher_upper_bound
  2204. ensure!(
  2205. default_entity_creation_voucher_upper_bound <= maximum_entities_count,
  2206. Error::<T>::PerControllerEntitiesCreationLimitExceedsOverallLimit
  2207. );
  2208. // Ensure maximum_entities_count does not exceed MaxNumberOfEntitiesPerClass limit
  2209. Self::ensure_valid_number_of_entities_per_class(maximum_entities_count)?;
  2210. // Ensure default_entity_creation_voucher_upper_bound constraint does not exceed IndividualEntitiesCreationLimit
  2211. Self::ensure_valid_number_of_class_entities_per_actor_constraint(
  2212. default_entity_creation_voucher_upper_bound,
  2213. )
  2214. }
  2215. /// Ensure maximum number of operations during atomic batching constraint satisfied
  2216. pub fn ensure_number_of_operations_during_atomic_batching_limit_not_reached(
  2217. operations: &[OperationType<T>],
  2218. ) -> Result<(), Error<T>> {
  2219. ensure!(
  2220. operations.len() <= T::MaxNumberOfOperationsDuringAtomicBatching::get() as usize,
  2221. Error::<T>::NumberOfOperationsDuringAtomicBatchingLimitReached
  2222. );
  2223. Ok(())
  2224. }
  2225. /// Complete all checks to ensure each `Property` is valid
  2226. pub fn ensure_all_properties_are_valid(
  2227. new_properties: &[Property<T::ClassId>],
  2228. ) -> Result<(), Error<T>> {
  2229. for new_property in new_properties.iter() {
  2230. // Ensure PropertyNameLengthConstraint satisfied
  2231. new_property.ensure_name_is_valid()?;
  2232. // Ensure PropertyDescriptionLengthConstraint satisfied
  2233. new_property.ensure_description_is_valid()?;
  2234. // Ensure Type specific constraints satisfied
  2235. new_property.ensure_property_type_size_is_valid()?;
  2236. // Ensure refers to existing class_id, if If Property Type is Reference,
  2237. Self::ensure_property_type_reference_is_valid(new_property)?;
  2238. }
  2239. Ok(())
  2240. }
  2241. /// Ensure refers to existing `class_id`, if If `Property` `Type` is `Reference`,
  2242. pub fn ensure_property_type_reference_is_valid(
  2243. property: &Property<T::ClassId>,
  2244. ) -> Result<(), Error<T>> {
  2245. let has_unknown_reference =
  2246. if let Type::Reference(other_class_id, _) = property.property_type.get_inner_type() {
  2247. !<ClassById<T>>::contains_key(other_class_id)
  2248. } else {
  2249. false
  2250. };
  2251. ensure!(
  2252. !has_unknown_reference,
  2253. Error::<T>::ClassSchemaRefersUnknownClass
  2254. );
  2255. Ok(())
  2256. }
  2257. /// Ensure all `Property` names are unique within `Class`
  2258. pub fn ensure_all_property_names_are_unique(
  2259. class_properties: &[Property<T::ClassId>],
  2260. new_properties: &[Property<T::ClassId>],
  2261. ) -> Result<(), Error<T>> {
  2262. // Used to ensure all property names are unique within class
  2263. let mut unique_prop_names = BTreeSet::new();
  2264. for property in class_properties.iter() {
  2265. unique_prop_names.insert(property.name.to_owned());
  2266. }
  2267. for new_property in new_properties {
  2268. // Ensure name of a new property is unique within its class.
  2269. ensure!(
  2270. !unique_prop_names.contains(&new_property.name),
  2271. Error::<T>::PropertyNameNotUniqueInAClass
  2272. );
  2273. unique_prop_names.insert(new_property.name.to_owned());
  2274. }
  2275. Ok(())
  2276. }
  2277. /// Ensure provided indices of `existing_properties` are valid indices of `Class` properties
  2278. pub fn ensure_schema_properties_are_valid_indices(
  2279. existing_properties: &BTreeSet<PropertyId>,
  2280. class_properties: &[Property<T::ClassId>],
  2281. ) -> Result<(), Error<T>> {
  2282. let has_unknown_properties = existing_properties
  2283. .iter()
  2284. .any(|&prop_id| prop_id >= class_properties.len() as PropertyId);
  2285. ensure!(
  2286. !has_unknown_properties,
  2287. Error::<T>::ClassSchemaRefersUnknownPropertyIndex
  2288. );
  2289. Ok(())
  2290. }
  2291. /// Create new `Schema` from existing and new property ids
  2292. pub fn create_class_schema(
  2293. existing_properties: BTreeSet<PropertyId>,
  2294. class_properties: &[Property<T::ClassId>],
  2295. new_properties: &[Property<T::ClassId>],
  2296. ) -> Schema {
  2297. // Calcualate new property ids
  2298. let properties = new_properties
  2299. .iter()
  2300. .enumerate()
  2301. .map(|(i, _)| (class_properties.len() + i) as PropertyId)
  2302. // Concatenate them with existing ones
  2303. .chain(existing_properties.into_iter())
  2304. .collect();
  2305. Schema::new(properties)
  2306. }
  2307. /// Update existing `Class` properties with new ones provided, return updated ones
  2308. pub fn make_updated_class_properties(
  2309. class_properties: Vec<Property<T::ClassId>>,
  2310. new_properties: Vec<Property<T::ClassId>>,
  2311. ) -> Vec<Property<T::ClassId>> {
  2312. class_properties
  2313. .into_iter()
  2314. .chain(new_properties.into_iter())
  2315. .collect()
  2316. }
  2317. }
  2318. decl_event!(
  2319. pub enum Event<T>
  2320. where
  2321. CuratorGroupId = <T as ActorAuthenticator>::CuratorGroupId,
  2322. CuratorId = <T as ActorAuthenticator>::CuratorId,
  2323. ClassId = <T as Trait>::ClassId,
  2324. EntityId = <T as Trait>::EntityId,
  2325. EntityController = EntityController<<T as ActorAuthenticator>::MemberId>,
  2326. EntityCreationVoucher = EntityCreationVoucher<T>,
  2327. Status = bool,
  2328. Actor = Actor<
  2329. <T as ActorAuthenticator>::CuratorGroupId,
  2330. <T as ActorAuthenticator>::CuratorId,
  2331. <T as ActorAuthenticator>::MemberId,
  2332. >,
  2333. Nonce = <T as Trait>::Nonce,
  2334. SideEffects = Option<ReferenceCounterSideEffects<T>>,
  2335. SideEffect = Option<(<T as Trait>::EntityId, EntityReferenceCounterSideEffect)>,
  2336. {
  2337. CuratorGroupAdded(CuratorGroupId),
  2338. CuratorGroupRemoved(CuratorGroupId),
  2339. CuratorGroupStatusSet(CuratorGroupId, Status),
  2340. CuratorAdded(CuratorGroupId, CuratorId),
  2341. CuratorRemoved(CuratorGroupId, CuratorId),
  2342. MaintainerAdded(ClassId, CuratorGroupId),
  2343. MaintainerRemoved(ClassId, CuratorGroupId),
  2344. EntityCreationVoucherUpdated(EntityController, EntityCreationVoucher),
  2345. EntityCreationVoucherCreated(EntityController, EntityCreationVoucher),
  2346. ClassCreated(ClassId),
  2347. ClassPermissionsUpdated(ClassId),
  2348. ClassSchemaAdded(ClassId, SchemaId),
  2349. ClassSchemaStatusUpdated(ClassId, SchemaId, Status),
  2350. EntityPermissionsUpdated(EntityId),
  2351. EntityCreated(Actor, EntityId),
  2352. EntityRemoved(Actor, EntityId),
  2353. EntitySchemaSupportAdded(Actor, EntityId, SchemaId, SideEffects),
  2354. EntityPropertyValuesUpdated(Actor, EntityId, SideEffects),
  2355. VectorCleared(Actor, EntityId, PropertyId, SideEffects),
  2356. RemovedAtVectorIndex(Actor, EntityId, PropertyId, VecMaxLength, Nonce, SideEffect),
  2357. InsertedAtVectorIndex(Actor, EntityId, PropertyId, VecMaxLength, Nonce, SideEffect),
  2358. EntityOwnershipTransfered(EntityId, EntityController, SideEffects),
  2359. TransactionCompleted(Actor),
  2360. }
  2361. );