dpp/data_contract/config/
mod.rs1mod fields;
2mod methods;
3pub mod v0;
4pub mod v1;
5
6use crate::data_contract::config::v1::{
7 DataContractConfigGettersV1, DataContractConfigSettersV1, DataContractConfigV1,
8};
9use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements;
10#[cfg(feature = "json-conversion")]
11use crate::serialization::JsonConvertible;
12use crate::version::PlatformVersion;
13use crate::ProtocolError;
14use bincode::{Decode, Encode};
15use derive_more::From;
16pub use fields::*;
17use platform_value::Value;
18use serde::{Deserialize, Serialize};
19use std::collections::BTreeMap;
20use v0::{DataContractConfigGettersV0, DataContractConfigSettersV0, DataContractConfigV0};
21
22#[cfg_attr(feature = "json-conversion", derive(JsonConvertible))]
23#[derive(Serialize, Deserialize, Encode, Decode, Debug, Clone, Copy, PartialEq, Eq, From)]
24#[serde(tag = "$formatVersion")]
25pub enum DataContractConfig {
26 #[serde(rename = "0")]
27 V0(DataContractConfigV0),
28 #[serde(rename = "1")]
29 V1(DataContractConfigV1),
30}
31
32impl DataContractConfig {
33 pub fn version(&self) -> u16 {
34 match self {
35 DataContractConfig::V0(_) => 0,
36 DataContractConfig::V1(_) => 1,
37 }
38 }
39
40 pub fn default_for_version(
41 platform_version: &PlatformVersion,
42 ) -> Result<DataContractConfig, ProtocolError> {
43 match platform_version
44 .dpp
45 .contract_versions
46 .config
47 .default_current_version
48 {
49 0 => Ok(DataContractConfigV0::default().into()),
50 1 => Ok(DataContractConfigV1::default().into()),
51 version => Err(ProtocolError::UnknownVersionMismatch {
52 method: "DataContractConfig::default_for_version".to_string(),
53 known_versions: vec![0, 1],
54 received: version,
55 }),
56 }
57 }
58
59 pub fn config_valid_for_platform_version(
64 self,
65 platform_version: &PlatformVersion,
66 ) -> DataContractConfig {
67 match self {
68 DataContractConfig::V0(v0) => DataContractConfig::V0(v0),
69 DataContractConfig::V1(v1) => {
70 if platform_version.dpp.contract_versions.config.max_version == 0 {
71 DataContractConfig::V0(v1.into())
72 } else {
73 self
74 }
75 }
76 }
77 }
78
79 pub fn from_value(
80 value: Value,
81 platform_version: &PlatformVersion,
82 ) -> Result<DataContractConfig, ProtocolError> {
83 match platform_version
84 .dpp
85 .contract_versions
86 .config
87 .default_current_version
88 {
89 0 => {
90 let config: DataContractConfigV0 = platform_value::from_value(value)?;
91 Ok(config.into())
92 }
93 1 => {
94 let config: DataContractConfigV1 = platform_value::from_value(value)?;
95 Ok(config.into())
96 }
97 version => Err(ProtocolError::UnknownVersionMismatch {
98 method: "DataContractConfig::from_value".to_string(),
99 known_versions: vec![0, 1],
100 received: version,
101 }),
102 }
103 }
104
105 pub(in crate::data_contract) fn get_contract_configuration_properties(
125 contract: &BTreeMap<String, Value>,
126 platform_version: &PlatformVersion,
127 ) -> Result<DataContractConfig, ProtocolError> {
128 match platform_version
129 .dpp
130 .contract_versions
131 .config
132 .default_current_version
133 {
134 0 => Ok(
135 DataContractConfigV0::get_contract_configuration_properties_v0(contract)?.into(),
136 ),
137 1 => Ok(
138 DataContractConfigV1::get_contract_configuration_properties_v1(contract)?.into(),
139 ),
140 version => Err(ProtocolError::UnknownVersionMismatch {
141 method: "DataContractConfig::get_contract_configuration_properties".to_string(),
142 known_versions: vec![0, 1],
143 received: version,
144 }),
145 }
146 }
147}
148
149impl DataContractConfigGettersV0 for DataContractConfig {
150 fn can_be_deleted(&self) -> bool {
151 match self {
152 DataContractConfig::V0(v0) => v0.can_be_deleted,
153 DataContractConfig::V1(v1) => v1.can_be_deleted,
154 }
155 }
156
157 fn readonly(&self) -> bool {
158 match self {
159 DataContractConfig::V0(v0) => v0.readonly,
160 DataContractConfig::V1(v1) => v1.readonly,
161 }
162 }
163
164 fn keeps_history(&self) -> bool {
165 match self {
166 DataContractConfig::V0(v0) => v0.keeps_history,
167 DataContractConfig::V1(v1) => v1.keeps_history,
168 }
169 }
170
171 fn documents_keep_history_contract_default(&self) -> bool {
172 match self {
173 DataContractConfig::V0(v0) => v0.documents_keep_history_contract_default,
174 DataContractConfig::V1(v1) => v1.documents_keep_history_contract_default,
175 }
176 }
177
178 fn documents_mutable_contract_default(&self) -> bool {
179 match self {
180 DataContractConfig::V0(v0) => v0.documents_mutable_contract_default,
181 DataContractConfig::V1(v1) => v1.documents_mutable_contract_default,
182 }
183 }
184
185 fn documents_can_be_deleted_contract_default(&self) -> bool {
186 match self {
187 DataContractConfig::V0(v0) => v0.documents_can_be_deleted_contract_default,
188 DataContractConfig::V1(v1) => v1.documents_can_be_deleted_contract_default,
189 }
190 }
191
192 fn requires_identity_encryption_bounded_key(&self) -> Option<StorageKeyRequirements> {
194 match self {
195 DataContractConfig::V0(v0) => v0.requires_identity_encryption_bounded_key,
196 DataContractConfig::V1(v1) => v1.requires_identity_encryption_bounded_key,
197 }
198 }
199
200 fn requires_identity_decryption_bounded_key(&self) -> Option<StorageKeyRequirements> {
202 match self {
203 DataContractConfig::V0(v0) => v0.requires_identity_decryption_bounded_key,
204 DataContractConfig::V1(v1) => v1.requires_identity_decryption_bounded_key,
205 }
206 }
207}
208
209impl DataContractConfigSettersV0 for DataContractConfig {
210 fn set_can_be_deleted(&mut self, value: bool) {
211 match self {
212 DataContractConfig::V0(v0) => v0.can_be_deleted = value,
213 DataContractConfig::V1(v1) => v1.can_be_deleted = value,
214 }
215 }
216
217 fn set_readonly(&mut self, value: bool) {
218 match self {
219 DataContractConfig::V0(v0) => v0.readonly = value,
220 DataContractConfig::V1(v1) => v1.readonly = value,
221 }
222 }
223
224 fn set_keeps_history(&mut self, value: bool) {
225 match self {
226 DataContractConfig::V0(v0) => v0.keeps_history = value,
227 DataContractConfig::V1(v1) => v1.keeps_history = value,
228 }
229 }
230
231 fn set_documents_keep_history_contract_default(&mut self, value: bool) {
232 match self {
233 DataContractConfig::V0(v0) => v0.documents_keep_history_contract_default = value,
234 DataContractConfig::V1(v1) => v1.documents_keep_history_contract_default = value,
235 }
236 }
237
238 fn set_documents_can_be_deleted_contract_default(&mut self, value: bool) {
239 match self {
240 DataContractConfig::V0(v0) => v0.documents_can_be_deleted_contract_default = value,
241 DataContractConfig::V1(v1) => v1.documents_can_be_deleted_contract_default = value,
242 }
243 }
244
245 fn set_documents_mutable_contract_default(&mut self, value: bool) {
246 match self {
247 DataContractConfig::V0(v0) => v0.documents_mutable_contract_default = value,
248 DataContractConfig::V1(v1) => v1.documents_mutable_contract_default = value,
249 }
250 }
251
252 fn set_requires_identity_encryption_bounded_key(
253 &mut self,
254 value: Option<StorageKeyRequirements>,
255 ) {
256 match self {
257 DataContractConfig::V0(v0) => v0.requires_identity_encryption_bounded_key = value,
258 DataContractConfig::V1(v1) => v1.requires_identity_encryption_bounded_key = value,
259 }
260 }
261
262 fn set_requires_identity_decryption_bounded_key(
263 &mut self,
264 value: Option<StorageKeyRequirements>,
265 ) {
266 match self {
267 DataContractConfig::V0(v0) => v0.requires_identity_decryption_bounded_key = value,
268 DataContractConfig::V1(v1) => v1.requires_identity_decryption_bounded_key = value,
269 }
270 }
271}
272
273impl DataContractConfigGettersV1 for DataContractConfig {
274 fn sized_integer_types(&self) -> bool {
275 match self {
276 DataContractConfig::V0(_) => false,
277 DataContractConfig::V1(v1) => v1.sized_integer_types,
278 }
279 }
280}
281
282impl DataContractConfigSettersV1 for DataContractConfig {
283 fn set_sized_integer_types_enabled(&mut self, enable: bool) {
284 match self {
285 DataContractConfig::V0(_) => {}
286 DataContractConfig::V1(v1) => v1.sized_integer_types = enable,
287 }
288 }
289}
290
291#[cfg(test)]
292mod tests {
293 use super::*;
294 use crate::data_contract::config::v0::DataContractConfigV0;
295 use crate::data_contract::config::v1::DataContractConfigV1;
296 use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements;
297 use platform_version::version::PlatformVersion;
298
299 mod default_for_version {
300 use super::*;
301
302 #[test]
303 fn default_for_latest_platform_version() {
304 let platform_version = PlatformVersion::latest();
305 let config = DataContractConfig::default_for_version(platform_version)
306 .expect("should create config for latest version");
307
308 let expected_version = platform_version
310 .dpp
311 .contract_versions
312 .config
313 .default_current_version;
314
315 assert_eq!(config.version(), expected_version as u16);
316 }
317
318 #[test]
319 fn default_for_first_platform_version() {
320 let platform_version = PlatformVersion::first();
321 let config = DataContractConfig::default_for_version(platform_version)
322 .expect("should create config for first version");
323
324 let expected_version = platform_version
325 .dpp
326 .contract_versions
327 .config
328 .default_current_version;
329
330 assert_eq!(config.version(), expected_version as u16);
331 }
332 }
333
334 mod version_method {
335 use super::*;
336
337 #[test]
338 fn v0_reports_version_0() {
339 let config = DataContractConfig::V0(DataContractConfigV0::default());
340 assert_eq!(config.version(), 0);
341 }
342
343 #[test]
344 fn v1_reports_version_1() {
345 let config = DataContractConfig::V1(DataContractConfigV1::default());
346 assert_eq!(config.version(), 1);
347 }
348 }
349
350 mod from_conversions {
351 use super::*;
352
353 #[test]
354 fn v0_into_config() {
355 let v0 = DataContractConfigV0::default();
356 let config: DataContractConfig = v0.into();
357 assert_eq!(config.version(), 0);
358 }
359
360 #[test]
361 fn v1_into_config() {
362 let v1 = DataContractConfigV1::default();
363 let config: DataContractConfig = v1.into();
364 assert_eq!(config.version(), 1);
365 }
366
367 #[test]
368 fn v1_to_v0_conversion_preserves_fields() {
369 let v1 = DataContractConfigV1 {
370 can_be_deleted: true,
371 readonly: true,
372 keeps_history: true,
373 documents_keep_history_contract_default: true,
374 documents_mutable_contract_default: false,
375 documents_can_be_deleted_contract_default: false,
376 requires_identity_encryption_bounded_key: None,
377 requires_identity_decryption_bounded_key: None,
378 sized_integer_types: true,
379 };
380 let v0: DataContractConfigV0 = v1.into();
381 assert!(v0.can_be_deleted);
382 assert!(v0.readonly);
383 assert!(v0.keeps_history);
384 assert!(v0.documents_keep_history_contract_default);
385 assert!(!v0.documents_mutable_contract_default);
386 assert!(!v0.documents_can_be_deleted_contract_default);
387 }
388 }
389
390 mod getters_v0 {
391 use super::*;
392
393 #[test]
394 fn default_v0_getter_values() {
395 let config = DataContractConfig::V0(DataContractConfigV0::default());
396 assert_eq!(config.can_be_deleted(), DEFAULT_CONTRACT_CAN_BE_DELETED);
397 assert_eq!(config.readonly(), !DEFAULT_CONTRACT_MUTABILITY);
398 assert_eq!(config.keeps_history(), DEFAULT_CONTRACT_KEEPS_HISTORY);
399 assert_eq!(
400 config.documents_keep_history_contract_default(),
401 DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY
402 );
403 assert_eq!(
404 config.documents_mutable_contract_default(),
405 DEFAULT_CONTRACT_DOCUMENT_MUTABILITY
406 );
407 assert_eq!(
408 config.documents_can_be_deleted_contract_default(),
409 DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED
410 );
411 assert!(config.requires_identity_encryption_bounded_key().is_none());
412 assert!(config.requires_identity_decryption_bounded_key().is_none());
413 }
414
415 #[test]
416 fn default_v1_getter_values() {
417 let config = DataContractConfig::V1(DataContractConfigV1::default());
418 assert_eq!(config.can_be_deleted(), DEFAULT_CONTRACT_CAN_BE_DELETED);
419 assert_eq!(config.readonly(), !DEFAULT_CONTRACT_MUTABILITY);
420 assert_eq!(config.keeps_history(), DEFAULT_CONTRACT_KEEPS_HISTORY);
421 assert_eq!(
422 config.documents_keep_history_contract_default(),
423 DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY
424 );
425 assert_eq!(
426 config.documents_mutable_contract_default(),
427 DEFAULT_CONTRACT_DOCUMENT_MUTABILITY
428 );
429 assert_eq!(
430 config.documents_can_be_deleted_contract_default(),
431 DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED
432 );
433 }
434 }
435
436 mod setters_v0 {
437 use super::*;
438
439 #[test]
440 fn set_can_be_deleted_on_v0() {
441 let mut config = DataContractConfig::V0(DataContractConfigV0::default());
442 config.set_can_be_deleted(true);
443 assert!(config.can_be_deleted());
444 config.set_can_be_deleted(false);
445 assert!(!config.can_be_deleted());
446 }
447
448 #[test]
449 fn set_readonly_on_v1() {
450 let mut config = DataContractConfig::V1(DataContractConfigV1::default());
451 config.set_readonly(true);
452 assert!(config.readonly());
453 config.set_readonly(false);
454 assert!(!config.readonly());
455 }
456
457 #[test]
458 fn set_keeps_history() {
459 let mut config = DataContractConfig::V0(DataContractConfigV0::default());
460 config.set_keeps_history(true);
461 assert!(config.keeps_history());
462 }
463
464 #[test]
465 fn set_documents_keep_history() {
466 let mut config = DataContractConfig::V1(DataContractConfigV1::default());
467 config.set_documents_keep_history_contract_default(true);
468 assert!(config.documents_keep_history_contract_default());
469 }
470
471 #[test]
472 fn set_documents_mutable() {
473 let mut config = DataContractConfig::V0(DataContractConfigV0::default());
474 config.set_documents_mutable_contract_default(false);
475 assert!(!config.documents_mutable_contract_default());
476 }
477
478 #[test]
479 fn set_documents_can_be_deleted() {
480 let mut config = DataContractConfig::V1(DataContractConfigV1::default());
481 config.set_documents_can_be_deleted_contract_default(false);
482 assert!(!config.documents_can_be_deleted_contract_default());
483 }
484
485 #[test]
486 fn set_encryption_key_requirements() {
487 let mut config = DataContractConfig::V0(DataContractConfigV0::default());
488 config
489 .set_requires_identity_encryption_bounded_key(Some(StorageKeyRequirements::Unique));
490 assert_eq!(
491 config.requires_identity_encryption_bounded_key(),
492 Some(StorageKeyRequirements::Unique)
493 );
494 }
495
496 #[test]
497 fn set_decryption_key_requirements() {
498 let mut config = DataContractConfig::V1(DataContractConfigV1::default());
499 config
500 .set_requires_identity_decryption_bounded_key(Some(StorageKeyRequirements::Unique));
501 assert_eq!(
502 config.requires_identity_decryption_bounded_key(),
503 Some(StorageKeyRequirements::Unique)
504 );
505 }
506 }
507
508 mod getters_setters_v1 {
509 use super::*;
510
511 #[test]
512 fn sized_integer_types_default_v1() {
513 let config = DataContractConfig::V1(DataContractConfigV1::default());
514 assert!(config.sized_integer_types());
516 }
517
518 #[test]
519 fn sized_integer_types_v0_always_false() {
520 let config = DataContractConfig::V0(DataContractConfigV0::default());
521 assert!(!config.sized_integer_types());
522 }
523
524 #[test]
525 fn set_sized_integer_types_on_v1() {
526 let mut config = DataContractConfig::V1(DataContractConfigV1::default());
527 config.set_sized_integer_types_enabled(false);
528 assert!(!config.sized_integer_types());
529 config.set_sized_integer_types_enabled(true);
530 assert!(config.sized_integer_types());
531 }
532
533 #[test]
534 fn set_sized_integer_types_on_v0_is_noop() {
535 let mut config = DataContractConfig::V0(DataContractConfigV0::default());
536 config.set_sized_integer_types_enabled(true);
537 assert!(!config.sized_integer_types());
539 }
540 }
541
542 mod config_valid_for_platform_version {
543 use super::*;
544
545 #[test]
546 fn v0_stays_v0_regardless_of_platform() {
547 let config = DataContractConfig::V0(DataContractConfigV0::default());
548 let result = config.config_valid_for_platform_version(PlatformVersion::latest());
549 assert_eq!(result.version(), 0);
550 }
551
552 #[test]
553 fn v1_downgraded_to_v0_when_max_version_is_0() {
554 let config = DataContractConfig::V1(DataContractConfigV1 {
555 can_be_deleted: true,
556 readonly: false,
557 keeps_history: true,
558 documents_keep_history_contract_default: false,
559 documents_mutable_contract_default: true,
560 documents_can_be_deleted_contract_default: true,
561 requires_identity_encryption_bounded_key: None,
562 requires_identity_decryption_bounded_key: None,
563 sized_integer_types: true,
564 });
565
566 let platform_version = PlatformVersion::first();
568 if platform_version.dpp.contract_versions.config.max_version == 0 {
569 let result = config.config_valid_for_platform_version(platform_version);
570 assert_eq!(result.version(), 0);
571 assert!(result.can_be_deleted());
573 }
574 }
575
576 #[test]
577 fn v1_stays_v1_when_max_version_is_1_or_higher() {
578 let config = DataContractConfig::V1(DataContractConfigV1::default());
579 let platform_version = PlatformVersion::latest();
580 if platform_version.dpp.contract_versions.config.max_version >= 1 {
581 let result = config.config_valid_for_platform_version(platform_version);
582 assert_eq!(result.version(), 1);
583 }
584 }
585 }
586}