dpp/data_contract/config/v1/
mod.rs

1use crate::data_contract::config;
2use crate::data_contract::config::v0::{DataContractConfigGettersV0, DataContractConfigSettersV0};
3use crate::data_contract::config::{
4    DataContractConfig, DEFAULT_CONTRACT_CAN_BE_DELETED, DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED,
5    DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY, DEFAULT_CONTRACT_DOCUMENT_MUTABILITY,
6    DEFAULT_CONTRACT_KEEPS_HISTORY, DEFAULT_CONTRACT_MUTABILITY, DEFAULT_SIZED_INTEGER_TYPES,
7};
8use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements;
9#[cfg(feature = "json-conversion")]
10use crate::serialization::json_safe_fields;
11use crate::ProtocolError;
12use bincode::{Decode, Encode};
13use platform_value::btreemap_extensions::BTreeValueMapHelper;
14use platform_value::Value;
15use serde::{Deserialize, Serialize};
16use std::collections::BTreeMap;
17
18#[cfg_attr(feature = "json-conversion", json_safe_fields)]
19#[derive(Serialize, Deserialize, Decode, Encode, Debug, Clone, Copy, PartialEq, Eq)]
20#[serde(rename_all = "camelCase", default)]
21pub struct DataContractConfigV1 {
22    /// Can the contract ever be deleted. If the contract is deleted, so should be all
23    /// documents associated with it. TODO: There should also be a way to "stop" the contract -
24    /// contract and documents are kept in the system, but no new documents can be added to it
25    pub can_be_deleted: bool,
26    /// Is the contract mutable. Means that the document definitions can be changed or new
27    /// document definitions can be added to the contract
28    pub readonly: bool,
29    /// Does the contract keep history when the contract itself changes
30    pub keeps_history: bool,
31    /// Do documents in the contract keep history. This is a default for all documents in
32    /// the contract, but can be overridden by the document itself
33    pub documents_keep_history_contract_default: bool,
34    /// Are documents in the contract mutable? This specifies whether the documents can be
35    /// changed. This is a default for all document types in the contract, but can be
36    /// overridden by the document type config.
37    pub documents_mutable_contract_default: bool,
38    /// Can documents in the contract be deleted? This specifies whether the documents can be
39    /// deleted. This is a default for all document types in the contract, but can be
40    /// overridden by the document types itself.
41    pub documents_can_be_deleted_contract_default: bool,
42    /// Encryption key storage requirements
43    pub requires_identity_encryption_bounded_key: Option<StorageKeyRequirements>,
44    /// Decryption key storage requirements
45    pub requires_identity_decryption_bounded_key: Option<StorageKeyRequirements>,
46    /// Use sized integer Rust types for `integer` property type based on validation rules
47    pub sized_integer_types: bool,
48}
49
50/// Trait representing getters for `DataContractConfigV1`
51pub trait DataContractConfigGettersV1: DataContractConfigGettersV0 {
52    /// Use sized integer Rust types for `integer` property type based on validation rules
53    fn sized_integer_types(&self) -> bool;
54}
55
56/// Trait representing setters for `DataContractConfigV1`
57pub trait DataContractConfigSettersV1: DataContractConfigSettersV0 {
58    /// Enable/disable sized integer Rust types for `integer` property type
59    fn set_sized_integer_types_enabled(&mut self, enable: bool);
60}
61
62impl Default for DataContractConfigV1 {
63    fn default() -> Self {
64        DataContractConfigV1 {
65            can_be_deleted: DEFAULT_CONTRACT_CAN_BE_DELETED,
66            readonly: !DEFAULT_CONTRACT_MUTABILITY,
67            keeps_history: DEFAULT_CONTRACT_KEEPS_HISTORY,
68            documents_keep_history_contract_default: DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY,
69            documents_mutable_contract_default: DEFAULT_CONTRACT_DOCUMENT_MUTABILITY,
70            documents_can_be_deleted_contract_default: DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED,
71            requires_identity_encryption_bounded_key: None,
72            requires_identity_decryption_bounded_key: None,
73            sized_integer_types: true,
74        }
75    }
76}
77
78impl DataContractConfigV1 {
79    pub fn from_value(value: Value) -> Result<Self, ProtocolError> {
80        platform_value::from_value(value).map_err(ProtocolError::ValueError)
81    }
82
83    pub fn default_with_version() -> DataContractConfig {
84        Self::default().into()
85    }
86}
87
88impl DataContractConfigV1 {
89    /// Retrieve contract configuration properties.
90    ///
91    /// This method takes a BTreeMap representing a contract and retrieves
92    /// the configuration properties based on the values found in the map.
93    ///
94    /// The process of retrieving contract configuration properties is versioned,
95    /// and the version is determined by the platform version parameter.
96    /// If the version is not supported, an error is returned.
97    ///
98    /// # Parameters
99    ///
100    /// * `contract`: BTreeMap representing the contract.
101    /// * `platform_version`: The platform version being used.
102    ///
103    /// # Returns
104    ///
105    /// * `Result<ContractConfig, ProtocolError>`: On success, a ContractConfig.
106    ///   On failure, a ProtocolError.
107    #[inline(always)]
108    pub(super) fn get_contract_configuration_properties_v1(
109        contract: &BTreeMap<String, Value>,
110    ) -> Result<DataContractConfigV1, ProtocolError> {
111        let keeps_history = contract
112            .get_optional_bool(config::property::KEEPS_HISTORY)?
113            .unwrap_or(DEFAULT_CONTRACT_KEEPS_HISTORY);
114        let can_be_deleted = contract
115            .get_optional_bool(config::property::CAN_BE_DELETED)?
116            .unwrap_or(DEFAULT_CONTRACT_CAN_BE_DELETED);
117
118        let readonly = contract
119            .get_optional_bool(config::property::READONLY)?
120            .unwrap_or(!DEFAULT_CONTRACT_MUTABILITY);
121
122        let documents_keep_history_contract_default = contract
123            .get_optional_bool(config::property::DOCUMENTS_KEEP_HISTORY_CONTRACT_DEFAULT)?
124            .unwrap_or(DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY);
125
126        let documents_mutable_contract_default = contract
127            .get_optional_bool(config::property::DOCUMENTS_MUTABLE_CONTRACT_DEFAULT)?
128            .unwrap_or(DEFAULT_CONTRACT_DOCUMENT_MUTABILITY);
129
130        let documents_can_be_deleted_contract_default = contract
131            .get_optional_bool(config::property::DOCUMENTS_CAN_BE_DELETED_CONTRACT_DEFAULT)?
132            .unwrap_or(DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED);
133
134        let requires_identity_encryption_bounded_key = contract
135            .get_optional_integer::<u8>(config::property::REQUIRES_IDENTITY_ENCRYPTION_BOUNDED_KEY)?
136            .map(|int| int.try_into())
137            .transpose()?;
138
139        let requires_identity_decryption_bounded_key = contract
140            .get_optional_integer::<u8>(config::property::REQUIRES_IDENTITY_DECRYPTION_BOUNDED_KEY)?
141            .map(|int| int.try_into())
142            .transpose()?;
143
144        let sized_integer_types = contract
145            .get_optional_bool(config::property::SIZED_INTEGER_TYPES)?
146            .unwrap_or(DEFAULT_SIZED_INTEGER_TYPES);
147
148        Ok(DataContractConfigV1 {
149            can_be_deleted,
150            readonly,
151            keeps_history,
152            documents_keep_history_contract_default,
153            documents_mutable_contract_default,
154            documents_can_be_deleted_contract_default,
155            requires_identity_encryption_bounded_key,
156            requires_identity_decryption_bounded_key,
157            sized_integer_types,
158        })
159    }
160}