Skip to main content

dpp/data_contract/config/v0/
mod.rs

1use crate::data_contract::config;
2use crate::data_contract::config::v1::DataContractConfigV1;
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,
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 DataContractConfigV0 {
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}
47
48/// Trait representing getters for `DataContractConfigV0`
49pub trait DataContractConfigGettersV0 {
50    /// Returns whether the contract can be deleted.
51    fn can_be_deleted(&self) -> bool;
52
53    /// Returns whether the contract is read-only.
54    fn readonly(&self) -> bool;
55
56    /// Returns whether the contract keeps history.
57    fn keeps_history(&self) -> bool;
58
59    /// Returns whether documents in the contract keep history by default.
60    fn documents_keep_history_contract_default(&self) -> bool;
61
62    /// Returns whether documents in the contract are mutable by default.
63    fn documents_mutable_contract_default(&self) -> bool;
64    fn documents_can_be_deleted_contract_default(&self) -> bool;
65
66    /// Encryption key storage requirements
67    fn requires_identity_encryption_bounded_key(&self) -> Option<StorageKeyRequirements>;
68
69    /// Decryption key storage requirements
70    fn requires_identity_decryption_bounded_key(&self) -> Option<StorageKeyRequirements>;
71}
72
73/// Trait representing setters for `DataContractConfigV0`
74pub trait DataContractConfigSettersV0 {
75    /// Sets whether the contract can be deleted.
76    fn set_can_be_deleted(&mut self, value: bool);
77
78    /// Sets whether the contract is read-only.
79    fn set_readonly(&mut self, value: bool);
80
81    /// Sets whether the contract keeps history.
82    fn set_keeps_history(&mut self, value: bool);
83
84    /// Sets whether documents in the contract keep history by default.
85    fn set_documents_keep_history_contract_default(&mut self, value: bool);
86
87    /// Sets whether documents in the contract are mutable by default.
88    fn set_documents_mutable_contract_default(&mut self, value: bool);
89
90    /// Sets whether documents in the contract can be deleted by default.
91    fn set_documents_can_be_deleted_contract_default(&mut self, value: bool);
92
93    /// Sets Encryption key storage requirements.
94    fn set_requires_identity_encryption_bounded_key(
95        &mut self,
96        value: Option<StorageKeyRequirements>,
97    );
98
99    /// Sets Decryption key storage requirements.
100    fn set_requires_identity_decryption_bounded_key(
101        &mut self,
102        value: Option<StorageKeyRequirements>,
103    );
104}
105
106impl Default for DataContractConfigV0 {
107    fn default() -> Self {
108        DataContractConfigV0 {
109            can_be_deleted: DEFAULT_CONTRACT_CAN_BE_DELETED,
110            readonly: !DEFAULT_CONTRACT_MUTABILITY,
111            keeps_history: DEFAULT_CONTRACT_KEEPS_HISTORY,
112            documents_keep_history_contract_default: DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY,
113            documents_mutable_contract_default: DEFAULT_CONTRACT_DOCUMENT_MUTABILITY,
114            documents_can_be_deleted_contract_default: DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED,
115            requires_identity_encryption_bounded_key: None,
116            requires_identity_decryption_bounded_key: None,
117        }
118    }
119}
120
121impl DataContractConfigV0 {
122    pub fn default_with_version() -> DataContractConfig {
123        Self::default().into()
124    }
125}
126
127impl DataContractConfigV0 {
128    /// Retrieve contract configuration properties.
129    ///
130    /// This method takes a BTreeMap representing a contract and retrieves
131    /// the configuration properties based on the values found in the map.
132    ///
133    /// The process of retrieving contract configuration properties is versioned,
134    /// and the version is determined by the platform version parameter.
135    /// If the version is not supported, an error is returned.
136    ///
137    /// # Parameters
138    ///
139    /// * `contract`: BTreeMap representing the contract.
140    /// * `platform_version`: The platform version being used.
141    ///
142    /// # Returns
143    ///
144    /// * `Result<ContractConfig, ProtocolError>`: On success, a ContractConfig.
145    ///   On failure, a ProtocolError.
146    #[inline(always)]
147    pub(super) fn get_contract_configuration_properties_v0(
148        contract: &BTreeMap<String, Value>,
149    ) -> Result<DataContractConfigV0, ProtocolError> {
150        let keeps_history = contract
151            .get_optional_bool(config::property::KEEPS_HISTORY)?
152            .unwrap_or(DEFAULT_CONTRACT_KEEPS_HISTORY);
153        let can_be_deleted = contract
154            .get_optional_bool(config::property::CAN_BE_DELETED)?
155            .unwrap_or(DEFAULT_CONTRACT_CAN_BE_DELETED);
156
157        let readonly = contract
158            .get_optional_bool(config::property::READONLY)?
159            .unwrap_or(!DEFAULT_CONTRACT_MUTABILITY);
160
161        let documents_keep_history_contract_default = contract
162            .get_optional_bool(config::property::DOCUMENTS_KEEP_HISTORY_CONTRACT_DEFAULT)?
163            .unwrap_or(DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY);
164
165        let documents_mutable_contract_default = contract
166            .get_optional_bool(config::property::DOCUMENTS_MUTABLE_CONTRACT_DEFAULT)?
167            .unwrap_or(DEFAULT_CONTRACT_DOCUMENT_MUTABILITY);
168
169        let documents_can_be_deleted_contract_default = contract
170            .get_optional_bool(config::property::DOCUMENTS_CAN_BE_DELETED_CONTRACT_DEFAULT)?
171            .unwrap_or(DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED);
172
173        let requires_identity_encryption_bounded_key = contract
174            .get_optional_integer::<u8>(config::property::REQUIRES_IDENTITY_ENCRYPTION_BOUNDED_KEY)?
175            .map(|int| int.try_into())
176            .transpose()?;
177
178        // CONSENSUS-FROZEN BUG: this intentionally reads from
179        // `REQUIRES_IDENTITY_ENCRYPTION_BOUNDED_KEY` (not the matching
180        // DECRYPTION constant). The V0 parser shipped this way and its output
181        // is part of V0 protocol behavior, so it must not be changed even
182        // though it looks like a copy-paste typo. V1 reads from the correct
183        // DECRYPTION key — see v1/mod.rs. Do not "fix" this line.
184        let requires_identity_decryption_bounded_key = contract
185            .get_optional_integer::<u8>(config::property::REQUIRES_IDENTITY_ENCRYPTION_BOUNDED_KEY)?
186            .map(|int| int.try_into())
187            .transpose()?;
188
189        Ok(DataContractConfigV0 {
190            can_be_deleted,
191            readonly,
192            keeps_history,
193            documents_keep_history_contract_default,
194            documents_mutable_contract_default,
195            documents_can_be_deleted_contract_default,
196            requires_identity_encryption_bounded_key,
197            requires_identity_decryption_bounded_key,
198        })
199    }
200}
201
202impl From<DataContractConfigV1> for DataContractConfigV0 {
203    fn from(value: DataContractConfigV1) -> Self {
204        DataContractConfigV0 {
205            can_be_deleted: value.can_be_deleted,
206            readonly: value.readonly,
207            keeps_history: value.keeps_history,
208            documents_keep_history_contract_default: value.documents_keep_history_contract_default,
209            documents_mutable_contract_default: value.documents_mutable_contract_default,
210            documents_can_be_deleted_contract_default: value
211                .documents_can_be_deleted_contract_default,
212            requires_identity_encryption_bounded_key: value
213                .requires_identity_encryption_bounded_key,
214            requires_identity_decryption_bounded_key: value
215                .requires_identity_decryption_bounded_key,
216        }
217    }
218}